☰
Kubernetes 节点磁盘治理实战:overlay2 爆盘、容器占盘与 Registry 清理
2026/10/12 2:33:20 网站建设 项目流程

适用场景:K8s GPU 集群节点、Docker 容器运行时
问题特征:overlay2 存储层暴增、开发容器吃满磁盘、/var/lib/docker 所在分区 100%
核心手段:du 精准定位 + 软链迁移 + 在线扩容 + journald 限日志 + Registry API 删镜像


📑 目录

  1. 背景与问题全景
  2. overlay2 爆盘排查
  3. 长驻开发容器占盘定位与清理
  4. 磁盘目录迁移
  5. 在线扩容
  6. 日志治理
  7. 私有 Registry 镜像清理
  8. 踩坑清单
  9. 小结

一、背景与问题全景

在 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-depth=1|sort-hr|head-20

2.2 找到具体容器和文件

本次排查中发现单个容器层占3.1T / 3.3T,罪魁祸首是.vscode-server下的Pylance 扩展缓存:

根据 overlay2 的 long ID 反查容器

dockerps-a--no-trunc|grep<overlay2-id-prefix>

或者直接进容器层看

cd/var/lib/docker/overlay2/<id>/diffdu-h-x--max-depth=2|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--format"table {{.Name}}\t{{.Size}}\t{{.MemUsage}}"

按容器查具体目录大小。小

dockerinspect<container-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:进入容器内部清理(不停服)

dockerexec<container-id>bash-c'conda clean -a -y && pip cache purge && rm -rf ~/.cache'

方案 2:直接删容器(确认数据已持久化到 PVC 后)

dockerrm-f<container-id>

方案 3:限制容器可写层大小(docker run 时)

dockerrun --storage-optsize=50G...

四、磁盘目录迁移:软链方案与批量执行

当/var/lib/docker所在分区空间不足,而数据盘有空闲时,最快捷的方案是停服务 → 迁移数据 → 建软链。

4.1 单节点迁移

  1. 停 Docker 和 kubelett
systemctl stopdockersystemctl stop kubelet
  1. 迁移数据
mv/var/lib/docker /home/data/dockermv/var/lib/kubelet /home/data/kubelet
  1. 建软链
ln-s/home/data/docker /var/lib/dockerln-s/home/data/kubelet /var/lib/kubelet
  1. 启动服务
systemctl startdockersystemctl start kubelet

4.2 Ansible 批量迁移移

批量移动(适用于多节点统一调整)。)

ansible gpu-nodes-mshell-a'mv /data1/data/docker /data'

批量创建软链。链

ansible gpu-nodes-mfile-a'src=/data/docker dest=/var/lib/docker state=link force=yes'

⚠️ 迁移前务必确认目标分区有足够空间,mv跨文件系统实际是 copy+delete,大目录可能耗时很久。


五、在线扩容:growpart + resize2fs

云环境新增云盘容量后,不需要重启,直接在线扩容分区和文件系统。

  1. 查看磁盘和分区
lsblkdf-hT
  1. 扩展分区(以 /dev/vdb1 为例)
growpart /dev/vdb1
  1. 扩展文件系统
ext4 resize2fs /dev/vdb1 xfs xfs_growfs /data
步骤命令说明
查看lsblk/df -hT确认分区和文件系统类型
扩分区growpart /dev/vdb 1将分区 1 扩展到整个磁盘
扩文件系统resize2fs/xfs_growfs让文件系统识别新空间

六、日志治理:journald + docker log

6.1 systemd journal 日志清理

临时清理:只保留最近 3 天或 500M

journalctl --vacuum-time=3d journalctl --vacuum-size=500M

永久限制:修改配置文件

cat>>/etc/systemd/journald.conf<<EOF SystemMaxUse=1G SystemKeepFree=2G MaxRetentionSec=1week EOF

重启 journald 生效

systemctl restart systemd-journald

6.2 Docker 容器日志限制

在/etc/docker/daemon.json中配置:

{"log-driver":"json-file","log-opts":{"max-size":"100m","max-file":"3"}}
systemctl reloaddocker

七、私有 Registry 镜像清理:用 API 删远程镜像私有 Registry(master0:5000/images/*)镜像堆积时,不能只删除本地 tag,必须从 Registry 存储中真正删除。。

7.1 开启 Registry 删除功能

确保 Registry 启动时设置了环境变量::

REGISTRY_STORAGE_DELETE_ENABLED=true

7.2 通过 API 删除镜像

  1. 获取镜像的 config digest
TOKEN=$(curl-s-u<user>:<pass>\"https://master0:10000/v2/eflops/<image>/manifests/<tag>"\-H"Accept: application/vnd.docker.distribution.manifest.v2+json"\|python-c'import sys,json;print(json.load(sys.stdin)["config"]["digest"])')
  1. 删除 manifest(这才是真正删镜像)
curl-XDELETE\-u<user>:<pass>\"https://master0:10000/v2/eflops/<image>/manifests/$TOKEN"
  1. 触发 Registry 垃圾回收收
dockerexec<registry-container>registry garbage-collect /etc/docker/registry/config.yml

⚠️ 注意:直接 DELETE manifest 是不可逆操作,删除前确认没有人在用这个版本。生产环境建议先用skopeo list-tags列出所有 tag,再逐个确认。


八、踩坑清单

现象排查点
overlay2 突然 100%查.vscode-server/pylance/conda/pip cache
growpart 报 “unexpected output”分区表类型不对(GPT vs MBR),或分区正在被使用
journald 日志删了又满只 vacuum 没改journald.conf,重启后又涨回来
开发容器删了盘没释放overlay2 的deleted文件仍被进程占用,用lsof | grep deleted排查

九、小结

磁盘治理的核心经验:

  1. 定位要快:du -h -x --max-depth=1是排查 overlay2 爆盘的最快手段。段2.迁移要稳:停服务 → mv → 软链 → 验启动,顺序不能乱。乱3.限制要早:journald 的SystemMaxUse和 Docker 的log-opts部署时就该配好。好4.清理要彻底:Registry 镜像不能只删 tag,要用 API 删 manifest + garbage-collect。t有问题欢迎在评论区贴出报错信息,我看到后会回复。。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询