容器数据磁盘被写满
造成的危害
- 不能创建 Pod (一直 ContainerCreating)
- 不能删除 Pod (一直 Terminating)
判断是否被写满
容器数据目录大多会单独挂数据盘,路径一般是 /var/lib/docker,也可能是 /data/docker 或 /opt/docker,取决于节点被添加时的配置:

可通过 docker info 确定:
$ docker info
...
Docker Root Dir: /var/lib/docker
...
如果没有单独挂数据盘,则会使用系统盘存储。判断是否被写满:
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
...
/dev/vda1 51474044 4619112 44233548 10% /
...
/dev/vdb 20511356 20511356 0 100% /var/lib/docker
解决方法
先恢复业务,清理磁盘空间
重启 dockerd (清理容器日志输出和可写层文件)
重启前需要稍微腾出一点空间,不然重启 docker 会失败,可以手动删除一些docker的log文件或可写层文件,通常删除log:
$ cd /var/lib/docker/containers $ du -sh * # 找到比较大的目录 $ cd dda02c9a7491fa797ab730c1568ba06cba74cecd4e4a82e9d90d00fa11de743c $ cat /dev/null > dda02c9a7491fa797ab730c1568ba06cba74cecd4e4a82e9d90d00fa11de743c-json.log.9 # 删除log文件注意:
使用
cat /dev/null > 式删除而不用rm 因为用 rm 删除的文件,docker 进程可能不会释放文件,空间也就不会释放;log 的后缀数字越大表示越久远,先删除旧日志。将该 node 标记不可调度,并将其已有的 pod 驱逐到其它节点,这样重启dockerd就会让该节点的pod对应的容器删掉,容器相关的日志(标准输出)与容器内产生的数据文件(可写层)也会被清理:
kubectl drain 10.179.80.31重启 dockerd:
systemctl restart dockerd取消不可调度的标记:
kubectl uncordon 10.179.80.31
定位根因,彻底解决
问题定位方法见附录,这里列举根因对应的解决方法:
- 日志输出量大导致磁盘写满:
- 减少日志输出
- 增大磁盘空间
- 减小单机可调度的pod数量
- 可写层量大导致磁盘写满: 优化程序逻辑,不写文件到容器内或控制写入文件的大小与数量
- 镜像占用空间大导致磁盘写满:
- 增大磁盘空间
- 删除不需要的镜像
附录
查看docker的磁盘空间占用情况
$ docker system df -v

定位容器写满磁盘的原因
进入容器数据目录(假设是 /var/lib/docker,并且存储驱动是 aufs):
$ cd /var/lib/docker
$ du -sh *
20K builder
72K buildkit
1.1G containers
12M image
100K network
12G overlay2
20K plugins
4.0K runtimes
4.0K swarm
4.0K tmp
4.0K trust
28K volumes

