惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
T
Threat Research - Cisco Blogs
N
News and Events Feed by Topic
Hacker News: Ask HN
Hacker News: Ask HN
Project Zero
Project Zero
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 叶小钗
Security Latest
Security Latest
Spread Privacy
Spread Privacy
aimingoo的专栏
aimingoo的专栏
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
U
Unit 42
Cyberwarzone
Cyberwarzone
小众软件
小众软件
Scott Helme
Scott Helme
Engineering at Meta
Engineering at Meta
Microsoft Security Blog
Microsoft Security Blog
T
The Blog of Author Tim Ferriss
A
About on SuperTechFans
爱范儿
爱范儿
S
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Schneier on Security
Schneier on Security
Latest news
Latest news
GbyAI
GbyAI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
The Register - Security
The Register - Security
WordPress大学
WordPress大学
博客园_首页
Blog — PlanetScale
Blog — PlanetScale
PCI Perspectives
PCI Perspectives
Jina AI
Jina AI
AI
AI
NISL@THU
NISL@THU
I
Intezer
G
GRAHAM CLULEY
B
Blog
S
Secure Thoughts
IT之家
IT之家
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
Y
Y Combinator Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
有赞技术团队
有赞技术团队
V2EX - 技术
V2EX - 技术
Recorded Future
Recorded Future
Hacker News - Newest:
Hacker News - Newest: "LLM"

蛮荆

如何获取更多的免费服务器 Kubernetes 调度器队列 - 设计与实现 Kubernetes 调度器 - 核心流程 Kubernetes Networking Model & CNI Kubernetes CronJob 设计与实现 Kubernetes Job 设计与实现 Kubernetes HPA 设计与实现 Kubernetes Deployment 滚动更新实现原理 Kubernetes GC 设计与实现 Kubernetes Pod 驱逐 - 设计与实现 Kubernetes Daemonset 设计与实现 Kubernetes ReplicaSet 设计与实现 Kubernetes EndPoint 设计与实现 Kubernetes Informer 设计与实现 降本增效之应用优化 (三) 日志存储与检索 Kubernetes Pod 设计与实现 - 创建流程 Kubernetes 探针设计与实现 Unix 编程艺术名句摘录 Kubernetes - CRI 概述 Golang 编译速度为什么这么快? Kubernetes Pod 设计与实现 - Pause 容器 Kubernetes - kube-proxy 代理模式工程优化 Kubernetes 应用最佳实践 - 优雅关闭长连接 Kubernetes Service 类型和会话亲和性 Kubernetes 为什么需要 Ingress Kubernetes 架构 - 控制平面和数据平面 降本增效之应用优化 (二) 大报表 Go 语言如何获取 CPU 利用率 降本增效之应用优化 (一) Redis 业务规则引擎演变过程简述 微服务中的熔断算法 漏桶算法和令牌桶算法 jsonparser 为什么比标准库的 encoding/json 快 10 倍 ? zap 高性能设计与实现 HTTP Router 算法演进 fastcache 高性能设计与实现 Web 常见的三个安全问题 ants Code Reading Go 线程安全 map 方案选型 布隆过滤器 死锁、活锁、饥饿、自旋锁 sync.Pool Code Reading Go 内存管理概述 Go netpoll Code Reading goroutine 泄漏与检测 time/Timer Code Reading GMP Scheduler Code Reading Go channel 的 15 条规则和底层实现 为什么 Linux “一切皆文件” context.Context Code Reading runtime/HACKING.md Goland 最佳实践 互联网开发与金庸武学 为什么 Redis 6.0 引入多线程模型? Kubernetes 应用最佳实践 - 金丝雀发布 容器中如何正确配置 GOMAXPROCS ? singleflight Code Reading sync.Map Code Reading sync.Cond Code Reading sync.WaitGroup Code Reading sync.RWMutex Code Reading sync.Mutex Code Reading sync.Once Code Reading Go 无锁编程 sync/atomic Code Reading goroutine 交替打印奇偶数 GODEBUG Go 并发模式 Go 汇编 UUID 通用技术选型 Kubernetes 应用最佳实践 - 水平自动伸缩 Go 高性能 Tips fasthttp 为什么比标准库 net/http 快 10 倍 ? 技术文章配图指南 ChatGPT 初体验 Docker 网络原理概览 iptables 的五表五链 Kubernetes 应用最佳实践 - 亲和性和污点容忍度 Go 的反射与三大定律 Docker 官方提供的最佳实践 Go 语言内置的设计模式 HTTP1 到 HTTP3 的工程优化 Kubernetes 应用最佳实践 - Sidecar 模式 Kubernetes 应用最佳实践 - init 容器和钩子函数 为什么 recover 必须在 defer 中调用? 为什么 defer 的执行顺序和注册顺序不同? Go map 设计与实现 Go 切片扩容底层实现 Go 语言中的零拷贝 Go Delve 云原生和边缘计算简介 Kubernetes Pod 服务质量等级 Kubernetes 应用最佳实践 - 探针 Kubernetes 应用最佳实践 - 资源请求和限制 CDN 原理 Kubernetes 应用最佳实践 - 开篇 缓存策略和模式 Go 内存模型 Kubernetes 核心概念 软件版本语义化
Kubernetes 控制器管理总结
2024-01-07 · via 蛮荆

