K8s 的控制循环
Kubernetes 运行 Pod 的核心逻辑就是基于 Informer 机制的控制循环(Control Loop)。每当 etcd 中的数据有更新,会触发相应的事件通知给各个 Controller,Controller 会根据这些事件来决定是否需要对集群状态进行调整,逻辑如下:

| |
各类资源都有相应的控制器 Controller 来实现这个控制循环,比如管理节点资源的 NodeController,管理 Deployment 的 DeploymentController。kube-controller-manager 的主要职责就是启动和管理这些 Controller,所管理的 Controller 列表位于 controller names。
kube-controller-manager 启动流程
kube-controller-manager 的启动方法是位于 controller-manager.go 文件的 Run 方法,核心代码如下:
| |
除了初始化和选主操作外,Controller 的启动流程都在内部的 run 方法中执行,我们来看下这个方法的具体实现。
Controller 创建启动流程
初始化 Controller 描述符
在运行 run 方法前,代码里先执行了 NewControllerDescriptors() 方法创建 ControllerDescriptors,即控制器描述符。
| |
每种 Controller 都有一个 ControllerDescriptor 描述符,描述符中包含了 Controller 的名称、初始化函数等信息。下面是我们常见的 Deployment Controller 的描述符信息。
| |
NewControllerDescriptors() 方法内部会定义一个 register() 注册函数,然后执行一系列的注册,最终会生成一个 Controller 名称到描述 map[string]*ControllerDescriptor 的映射表。
| |
创建 ControllerContext
创建完描述后,就会进入 run 方法启动所有 Controller 了,这里第一步就是调用 CreateControllerContext 方法创建ControllerContext(控制器上下文)。这是一个结构体,包含了控制器运行所需的所有上下文信息,包括 Kubernetes 客户端、Informer 工厂等,ControllerContext 会被传递给各个控制器,以便它们能够访问共享的资源和服务。
| |
创建控制器:run()->StartControllers()
控制器运行所需的上下文准备好后,就会调用 StartControllers 方法启动所有 Controller。
| |
其核心流程是遍历创建好的控制器描述符集合,然后调用 StartController 方法创建并启动具体的 Controller。
| |
该函数的流程为:
- 检查 FeatureGate 是否开启:检查 Controller 是否需要通过 FeatureGate 开启,如果未开启,则跳过该 Controller。
- 检查是否为云提供商 Controller:如果是云提供商的 Controller,则跳过该 Controller。
- 检查 Controller 是否启用:如果 Controller 未启用,则跳过该 Controller。
- 短暂等待:调用
time.sleep()短暂等待,防止 Controller 启动过快对 kube-apiserver 造成压力。 - 启动 Controller:调用 Controller 的 initFunc 启动 Controller。
- 注册健康检查:如果 Controller 实现了健康检查接口,则注册健康检查。
启动 Informer
在执行完 StartControllers 启动完所有控制器后,run 方法的最后一步是启动 Informer 工厂,这一步会启动所有的 Informer 监听,当资源发生变化时,相关的 Controller 会收到通知并进行相应的处理。
| |
总结
可以看到 kube-controller-manager 的整体逻辑还是比较简单的,主要就是做了一系列初始化工作后,去创建并启动 Controller 并开启 Informer 监听,这样 各个 Controller 就可以通过 Informer 机制监听资源变化并执行相应的控制逻辑了。