kubernetes源码-kubelet 原理和源码分析(四)
kubelet 是如何创建进行健康检查的,源码为 kubernetes 的 release-1.26 分支 .
写在前面
前面我们已经了解了 kubelet 是如果同步 pod 的整个过程,但是还有很多功能我们还没来得及看,比如健康检查,pleg ,存储卷挂载,驱逐管理等,我们今天得闲,先看看健康检查这一块是怎么完成的。
我们先看流程图,这样会有一个更清晰的概念。
大致流程如下:
-
podWorker 在对 pod 进行同步的时候,调用 AddPod() 方法对 pod 进行检查,看看 pod 是否配置了探针。
-
根据探针类型,构造 probe worker ,并拉起 worker 的 goroutine 进程。
-
run() 的时候,调用 prober 的 probe() 方法对探针类型进行检查,并使用对应类型的方法进行探测。
-
结果返回。
-
通知 kubelet 更新 pod 容器状态。
probeManager
在看 kl.probeManager.AddPod() 方法之前,我们先看看 probeManager 的构造,因为 AddPod 方法是建立在这个管理器的基础上的。
-
kubelet 在构建入口函数的时候,可以看到它在这里做了初始化。
-
newProber() 构建 4 个探测器,其中 runner 用来在容器里面执行 exec 命令用的。
-
创建 livenessManager, readinessManager, readinessManager 空的结果管理器。
-
创建 workers 缓存管理器。
|
|
AddPod()
-
检查 pod 里面的每个容器,有没有配置探针。
-
先检查缓存中有没有 worker , 没有的话,
m.workers[key] = w
将 worker 加入 prober 管理器缓存。 -
根据不同类型的探针,构建不同的 probe worker 并启动。
|
|
newWorker()
我们看看构造函数里面做了哪些操作。
做了 2 个操作:
-
根据探针类型对 worker 进行初始化设置。
-
设置监控值。
|
|
run()
接下来就是 worker 运行的逻辑代码。
-
设置定时器。
-
通过 doProbe 计算是否进行周期性循环健康检测。
-
defer 清理。
|
|
doProbe()
-
获取 pod 状态,检查 pod 是否处于退出状态,检查容器是否存在,检查 pod 是否处于优雅退出状态,是否在延迟时间内等,这些都不做探测。
-
startup 只执行一次,只要成功了,以后都是返回 true ,防止容器重启也执行再次 startup 探测,其他探针会等到容器就绪再进行探测。
-
执行
w.probeManager.prober.probe()
进行探测。 -
对结果进行记录。
-
根据容器 id ,结果,和 pod 信息,通过 w.resultsManager.Set() 通知 kubelet 更新 pod 容器状态和处理探针同步。
-
如果 liveness 和 startup 探针检测失败,则容器需要重启,且需要等待新的容器 id 出现才再次探测,防止在执行
doccker exec
的时候,破坏了容器的状态, resultRun 变量归零。 -
如果 pod 终止,则探针退出。
|
|
probe()
-
根据探针类型赋值 probeSpec ,后面探测要用到这个变量,如果这个值为空,则说明没有探针,直接返回成功的值。
-
运行 pb.runProbeWithRetries() 探测,这个方法是自带重试次数的,默认是 3 次重试。
-
pb.runProbeWithRetries() 调用 pb.runProbe() 执行探测, pb.runProbe() 根据探测器类型,执行对应的探测器,并将结果返回。
|
|
resultsManager.Set()
kubelet 的 syncLoopIteration() 方法内,接收探针结果,并对结果进行处理。
如果是就绪探针和启动探针,会分别调用到 kl.statusManager.SetContainerReadiness() , kl.statusManager.SetContainerStartup() ,设置 pod 容器状态。
-
查找容器。
-
修改容器状态值。
-
通过 statusManager 将容器和 pod 状态更新到缓存和 api server ,通过 podWorker 节点上 pod 的状态。
-
resultsManager.Set() 方法主要是将健康检测的结果保存到 worker 缓存中,然后 kubelet 再次同步 pod 的时候,调用到 syncPodFn 这个方法对容器进行同步的时候,会去拿里面 liveness ,startup 的结果来判断是否需要将容器 kill 掉重建。具体代码在
pkg/kubelet/kuberuntime/kuberuntime_manager.go
的 computePodActions() 方法里面看到。
|
|
然后再次调用 handleProbeSync() 对 pod 状态进行同步。
总结
-
kubelet 会对 pod 里面的每个容器进行检查,看看是否配置了探针,如果配置了,则每种探针类型都会给单独拉一个 goroutine 运行,知道 pod 销毁时再退出。
-
每种探针又会检查用的哪种协议或者说类型的方式来对容器进行检查,目前看是有 4 种, grpc 需要开启特性门口才能使用。
-
存活探针和启动探针的检测结果会存储在 kubelet 所在节点的缓存中,等 kubelet 对容器进行同步的时候,会取出结果进行检查,如果是失败的结果,则将容器 kill 掉重新创建。