containers目录: 体积大说明日志标准输出量大[root@v-cjweichen-mesh /var/lib/docker/containers]# du -sh * 17M 01d8566ea348bd333b0d971a1751335b32f0d97396352e63a2dc25fdc7360a19 32K 07533d0f9e45ee03f6f22117326de17e2c9e0712a1e265d3a778dec1329f25e7 120K 076f585dc0f7532ab567743b7066d2803e2fbc698fa33f769e7f61002f450a3a 28K 0777cff7c65a4594df7c612eca7dac0ec6ddea2ffe70a8b118830150b062a468 28K 44565163715c8cdfe355892d7400f1836a86f9df27fb32adf32f5e41d7ea0531 目录名即为容器id,可以根据前12位 进行模糊匹配,就等查到对应的POD 信息 如: #docker ps | grep 01d8566ea348 01d8566ea348 ccr.ccs.tencentyun.com/tkeimages/tke-bridge-agent "/install-cni.sh --c…" 2 weeks ago Up 2 weeks k8s_tke-bridge-agent_tke-bridge-agent-qbbmn_kube-system_3b66c838-57c7-43a1-9281-8899c8b8b264_1 #docker ps | grep 445651637 44565163715c nginx "/docker-entrypoint.…" 2 days ago Up 2 days k8s_nginx_nginx-v1-6dc49fbd58-v2ntt_default_eed1f780-0d02-4788-9f45-8c94a2a58435_0overlay2 容器里面的文件系统rootfs在宿主机的路径规则
[root@mesh /var/lib/docker/overlay2]# du -sh * 36K 005fb0cee0261e7ab9201986ede339f5e1ea9f4d36efb5535c2451ecdb69488c 91M 02973b91425e166ac4a6f096ab37e4af41fb2fcf7e658e809ddaf7698caa73b7 32K 03cb6d1267a971930cdf50dcef86c69b3f92d16f0fc56a19b637e192c3bb57f7 720K 07e9f8b0c251d3e6d01551622bd2c4994a638d65cba9a7073a61a3273b13a20a 48K 07e9f8b0c251d3e6d01551622bd2c4994a638d65cba9a7073a61a3273b13a20a-init 163M 09ae9b4457a0ed3eec58c129d524345855ab20bdb18560f9c7d506da3c48d121 #目录名即为mount_id, 可以通过<docker_root>/image/overlay2/layerdb/mounts/container_id/mount-id查询 cd 09ae9b4457a0ed3eec58c129d524345855ab20bdb18560f9c7d506da3c48d121 [root@mesh /var/lib/docker/overlay2/09ae9b4457a0ed3eec58c129d524345855ab20bdb18560f9c7d506da3c48d121]# du -sh * 100K diff #diff子目录: 容器可写层,体积大说明可写层数据量大(程序在容器里写入文件) 4.0K link 4.0K lower 163M merged #联合挂载点,内容为容器里看到的内容,即包含镜像本身内容以及可写层内容 8.0K work
找出日志输出量大的 pod
TKE 的 pod 中每个容器输出的日志最大存储 1G (日志轮转,最大10个文件,每个文件最大100m,可用 docker inpect 查看):
$ docker inspect fef835ebfc88
[
{
...
"HostConfig": {
...
"LogConfig": {
"Type": "json-file",
"Config": {
"max-file": "10",
"max-size": "100m"
}
},
...
查看哪些容器日志输出量大:
$ cd /var/lib/docker/containers
$ du -sh *

目录名即为容器id,使用前几位与 docker ps 结果匹配可找出对应容器,最后就可以推算出是哪些 pod 搞的鬼
找出可写层数据量大的 pod
可写层的数据主要是容器内程序自身写入的,无法控制大小,可写层越大说明容器写入的文件越多或越大,通常是容器内程序将log写到文件里了,查看一下哪个容器的可写层数据量大:
$ cd /var/lib/docker/overlay2/diff
$ du -sh *

通过可写层目录(diff的子目录)反查容器id:
$ grep 834d97500892f56b24c6e63ffd4e520fc29c6c0d809a3472055116f59fb1d2be /var/lib/docker/image/aufs/layerdb/mounts/*/mount-id
/var/lib/docker/image/aufs/layerdb/mounts/eb76fcd31dfbe5fc949b67e4ad717e002847d15334791715ff7d96bb2c8785f9/mount-id:834d97500892f56b24c6e63ffd4e520fc29c6c0d809a3472055116f59fb1d2be
mounts 后面一级的id即为容器id: eb76fcd31dfbe5fc949b67e4ad717e002847d15334791715ff7d96bb2c8785f9,使用前几位与 docker ps 结果匹配可找出对应容器,最后就可以推算出是哪些 pod 搞的鬼
找出体积大的镜像

Docker 作为 K8S 容器运行时,容器日志的落盘将由 docker 来完成,保存在类似/var/lib/docker/containers/$CONTAINERID 目录下。Kubelet 会在 /var/log/pods 和 /var/log/containers 下面建立软链接,指向 /var/lib/docker/containers/$CONTAINERID 该目录下的容器日志文件
如果 Containerd 作为 K8S 容器运行时, 容器日志的落盘由 Kubelet 来完成,保存至 /var/log/pods/$CONTAINER_NAME 目录下,同时在 /var/log/containers 目录下创建软链接,指向日志文件