深入解析OverlayFS与Containerd:如何追踪POD的磁盘占用问题
1. 为什么需要关注POD的磁盘占用问题最近在排查一个生产环境的问题时发现所有主机在凌晨2-3点都会出现/home/t4目录磁盘使用率暴涨后回落的现象。客户确认这个时间段没有设置定时任务产品团队也表示没有相关计划任务。这让我意识到必须深入底层才能找到真正的原因。在容器化环境中磁盘空间管理是个永恒的话题。特别是当使用OverlayFS作为容器存储驱动时经常会遇到一些诡异的磁盘占用问题。比如容器删除后磁盘空间没有释放某个POD突然占用大量磁盘空间宿主机磁盘使用率周期性波动这些问题如果不及时处理轻则影响应用性能重则导致整个节点不可用。而要想快速定位这类问题就必须理解OverlayFS和Containerd的工作原理。2. OverlayFS的工作原理与磁盘占用机制2.1 OverlayFS的基本架构OverlayFS是一种联合文件系统它通过将多个目录叠加在一起呈现出一个统一的视图。在容器场景中OverlayFS通常由两层组成下层目录lowerdir只读层存储镜像的基础内容上层目录upperdir可写层存储容器运行时的修改当容器读取文件时OverlayFS会先检查upperdir如果文件不存在则从lowerdir读取。写入操作则全部发生在upperdir。2.2 磁盘占用的关键因素在实际使用中OverlayFS的磁盘占用主要来自以下几个方面镜像层叠加每个镜像层都会占用空间层数越多占用越大容器写入量upperdir的大小直接取决于容器的写入量日志文件应用日志如果没有合理配置轮转会快速膨胀临时文件某些应用生成的临时文件可能不会被及时清理在我的案例中通过脚本监控发现是/home/t4/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/下的某个数字目录导致了磁盘波动。这正是OverlayFS存储容器可写层的地方。3. Containerd的快照机制与磁盘管理3.1 Containerd的快照机制Containerd通过snapshotter管理容器的文件系统。默认使用overlayfs snapshotter它会为每个容器创建快照存储在/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/目录下。每个数字目录对应一个容器包含fs目录实际的文件系统内容work目录OverlayFS内部使用的工作目录3.2 磁盘问题的排查方法当发现磁盘异常时可以按照以下步骤排查定位问题目录#!/bin/bash directory/home/t4 while true; do current_time$(date %Y-%m-%d %H:%M:%S) echo 当前时间$current_time du -sh $directory --max-depth1 du -sh $directory/containerd --max-depth1 | sort -hr | head sleep 5 done关联容器IDmount | grep containerd.snapshotter.v1.overlayfs | grep {目录名}确认具体服务ctr -n k8s.io c list | grep [容器ID]在我的案例中最终发现是logrotate配置的copytruncate参数导致大日志文件拷贝引发了磁盘使用率突增。4. 实战排查与解决磁盘占用问题4.1 问题复现与分析通过监控脚本我们锁定了问题目录。进一步检查发现该目录对应的是一个日志服务的POD。该服务虽然没有定时任务但配置了logrotate进行日志切割。关键问题出在logrotate的配置上使用了copytruncate参数日志文件体积过大超过40GB没有设置minsize限制copytruncate的工作机制是复制原日志文件清空原文件对新文件进行压缩对于大日志文件这个复制操作会瞬间占用大量磁盘空间。4.2 解决方案与优化建议针对这个问题我们采取了以下措施优化logrotate配置/var/log/service/*.log { daily minsize 1G rotate 7 compress delaycompress missingok notifempty copytruncate }定期清理旧快照ctr -n k8s.io snapshot prune监控关键目录# 监控OverlayFS目录大小 watch -n 60 du -sh /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots考虑使用其他snapshotter 对于特殊场景可以尝试devmapper等snapshotter但需要注意性能影响。5. 高级技巧深入Containerd快照管理5.1 自定义snapshotterContainerd支持自定义snapshotter这为我们提供了更多灵活性。例如可以通过以下方式创建一个自定义的overlay snapshotterfunc NewSnapshotter(root string, opts ...overlay.Opt) (snapshots.Snapshotter, error) { sn, err : overlay.NewSnapshotter(root, opts...) if err ! nil { return nil, err } return overlayCustomAddLowerSnapshotter{sn}, nil }然后在containerd配置中启用[proxy_plugins] [proxy_plugins.overlay-custom-add-lower-snapshotter] type snapshot address /var/lib/containerd/cn.rectcircle.containerd.overlay-custom-add-lower-snapshotter/grpc.socks5.2 多snapshotter支持在Kubernetes环境中可以通过Pod注解指定snapshotterapiVersion: v1 kind: Pod metadata: annotations: io.containerd.snapshotter: devmapper这对于混合部署Kata和Runc容器的场景特别有用。6. 预防措施与最佳实践根据我的经验预防磁盘问题比事后排查更重要。以下是一些推荐的最佳实践日志管理合理配置logrotate避免使用copytruncate处理大文件考虑使用日志收集器直接收集日志避免本地存储存储监控监控/var/lib/containerd目录大小设置磁盘使用率告警阈值定期维护定期清理无用镜像和容器使用ctr snapshot prune清理旧快照配置优化限制单个容器磁盘配额考虑使用size选项限制OverlayFS大小应急预案准备磁盘清理脚本制定磁盘满载时的处理流程在实际生产环境中我遇到过多次因日志配置不当导致的磁盘问题。有一次一个服务的日志文件在短时间内增长到100GB直接导致节点不可用。从那以后我都会特别关注日志配置和磁盘监控。