适用场景K8s GPU 集群节点、Docker 容器运行时问题特征overlay2 存储层暴增、开发容器吃满磁盘、/var/lib/docker 所在分区 100%核心手段du 精准定位 软链迁移 在线扩容 journald 限日志 Registry API 删镜像 目录背景与问题全景overlay2 爆盘排查长驻开发容器占盘定位与清理磁盘目录迁移在线扩容日志治理私有 Registry 镜像清理踩坑清单小结一、背景与问题全景在 AI/GPU 集群的日常运维中磁盘问题比 CPU/内存问题更隐蔽、更致命——服务不会立刻崩溃但会在某个深夜悄悄把/var/lib/docker撑到 100%然后 kubelet 开始驱逐 Pod、容器无法启动、节点直接变为 NotReady。本次治理覆盖了生产环境中最典型的五类磁盘问题overlay2 单容器层占 3.1T.vscode-server的 pylance 扩展缓存爆炸长驻开发容器单实例吃 130G/var/lib/docker和/var/lib/kubelet挂错分区云盘需要在线扩容systemd journal 日志无限制增长私有 registry 镜像堆积需要 API 级清理二、overlay2 爆盘排查精准定位元凶2.1 快速定位哪个目录最大先看整体磁盘使用df-h进入 overlay2 目录逐层排查cd/var/lib/docker/overlay2du-h-x--max-depth1|sort-hr|head-202.2 找到具体容器和文件本次排查中发现单个容器层占3.1T / 3.3T罪魁祸首是.vscode-server下的Pylance 扩展缓存根据 overlay2 的 long ID 反查容器dockerps-a--no-trunc|grepoverlay2-id-prefix或者直接进容器层看cd/var/lib/docker/overlay2/id/diffdu-h-x--max-depth2|sort-hr|head-10定位到/root/.vscode-server/extensions/ms-python.vscode-pylance-*/ 经验AI 开发场景中Pylance 索引大型 Python 项目时会疯狂写缓存单个扩展目录轻松突破 TB 级。解决方案是给.vscode-server配置settings.json排除目录或在镜像构建时预装 Pylance 并限制其缓存路径。。三、长驻开发容器占盘定位与清理算法同学的长驻开发容器Jupyter / SSH 开发容器经常在不知不觉中吃掉上百 GB因为数据集、conda 环境、pip cache 全都写入容器可写层。。3.1 找出占盘大户实时查看容器磁盘占用。用dockerstats --no-stream--formattable {{.Name}}\t{{.Size}}\t{{.MemUsage}}按容器查具体目录大小。小dockerinspectcontainer-id|grep-imerged 输出类似/var/lib/docker/overlay2/id/mergeddu-sh/var/lib/docker/overlay2/id/merged本次查出的典型案例本次排查出的典型案例容器名占盘大小原因dev-container-7f3a134 GB数据集直接下载到容器层notebook-8821131 GBConda 环境 pip cache 未清理3.2 清理策略方案 1进入容器内部清理不停服dockerexeccontainer-idbash-cconda clean -a -y pip cache purge rm -rf ~/.cache方案 2直接删容器确认数据已持久化到 PVC 后dockerrm-fcontainer-id方案 3限制容器可写层大小docker run 时dockerrun --storage-optsize50G...四、磁盘目录迁移软链方案与批量执行当/var/lib/docker所在分区空间不足而数据盘有空闲时最快捷的方案是停服务 → 迁移数据 → 建软链。4.1 单节点迁移停 Docker 和 kubelettsystemctl stopdockersystemctl stop kubelet迁移数据mv/var/lib/docker /home/data/dockermv/var/lib/kubelet /home/data/kubelet建软链ln-s/home/data/docker /var/lib/dockerln-s/home/data/kubelet /var/lib/kubelet启动服务systemctl startdockersystemctl start kubelet4.2 Ansible 批量迁移移批量移动适用于多节点统一调整。ansible gpu-nodes-mshell-amv /data1/data/docker /data批量创建软链。链ansible gpu-nodes-mfile-asrc/data/docker dest/var/lib/docker statelink forceyes⚠️ 迁移前务必确认目标分区有足够空间mv跨文件系统实际是 copydelete大目录可能耗时很久。五、在线扩容growpart resize2fs云环境新增云盘容量后不需要重启直接在线扩容分区和文件系统。查看磁盘和分区lsblkdf-hT扩展分区以 /dev/vdb1 为例growpart /dev/vdb1扩展文件系统ext4 resize2fs /dev/vdb1 xfs xfs_growfs /data步骤命令说明查看lsblk/df -hT确认分区和文件系统类型扩分区growpart /dev/vdb 1将分区 1 扩展到整个磁盘扩文件系统resize2fs/xfs_growfs让文件系统识别新空间六、日志治理journald docker log6.1 systemd journal 日志清理临时清理只保留最近 3 天或 500Mjournalctl --vacuum-time3d journalctl --vacuum-size500M永久限制修改配置文件cat/etc/systemd/journald.confEOF SystemMaxUse1G SystemKeepFree2G MaxRetentionSec1week EOF重启 journald 生效systemctl restart systemd-journald6.2 Docker 容器日志限制在/etc/docker/daemon.json中配置{log-driver:json-file,log-opts:{max-size:100m,max-file:3}}systemctl reloaddocker七、私有 Registry 镜像清理用 API 删远程镜像私有 Registrymaster0:5000/images/*镜像堆积时不能只删除本地 tag必须从 Registry 存储中真正删除。。7.1 开启 Registry 删除功能确保 Registry 启动时设置了环境变量REGISTRY_STORAGE_DELETE_ENABLEDtrue7.2 通过 API 删除镜像获取镜像的 config digestTOKEN$(curl-s-uuser:pass\https://master0:10000/v2/eflops/image/manifests/tag\-HAccept: application/vnd.docker.distribution.manifest.v2json\|python-cimport sys,json;print(json.load(sys.stdin)[config][digest]))删除 manifest这才是真正删镜像curl-XDELETE\-uuser:pass\https://master0:10000/v2/eflops/image/manifests/$TOKEN触发 Registry 垃圾回收收dockerexecregistry-containerregistry garbage-collect /etc/docker/registry/config.yml⚠️ 注意直接 DELETE manifest 是不可逆操作删除前确认没有人在用这个版本。生产环境建议先用skopeo list-tags列出所有 tag再逐个确认。八、踩坑清单现象排查点overlay2 突然 100%查.vscode-server/pylance/conda/pip cachegrowpart 报 “unexpected output”分区表类型不对GPT vs MBR或分区正在被使用journald 日志删了又满只 vacuum 没改journald.conf重启后又涨回来开发容器删了盘没释放overlay2 的deleted文件仍被进程占用用lsof | grep deleted排查九、小结磁盘治理的核心经验定位要快du -h -x --max-depth1是排查 overlay2 爆盘的最快手段。段2.迁移要稳停服务 → mv → 软链 → 验启动顺序不能乱。乱3.限制要早journald 的SystemMaxUse和 Docker 的log-opts部署时就该配好。好4.清理要彻底Registry 镜像不能只删 tag要用 API 删 manifest garbage-collect。t有问题欢迎在评论区贴出报错信息我看到后会回复。。