1. 课程导论:为什么需要垃圾回收与磁盘释放?

在 Kubernetes 集群中,容器运行时(Container Runtime)是承载 Pod 生命周期的核心组件。以 containerd 为例,它负责拉取镜像、创建容器、管理容器文件系统。然而,随着业务的持续部署、版本迭代与故障恢复,节点磁盘空间会迅速被以下三类数据吞噬:

  • 悬空镜像层(Dangling Layers):镜像更新后,旧层不再被任何镜像或容器引用,但仍残留在磁盘上。
  • 已退出容器的读写层(Read-Write Layers):容器退出后,其上层可写层(snapshotter 挂载点)未被及时清理。
  • 临时挂载与快照元数据(Snapshots & Metadata):containerd 的 snapshotter 维护大量中间快照,长期积累导致元数据膨胀。

若不引入有效的垃圾回收(Garbage Collection, GC)策略,磁盘容量将逐步逼近上限,最终引发 Eviction(驱逐)、Pod 创建失败 甚至 节点 NotReady 等生产事故。

1.1 容器镜像与层文件系统带来的磁盘压力

容器镜像采用 分层联合文件系统(OverlayFS / AUFS / devicemapper) 设计。每个镜像由多个只读层(Layer)叠加而成,容器启动时在最上层添加一个可写层。这种设计虽然实现了存储复用与快速分发,但也带来了独特的磁盘管理挑战:

压力来源 产生原因 磁盘影响
镜像层堆积 频繁构建/拉取新版本镜像,旧层未被 GC 回收 每层数 MB~数百 MB,累计可达数十 GB
容器可写层残留 容器退出后未执行 docker rm 或 crictl rm 每个容器可写层占用 100MB~数 GB(日志、临时文件)
快照元数据膨胀 snapshotter 维护大量已删除容器的快照记录 元数据文件(bolt.db)可达 GB 级,影响查询性能
临时拉取缓存 镜像拉取过程中产生的临时层与索引文件 拉取失败或中断后残留,占用额外空间
关键指标: 在生产环境中,一个运行 30 天的 32 节点 Kubernetes 集群,若未配置 GC,平均每个节点因悬空镜像和退出容器可写层浪费 15~25 GB 磁盘空间。这相当于 2~3 个完整业务镜像的体积。

1.2 磁盘压力引发的连锁故障

当节点磁盘使用率超过阈值(通常为 85%~95%),kubelet 会触发 节点压力驱逐(Node Pressure Eviction)。以下是典型的故障演进路径:

  1. 镜像拉取失败:磁盘空间不足,containerd 无法写入新层,Pod 启动卡在 ImagePullBackOff。
  2. 容器 OOM 与写延迟:文件系统元数据操作变慢,容器日志写入阻塞,引发健康检查失败。
  3. kubelet 驱逐 Pod:kubelet 根据 evictionHard 配置驱逐低优先级 Pod,导致服务抖动。
  4. 节点 NotReady:磁盘 I/O 完全阻塞,kubelet 心跳上报超时,节点从集群中脱离。
⚠️ 常见误区: 很多运维人员认为“只要节点磁盘够大(如 200GB SSD)就不需要 GC”。实际上,镜像层和容器可写层的增长速度远超预期——一次 CI/CD 流水线触发 10 次镜像构建,就可能产生 50+ 悬空层。GC 不是“可选项”,而是 节点稳定性的基础保障。

1.3 垃圾回收的核心目标

containerd 的垃圾回收机制围绕以下三个目标设计:

  • 回收悬空镜像层:删除未被任何镜像或容器引用的层,释放只读层空间。
  • 清理已退出容器的可写层:根据容器状态与保留策略,删除不再需要的快照。
  • 压缩元数据存储:定期对 snapshotter 的元数据库进行碎片整理与空间回收。

下图展示了 containerd 垃圾回收在节点存储体系中的位置与作用范围:

containerd 垃圾回收在节点存储体系中的位置 Kubernetes kubelet (Eviction Manager) containerd 守护进程 (containerd) CRI gRPC · 镜像管理 · 容器生命周期 · 垃圾回收 镜像存储 (Image Store) 悬空层 · 已拉取层 · 元数据索引 GC 目标:删除未被引用的层 快照存储 (Snapshot Store) 容器可写层 · 中间快照 · bolt.db GC 目标:清理退出容器快照 节点磁盘文件系统 (OverlayFS / ext4 / xfs) /var/lib/containerd · /var/lib/kubelet · 系统分区 GC 策略作用于镜像存储与快照存储两层,最终释放底层磁盘空间,避免 kubelet 触发驱逐

1.4 课程内容预览

本课程将深入 containerd 的垃圾回收实现,涵盖以下核心模块:

章节 核心内容 实践产出
2~4 镜像垃圾回收原理与参数调优 配置 image_gc_high_threshold / low_threshold
5~7 快照垃圾回收与容器可写层清理 手动触发 crictl rmi --prune 与 snapshot GC
8~10 元数据压缩与 bolt.db 碎片整理 使用 containerd metadata gc 命令
11~13 生产级 GC 策略设计 结合 kubelet 驱逐与 Prometheus 监控