在Kubernetes节点上排查磁盘占用时,很多人会先问:containerd镜像到底存在哪里?这个问题不能只用一个目录回答。containerd把镜像内容、元数据、快照层和运行中容器状态拆成多个部分管理;Kubernetes又通过CRI以自己的命名空间观察这些资源。因此,节点上看到的镜像占用,往往同时包含镜像内容存储、解压后的文件系统快照、容器可写层和运行时元数据。
理解这些结构的价值很直接:当节点出现磁盘压力、镜像拉取失败、镜像清理无效或Pod反复重建时,团队可以判断问题发生在镜像内容、快照层、运行时状态还是kubelet回收策略,而不是盲目删除目录。

containerd镜像通常存在哪些位置
在多数Linux发行版和Kubernetes节点中,containerd的数据根目录通常位于 /var/lib/containerd。其中比较关键的部分包括内容存储、元数据、快照和运行时任务信息。不同发行版、安装方式或托管平台可能调整路径,所以实际环境应以containerd配置为准。
常见检查命令如下:
containerd config dump |
grep -E "root|state"
如果使用systemd管理containerd,也可以查看服务启动参数和配置文件位置:
systemctl status containerd
需要注意,知道目录并不等于可以直接删除目录。containerd内部会维护镜像引用、内容摘要、快照依赖和租约关系,手工删除文件容易造成元数据不一致。生产环境应优先通过CRI或containerd命令查看与清理。
内容存储、镜像索引和快照层的区别
containerd的镜像管理可以分为三个视角。第一是内容存储,保存以摘要标识的blob、manifest和配置对象;第二是镜像元数据,记录镜像名和tag指向哪些内容摘要;第三是快照层,镜像被拉取后需要解压成可挂载的文件系统层,容器启动时再叠加可写层。
这也是为什么 crictl images 看到的镜像大小,与宿主机目录统计结果不一定完全一致。前者偏镜像视角,后者包含更多运行时文件系统成本。多个镜像共享layer时,显示大小也可能和实际增量占用不同。

Kubernetes节点如何使用这些镜像
当Pod调度到节点后,kubelet会通过CRI请求containerd拉取镜像。containerd先检查本地是否已经存在可用内容,再决定是否访问镜像仓库。镜像内容准备好后,快照器会生成容器根文件系统所需的层,运行时再创建容器进程。
这个流程里有几个容易混淆的点:同一个镜像tag可能被重新推送,节点本地是否重新拉取取决于镜像拉取策略和摘要变化;镜像被多个Pod复用时,删除一个Pod通常不会立即删除镜像内容;节点磁盘清理由kubelet根据阈值、镜像使用情况和回收策略执行,不应依赖人工定期删除底层目录;containerd存在命名空间概念,Kubernetes通过CRI使用的资源通常在 k8s.io 命名空间下观察。
常用检查命令怎么组合
建议按“节点概况、CRI镜像、containerd内容、快照占用”的顺序检查。
crictl info
crictl images
crictl ps -a
ctr -n k8s.io images ls
ctr -n k8s.io content ls
ctr -n k8s.io snapshots ls
当节点出现磁盘压力时,再结合文件系统工具定位大目录。这里的目标不是立刻删除,而是判断占用类型:镜像内容多、快照多、容器日志多,还是业务写入容器可写层过多。容器日志通常不属于镜像存储本身,但经常与镜像目录一起被误判为“containerd占满磁盘”。更多容器运行时背景可参考容器技术专题。

镜像清理与治理建议
直接删除 /var/lib/containerd 下的文件,看似能快速释放空间,实际可能导致containerd无法识别已有镜像、快照残留、Pod启动失败,甚至需要重启节点才能恢复一致性。正确做法应分场景处理。如果只是清理未使用镜像,优先让kubelet根据策略自动回收。对于临时排障,可以使用CRI命令删除明确不再使用的镜像:
crictl rmi <image_id>
镜像存储治理不只是节点清理问题,还涉及镜像命名、版本、仓库、发布策略和容量规划。生产镜像应使用不可变版本或摘要引用,节点磁盘应设置监控水位,镜像构建应减少重复大层,关键业务镜像可以做受控预热,清理策略要考虑回滚需求。
常见问题
containerd镜像一定都在 /var/lib/containerd 吗?
不一定。这个路径是常见默认值,但实际位置取决于containerd配置、发行版封装和平台安装方式。排查时应先查看containerd配置中的root和state路径,再结合CRI命名空间确认Kubernetes使用的镜像资源。不要只凭目录名判断,也不要在不了解依赖关系的情况下直接删除文件。
crictl images 显示的大小为什么和磁盘占用不同?
因为两者统计口径不同。crictl images 更接近镜像引用和镜像内容视角,宿主机磁盘占用还包括解压后的快照层、容器可写层、日志、运行时状态和文件系统元数据。排查磁盘问题时,应同时看镜像列表、快照、容器日志和业务写入路径。
节点镜像太多时能不能定时执行删除脚本?
可以做自动化治理,但不建议用粗暴脚本直接删除containerd目录。更稳妥的方式是配置kubelet镜像回收阈值,定期清理未使用镜像,并在删除前确认没有运行中容器依赖。对于关键业务镜像,还要考虑预拉取和回滚需要,避免清理过度导致发布或故障恢复变慢。
转载请注明出处:https://www.cloudnative-tech.com/p/7461/