containerd 1.7: 垃圾回收的拓展
之前和苦总/Ace 维护 pouch-container/containerd 的时候,我们遇到比较多的问题是资源泄漏,比如节点负载太高以至于无法 umount 容器根目录(容器 bundle 目录残留),内核 pidns 死锁问题导致容器进程僵尸态( cgroup 残留),还有进程重启导致 CNI 网络资源泄漏等等。对于内核死锁等问题,重启可能是唯一的解决方案;而那些因为短期高负载或者进程重启导致的资源泄漏,它们需要从系统层面解决,至少应该让资源的创建者有机会去清理。 containerd 它本身就具备垃圾回收能力,但它只关注内部资源的清理,比如镜像数据以及容器可写层。而 CNI 网络资源以及 containerd-shim 等外部资源并不在垃圾回收的管理范围内,这部分资源容易出现泄漏的情况,比如 GKE 平台的用户就多次遇到了 Containerd IP leakage : 直到 pause 容器创建之前,containerd 仅在内存里保持对网络资源的引用;在将网络资源绑定给 pod 以前,containerd 一旦被强制重启就会发生泄漏。当时 containerd 社区的处理方式是提前创建 pod 记录,以此来提前关联网络资源,并利用 kubelet 的垃圾回收机制来触发资源清理。问题倒是解决了,但该方案仅适用于 kubernetes 场景,最合理的方案应该是创建者应具备周期性的清理流程。 考虑我们还有 shim 资源泄漏的问题,containerd 社区提了 Add collectible resources to metadata gc 方案来管理外部资源清理。在介绍这个方案之前,我想先介绍下 containerd 的垃圾清理机制。 基于标签系统和 lease 构建的垃圾回收 containerd 核心插件 metadata 管理着容器和镜像数据,如下图所示,其中虚线方块代表着子模块,比如 Images 代表着 image service,它仅用来管理镜像名字和镜像 manifest 的映射关系,而镜像的 blob 数据和解压后的文件内容分别由 content service 和 snapshot service 管理;需要说明的是,container service 仅用来保存用于启动容器的配置信息,它并不负责管理容器进程的生命周期。...