首页 > 其他分享 >k8s中controller-runtime并发Reconcile分析

k8s中controller-runtime并发Reconcile分析

时间:2024-01-24 09:04:08浏览次数:42  
标签:Reconcile 对象 并发 controller dirty runtime struct

§ 0x01 起因

开发控制器时,团队内一直在讨论是否需要为单个控制器对象添加并发控制(即加锁),最终把 controller-runtime 框架中并发数改为1,同时启用了 k8s 的 leader election机制保证只有单实例来规避并发的可能。

这种做法其实是有问题的,没有搞清楚 controller-runtime 框架本身是什么样的行为,强行把并发限制为1,可能导致性能上不去。

刚好在使用 cluster-api 过程中又遇到另外一个问题,某个 cluster 对象的 Reconcile 过程死锁阻塞了,导致这个对象后续都不再有 Reconcie 日志产生,而且注意到 cluster-api 的默认并发数是10。这两个问题的解答都需要对 controller-runtime 的行为进行梳理。

一般情况下直接看 controller-runtime 的文档就能明白了,不过在看过 https://github.com/kubernetes-sigs/controller-runtime/blob/main/pkg/reconcile/reconcile.go 中的文档,对 Reconcile 的解释,并没有强调同一个对象的并发 Reconcie 行为:是不会并发,还是会有并发?没有体现。没办法只能看代码了。

§ 0x02 无奈地去看源码

最终的关键逻辑在 k8s.io/client-go/util/workqueue/queue.go 中。

Type 对象中有3个关键数据结构。

  1. queue 队列,用来添加新对象。
  2. dirty hashset 记录 dirty 的对象集合。一个对象被取出处理时,如果又收到新的对象时,它就是 dirty 的,需要两次处理。 Add 时加入, Done 时取出,重新放回 queue 中。
  3. processing hashset 正在处理的对象集合。 Get 获取对象时放入,Done 调用时取出。

对应的数据流转图如下:

以上 hashset 的定义如下:

type empty struct{}
type t interface{}
type set map[t]empty

它是一个以泛型为 key 的map 。结合 controller-runtime,它存放的对象类型是 Request,定义如下:

type Request struct {
	// NamespacedName is the name and namespace of the object to reconcile.
	types.NamespacedName
}

而 types.NamespacedName 是个包含 Namepsace 和 Name 的 struct 类型。

通过分析 Type 类型的 Add 方法,可以解释一个对象 A 正在被 Reconcile 过程中,又有一个事件触发时, controller-runtime 的行为。

Add 上述场景会把对象放在 dirty 集合中,判断已在 processing 集群中则返回。所以解释这个问题的关键在于,set 类型中是是否存在某个元素是如何判断的,即 Request 对象对应的 struct 类型是如何在 map 中取 hash 的。

这种验证比较简单,直说结论:struct 类型是逐个对象迭代计算出的 hash 值,所以同一个对象转换得到的 Request 对象取值是一样的,最终对应的 hash 值 也是一样的。

§ 0x03 结论

即便控制器的并发数不为1,同一个进程中,不会有多个协程同时处理一个对象。

详细如下:

  1. 正在处于中的对象,Add 调用不会入队,只记录在 dirty 中。
  2. 对象处于完成后,在 Done 调用时检查,如在 dirty 中,再次入队,开始下一轮的处理。保证不丢事件。

这种设计核心思想是,用 map 对事件进行合并;使用队列保证顺序。

标签:Reconcile,对象,并发,controller,dirty,runtime,struct
From: https://www.cnblogs.com/linlinsite/p/17983814

相关文章

  • u盘安装出现No controller found
    https://www.cnblogs.com/snooker/articles/9259218.html RHEL7.4安装过程:1\用软碟通刻制U盘启动盘2\插入U盘到物理机(lenovors650服务器)3\配置riad后用U盘启动,出现以下报错信息: 这时只需耐心等待,等一会之后会不断的滚动错误警告,这个时候继续等待,那么一会就会出来......
  • onnxruntime输出模型中间层的结果
    defget_layer_output(model,image):ori_output=copy.deepcopy(model.graph.output)fornodeinmodel.graph.node:foroutputinnode.output:model.graph.output.extend([onnx.ValueInfoProto(......
  • ILRuntime是如何与Unity互相调用的
    ILRuntime是一个跨平台CLR实现,它可以在多个平台上运行C#代码,包括Android、iOS、Windows、Linux等等。ILRuntime的实现方式是将C#代码编译成IL代码,然后在运行时通过JIT或AOT的方式将IL代码转换为机器代码,从而实现跨平台的效果。ILRuntime的主要功能包括热更新、动态加载、代码加密......
  • Java中System类和Runtime类常用方法和属性
    ​ Java中,System类和Runtime类提供了一些关键的功能,用于与底层操作系统以及运行时环境进行交互。System类是Java标准库中的一个类,提供了对JVM的一些基本访问和控制方法。Runtime类实例封装了运行时环境。为Java程序提供了与底层系统交互的强大工具,但也需要谨慎使用以避免潜......
  • Nacos 2.3.0 正式版发布,Nacos Controller 项目开源
    作者:杨翊新版本发布Nacos2.3.0-BETA版本经过1个多月的社区测试,修复了部分的问题并对部分新功能的使用进行了少量优化后,于2023年12月7日正式发布。Nacos2.3.0版本基于 2.3.0-BETA 版本为基础,主要进行了如下更新:基于能力协商机制,支持通过Grpc的方式进行持久化服务实......
  • Nacos 2.3.0 正式版发布,Nacos Controller 项目开源
    作者:杨翊新版本发布Nacos2.3.0-BETA版本经过1个多月的社区测试,修复了部分的问题并对部分新功能的使用进行了少量优化后,于2023年12月7日正式发布。Nacos2.3.0版本基于 2.3.0-BETA 版本为基础,主要进行了如下更新:基于能力协商机制,支持通过Grpc的方式进行持久化......
  • 解决controller拿不到前端的参数
    如果在你的控制器(Controller)中无法获取前端传递的值,有几个常见的原因和解决方法:参数绑定错误:确保你的Controller方法的参数列表与前端传递的参数一致。使用@RequestParam、@PathVariable等注解来映射前端参数到方法的参数。@RestControllerpublicclassYourController{......
  • @RestControllerAdvice定义返回格式
    原文链接:如何优雅的写Controller层代码?一、拦截异常,封装返回值@RestControllerAdvicepublicclassControllerExceptionAdvice{@ExceptionHandler({BindException.class})publicResultVoMethodArgumentNotValidExceptionHandler(BindExceptione){/......
  • SpringMVC中@pathVariable 为spring的注解,都可以用在Controller 层接受前段传递的数据
    @PathVariable主要接收http://host:port/path{参数值}数据 @pathVariable作为借口是,url是http"//ww.yoodb.com/user/getUserById/2 @RequestParam主要用于接受http://host:port/path?参数名=值数据值 @ResquesrParam请求接口时,url是http://www.yoodb.com/user/getUsrBy......
  • 使用ChatGPT解决在Spring AOP中@Pointcut中的execution如何指定Controller的所有方法
    背景使用ChatGPT解决工作中遇到的问题,https://xinghuo.xfyun.cn/desk切指定类在SpringAOP中,@Pointcut注解用于定义切点表达式,而execution属性用于指定切点表达式的具体匹配规则。要指定Controller的所有方法,可以使用以下方法:使用类名和方法名进行精确匹配。例如,如果要匹配名......