kubernetes garbage collection
Table of Contents
1. 前言
k8s 是一个异步的调度系统,当一个资源生命周期结束,内部的垃圾回收机制是如何运行的呢?
2. 代码参考
v1.14.0-alpha.3 commitid: cd9e590178c9f3812e296484b587de1c79461033
3. 简要说明
这里仅对 pod 以及 容器 的删除做了简要的说明
k8s 的垃圾回收机制逐渐向 evict 模块移动而不是直接放在 kubelet 中
垃圾回收作为整个系统的分支而不是核心部分,虽然刚刚开始;
之后也许会有 GCI 这种东西出现(虽然 Runtime 这个接口中已经有了)
4. gc 设计文档
5. gc 触发条件
https://kubernetes.io/docs/concepts/cluster-administration/kubelet-garbage-collection/
通过查看这个文档可以发现,旧的 gc 机制正在逐渐被被新的 evict 机制所取代
6. 代码详解
6.1. pod 的删除
kubelet 启动时会启动 syncLoop 来处理 file、apiserver、http 这三个 channel 的变化
详细的变化处理可以看 kubelet.go 的 1872 行 syncLoopIteration 的定义
HandlePodRemoves 作为 SyncHandler 的回调,会调用 deletePod 来删除 pod
这里注意 1728 行注释提及的内容
这里会发送信号给 podKillCh 这个 channel
podKiller 运行了一个 goroutine 从 podKillch 中读取数据然后杀死 pod
killPod 中调用了 controllerRuntime 中的 KillPod
KillPod 会调用 runtime 中的 KillContainer 来尝试删除容器
在删出容器之前会先运行 preStopContainer 来检查 lifecycle hooks
然后才会停止容器,通常情况下来请求 api 删除容器
至此一个 pod 删除完毕
6.2. podcontainerdeletor
kubelet/podcontainerdeletor.go
在启动 ContainerGc 后还启动了 podContainerDeletor 用于处理 pleg 这个 channel 中传来的信号
同样在 syncLoopIteration 中被使用
6.3. kuberuntimegc
kubelet/kuberuntime/kuberuntimegc.go
在第一次删除 pod 时,是允许失败的,因为会有一个线程周期性的清理无用的资源
kubelet 在 Bootstrap 时会启动一个垃圾回收线程
启动一个镜像垃圾回收器
根据 回收策略 启动了一个 容器垃圾回收
定义了 runtime 的接口 其中声明了 GarbageCollect
接下来是 k8s 通常情况下的垃圾回收运行机制
1.获得应该被驱逐的容器(没有在工作并且创建时间超出了回收策略设置的时间)
2.根据回收策略中的 MaxPerPodContainer 字段删除每个 pod 中最老的容器
3.根据回收策略中的 MaxContainers 字段删除最老的容器
4.获取所有无用的 sandbox
5.删除应该被驱逐的 sandbox
最后删除 pod 的日志目录