登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  业界新闻

云原生 containerd 清理镜像 怎样处理

来源:17golang原创

时间:2026-10-22 07:23:24 322浏览 收藏

containerd 清理镜像,关键不是找到一个“删得最狠”的命令,而是先确认这些镜像由谁使用、位于哪个 namespace,以及它们是否仍被容器、快照或 lease 引用。独立 containerd 可以用 ctr 查看和删除,日常镜像管理更适合 nerdctl;Kubernetes 节点则优先沿着 CRI 的管理边界处理。

官方地址:https://github.com/containerd/containerd/

稳妥的顺序是“确认运行时边界 → 列出镜像 → 精确删除或按条件 prune → 等待并观察 GC”。不要直接删除 /var/lib/containerd,也不要把删除镜像引用误认为已经同步删除所有层。

先判断:你清理的是哪一套 containerd

我第一次遇到节点磁盘告警时,最容易误判的是把“能执行 ctr”当成“正在操作业务使用的镜像”。containerd 支持 namespace;Kubernetes、独立容器工具和测试任务可能并不共享同一个镜像视图。containerd 官方还明确说明,ctr 主要用于调试,面向日常使用的 CLI 是 nerdctl。

# 先看 containerd 的插件和 namespace,确认命令连接到哪套运行时
sudo ctr plugins ls
sudo ctr namespaces ls

# 独立 containerd 场景:只查看当前 namespace 的镜像引用
sudo ctr images ls

# 常见的 Kubernetes CRI 场景:优先从 CRI 视角查看镜像
sudo crictl images

如果节点由 Kubernetes 管理,不要把 ctr images rm 当成 kubelet 镜像回收策略的替代品。先确认 kubelet、CRI 配置和实际的 containerd namespace;如果只是独立主机上的 nerdctl 工作流,则用 nerdctl 的镜像命令更容易表达“未使用”和过滤条件。

containerd 独立命令、nerdctl 与 Kubernetes CRI 的边界关系说明图
图1:说明图,查看 containerd、CLI、CRI 和镜像视图之间的静态边界;这不是运行时截图。

为什么删掉镜像后磁盘空间没有立刻下降

containerd 的镜像不是一个单独的大文件。拉取后,索引或 manifest、config、压缩层、解压后的 snapshot 都可能参与资源关系;content store 按内容摘要保存对象,snapshotter 再负责容器文件系统快照。一个镜像引用被移除,只能说明这条引用不再保留,不代表所有相关资源此刻都没有其它引用。

官方垃圾回收文档把资源关系分成镜像、容器、快照、content 和 lease。lease 是客户端在操作完成后继续声明“未来还会使用这些资源”的方式。如果资源仍被容器或 lease 引用,GC 不应当把它们当成可回收对象。

# 查看镜像、content 与快照的概况;这些是排查信息,不要手动改目录
sudo ctr images ls
sudo ctr content ls
sudo ctr snapshots ls

# 独立 containerd 场景可用精确引用删除镜像元数据
sudo ctr images rm docker.io/library/nginx:1.27

因此,删除后的正确预期是:镜像引用先消失,随后由 containerd 的 GC 根据引用关系回收不再使用的 content 和 snapshot。回收时机与后台调度、删除数量和数据库变更有关,释放空间也可能受到正在运行容器、共享层和文件系统行为影响。

containerd 镜像引用、content、snapshotter、容器和 lease 的垃圾回收关系说明图
图2:结构说明图,查看镜像引用、content、快照、容器和 lease 如何共同影响 GC;这不是运行结果。

按场景选择删除方式

如果只想删一个确定的标签,优先用精确引用删除,改动面最小。需要批量清理时,先用 nerdctl 列出并确认工作流,再使用它的 image prune;该命令支持只处理 dangling image,也支持 -a、until 和 label 过滤。

# nerdctl 工作流:先列出镜像,再只清理 dangling image
sudo nerdctl images
sudo nerdctl image prune

# 需要扩大范围时显式写出 -a,并用时间条件限制候选
sudo nerdctl image prune -a --filter "until=168h"

# 生产环境先保留预览和审批记录;确认无误后再加 -f 取消交互确认
sudo nerdctl image prune -a --filter "label=cleanup.candidate=true" -f

如果是 Kubernetes 节点,优先从 CRI 视角处理未被工作负载使用的镜像,并让 kubelet 的镜像回收策略承担日常治理。crictl 更适合诊断 CRI;对具体镜像执行删除前,要确认它不再被运行中的 Pod 或下一次滚动发布需要。

# Kubernetes 节点:从 CRI 视角列出镜像,避免只看错 namespace
sudo crictl images

# 仅在已经确认该镜像不再被工作负载需要时执行精确删除
sudo crictl rmi registry.example.com/team/service:old

我现在会保留的四个检查点

清理动作真正危险的地方,不在命令长度,而在“删完才发现下一次启动要重新拉取”。我通常会把下面四项写进维护记录:

  • 命名空间:记录 ctr namespaces ls 的目标,不凭默认值猜测。
  • 使用者:确认没有运行中容器、Pod、滚动发布或离线任务依赖目标镜像。
  • 保留窗口:为回滚镜像、基础镜像和最近一次稳定版本保留空间,避免把 prune 变成一次性清空。
  • 回收结果:删除后观察 containerd 的资源变化和文件系统余量;不要用手工删除目录来“加速”结果。

最值得避免的做法是直接执行 rm -rf /var/lib/containerd。这会绕开 content、snapshot、metadata 和 lease 的关系管理,可能让现有容器、重启恢复和后续拉取一起进入不可预测状态。需要释放异常占用时,应先看日志、namespace、快照和 lease,再决定是删除某个引用、清理租约,还是修复调用方的资源生命周期。

常见问题

删了 tag,为什么层文件还在?

因为同一层可能被其它镜像、容器、snapshot 或 lease 引用。tag 删除改变的是镜像引用,GC 会按资源关系判断是否可回收,不保证同步删除。

containerd 和 nerdctl 的 prune 能混用吗?

不要把两个 CLI 的 namespace、snapshotter 和管理边界想当然地混在一起。先确认镜像由哪套工具创建,再使用同一套工具查看、筛选和删除。

Kubernetes 节点可以定时执行 ctr images prune 吗?

应先评估 kubelet 的镜像回收、CRI 配置和发布回滚需求。定时任务直接删除生产节点镜像,可能增加下一次调度的拉取压力;通常应先调整运行时治理策略,而不是把手工清理脚本当成唯一方案。

总结一下:containerd 清理镜像的核心是管理引用关系,而不是删除一个目录。先分清使用者和 namespace,再用精确删除或有过滤条件的 prune,最后让 GC 在保留运行中资源的前提下完成回收。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>