2024-01-07 Cloud Native Kubernetes 读代码

控制器管理逻辑

Kubernetes 中,控制器通过监控集群的资源状态,保证资源的当前状态向期望值收敛,单个控制器至少管理一种类型资源。

如果单从逻辑上划分,每个控制器应该是一个独立的进程,但是为了降低管理复杂度和代码的实现难度,Kubernetes 中所有的控制器会在同一个进程中运行。 当然,不同的控制器主体执行逻辑位于单独的 goroutine 中,每个控制器的内部可以被简化为一个无限循环,不断执行自身相关的控制逻辑,使系统资源收敛于期望状态。

控制器之间不会直接通信,它们甚至不知道其他控制器的存在,每个控制器内部的处理逻辑都是独立且类似的: 通过订阅 Informer 资源事件,并根据事件来执行对应的资源操作

通过 API Server 控制

需要注意的是: 所有控制器并不会主动创建并运行资源, 而是通过创建对应的资源 声明并发送到 API Server, 最后由控制面板其余组件配合完成剩下的操作, 例如 Deployment 控制器创建 Pod 时,由调度器分配 Node 并由 Node 上面的 kubelet 创建并运行指定的 Pod。

下面以经常使用的任务控制器 JobController 为例来进行说明。

Job 是集群中用于运行任务的资源,它通过一个或多个 Pod 来执行一个具体的任务,当 JobController 获取到新的运行任务时,保证一组节点上面的 kubelet 可以运行正确的 Pod 来完成任务。 JobController 自身不会去运行 Pod 或者容器,而是通过请求告知 API Server 具体的操作 (例如创建或删除 Pod), 当 API Server 执行完对应的请求操作后会返回消息, 控制面板中的其他组件会根据返回消息做出对应操作。

Controller Manager

顾名思义,Controller Manager 的角色就是作为一个大管家,管理集群中的各类控制器运行。

初始化

在控制器管理器执行 初始化操作 时,可以看到 Kubernetes 中常见的控制器全部会被注册:

func NewControllerInitializers(loopMode ControllerLoopMode) map[string]InitFunc {
	// 注册表结构
	// 控制器名称 => 启动方法
	controllers := map[string]InitFunc{}

	// 注册方法会逐个注册控制器
	// 注册时需要保证每个控制器的名称是唯一的
	//   如果出现重复的名称,直接 panic
	register := func(name string, fn InitFunc) {
		if _, found := controllers[name]; found {
			panic(fmt.Sprintf("controller name %q was registered twice", name))
		}
		controllers[name] = fn
	}

	// 注册各种控制器
	register(names.EndpointsController, startEndpointController)
	register(names.DaemonSetController, startDaemonSetController)
	register(names.JobController, startJobController)
	register(names.DeploymentController, startDeploymentController)
	register(names.HorizontalPodAutoscalerController, startHPAController)
	
	...

	return controllers
}

Informer 存在的必然性

如果从交互流程简单来看,控制器完全可以绕开 Informer, 直接和 API Server 进行通信获取资源的变更情况,然后根据结果执行对应的操作, 但是这种通信模式下为了保证即时获取资源变化情况,控制器的访问方式必须是类似轮询方式,那么所有控制器都采用这个方式的话,API Server 将会面对极大的负载压力, 因此通过使用 Informer 提供的 List & Watch 方式缓存增量事件数据,可以非常有效地降低 API Server 等控制面板相关组件的压力。

此外,通过增加一个 Informer “中间缓存层”,开发者只需要订阅 Informer 事件本身,然后专注于处理控制器的具体业务逻辑,而无需考虑事件数据源访问和并发等问题。

执行框架和流程

API Server 的工作只是负责存储资源对象到 etcd, 并将资源对象的变化以事件形式通知到 Informer,控制器初始化后启动时会从 Informer 订阅相关的事件, 根据事件创建对应的资源声明并发送到 API Server, 最后由控制面板其余组件配合完成剩下的操作。

每个控制器内部的处理逻辑都是独立且类似的: 通过订阅 Informer 资源事件, 注册资源对应的 Add/Update/Delete 等事件回调方法. 资源事件会被放入控制器关联的具体的队列中,然后控制器会开启多个 goroutine 从队列中获取资源事件并消费 (执行相关的操作),最后将期望状态声明回填到 API Server。

控制器执行框架流程图