k8s中controller-runtime并发Reconcile分析
§ 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个关键数据结构。
- queue 队列,用来添加新对象。
- dirty hashset 记录 dirty 的对象集合。一个对象被取出处理时,如果又收到新的对象时,它就是 dirty 的,需要两次处理。 Add 时加入, Done 时取出,重新放回 queue 中。
- 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,同一个进程中,不会有多个协程同时处理一个对象。
详细如下:
- 正在处于中的对象,Add 调用不会入队,只记录在 dirty 中。
- 对象处于完成后,在 Done 调用时检查,如在 dirty 中,再次入队,开始下一轮的处理。保证不丢事件。
这种设计核心思想是,用 map 对事件进行合并;使用队列保证顺序。
k8s中controller-runtime并发Reconcile分析的更多相关文章
- K8s中Pod健康检查源代码分析
了解k8s中的Liveness和Readiness Liveness: 表明是否容器正在运行.如果liveness探测为fail,则kubelet会kill掉容器,并且会触发restart设置的策略. ...
- SpringMVC中 Controller的 @ResponseBody注解分析
需求分析:需要 利用 out 对象返回给财付通是否接收成功 .那么将需要如下代码: /** * 返回处理结果给财付通服务器. * @param msg: Success or fail. * @ ...
- k8s deployment controller源码分析
deployment controller简介 deployment controller是kube-controller-manager组件中众多控制器中的一个,是 deployment 资源对象的 ...
- k8s replicaset controller分析(2)-核心处理逻辑分析
replicaset controller分析 replicaset controller简介 replicaset controller是kube-controller-manager组件中众多控制 ...
- 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
目录 前言 现象 源码分析 HandlerMethodArgumentResolver与HandlerMethodReturnValueHandler接口介绍 HandlerMethodArgumen ...
- 【MVC - 参数原理】详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/spring ...
- k8s replicaset controller分析(1)-初始化与启动分析
replicaset controller分析 replicaset controller简介 replicaset controller是kube-controller-manager组件中众多控制 ...
- k8s replicaset controller 分析(3)-expectations 机制分析
replicaset controller分析 replicaset controller简介 replicaset controller是kube-controller-manager组件中众多控制 ...
- k8s endpoints controller分析
k8s endpoints controller分析 endpoints controller简介 endpoints controller是kube-controller-manager组件中众多控 ...
- k8s client-go源码分析 informer源码分析(5)-Controller&Processor源码分析
client-go之Controller&Processor源码分析 1.controller与Processor概述 Controller Controller从DeltaFIFO中pop ...
随机推荐
- hive第二课:Hive3.1.2分区与排序以及分桶(内置函数)
Hive3.1.2分区与排序(内置函数) 1.Hive分区(十分重要!!) 分区的目的:避免全表扫描,加快查询速度! 在大数据中,最常见的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件 ...
- 面试官:transient关键字修饰的变量当真不可序列化?我:烦请先生教我!
一.写在开头 在这篇文章中记录一下之前自己面试时学到的东西,是关于transient关键字的,当时面试官问我IO的相关问题,基本上全答出来了,关于如何不序列化对象中某个字段时,我果断的选择了stati ...
- PHP转Go系列 | GET 和 POST 请求的使用姿势
大家好,我是码农先森. 说到 HTTP 请求工具想必对我们做 Web 开发的程序员都不陌生,只要涉及到网络请求都必须使用.对于我们 PHP 程序员来说,最熟悉不过的就是 CURL 扩展,只要安装的这个 ...
- Linux系统基本介绍
一.Linux系统基本介绍 [1].Linux操作系统特点 多任务的操作系统 多任务操作系统 严格区分大小写 Linux一切皆文件 所有文件的起点都是"/"根目录 对于Linux操 ...
- 【Python】用Python把从mysql统计的结果数据转成表格形式的图片并推送到钉钉群
** python把数据转为图片 / python推送图片到钉钉群 ** 需求:通过python访问mysql数据库,统计业务相关数据.把统计的结果数据生成表格形式的图片并发送到钉钉群里. 一:Cen ...
- SpringBoot 处理xss攻击
添加依赖 <!-- xss跨站脚本攻击 --> <dependency> <groupId>net.dreamlu</groupId> <arti ...
- sora未来在哪里,是否改变世界?
什么是Sora?(Solo 社区投稿) Sora在日语中是天空的意思,是一种文本到视频的扩散模型,Sora与使用文本提示创建图像的 Dall-E 非常相似,Sora 使用文本提示创建短视频.Sora ...
- UE Spline 样条网格体组件添加碰撞
最近做的一个功能是通过Spline 生成管道模型. 如下图所示: 遇到的一个问题是需要给生成的管路加上碰撞.其中需要两个重要的步骤: 设置SplineMeshComponent的碰撞预设 找到&quo ...
- 暑假Java自学每日进度总结1
今日所学: 一.常用的cmd命令: 1>盘符: 2>dir(显示当前文件所有目录) 3>cd 目录(打开该目录) 4>cd..(回到上一目录) 5>cd(回到当前盘符初始 ...
- 单细胞测序最好的教程(八): 细胞类型自动注释-1|基于marker的自动注释
作者按 本章节主要讲解了基于marker的自动注释方法,一般来说,我会先自动注释,再手动去确认marker,这是因为,对于一个陌生的组织,我对marker是不了解的,自动注释可以帮助我快速熟悉细胞类型 ...