k8s节点磁盘满
整理生产过程中遇到的宿主机磁盘容量满的排查思路和解决方案。
docker 环境下
docker 目录结构:
/var/lib/docker
├── containers # 存放的是容器的日志文件和元数据
├── image
├── volumes
|── networks
└── overlay2 # 存放的是 overlay2 存储驱动的镜像和容器临时数据(文件系统层)
/var/lib/docker/containers 目录满.
该目录下有很多文件夹,文件夹名字的前 12 位是 docker id 的名称,可以根据docker id获取运行的容器的信息.
具体操作如下:
docker ps -a| grep <容器 id> # (4~12位)
# 例如:
docker ps | grep 60988
# 输出如下:
# 可以定位到具体的 pod 名称信息
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 60988c3f8b2d nginx:latest "/docker-entrypoint.…" 2 days ago Up 2 days k8s_nginx_nginx-6f4b5c7d6c-2j5x7
# 结合 kubectl get pods -A 可以定位到具体的命名空间
kubectl get pod -A | grep <pod 名称>
/var/lib/docker/overlay2 目录满.
目录下有很多文件夹,该文件夹是 overlay2 存储驱动的镜像和容器数据(文件系统层),文件夹的名字是 docker id 的哈希值。
具体操作如下:
# 查看 overlay2 目录下的空间占用情况
# 找到占用空间较大的目录
du -sh /var/lib/docker/overlay2/* | sort -rh | head -20
...
381120 16d0b571a4b524e9fba283c6104f6554708bb0239f907765d5a371460ef7d978
407160 35edfde47350a64d141b26d3f56099c17d2a9ddf0650fd40875e099e43834bc8
438548 c92ca897a02d2675a63cee0ab08734b80f18c99e66fbfc328562e802b4d2768c
819672 f1135cb9834b71d1922c7cdb381049eaf6fdd4d1b43cb0cfe1aa31e93928d303
1041920 9779ad46cef024907894bd8413d380d53b86fac1f9820021e197edaca1c1fd38
# 然后通过 docker 命令获取该目录对应的容器信息
docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Id}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}}' | grep "9779ad46cef024907894bd8413d380d53b86fac1f9820021e197edaca1c1fd38"
# 7602, f1a9cfbb89b805a3d9ec11bf4a51e62ed07ff32dddc826d402306e0142b8ff53, /vanblog_vanblog_1, /var/lib/docker/overlay2/9779ad46cef024907894bd8413d380d53b86fac1f9820021e197edaca1c1fd38/work
# 精简版,输出docker容器的name,足以判断是哪个docker容器了
docker ps -q | xargs docker inspect --format '{{.Config.Hostname}}, {{.HostsPath}}, {{.GraphDriver.Data.WorkDir}}' | grep 114a2e3cda3bb7277f603d464cd2b4705f81abdf999a39ee2d110c1d84ff61ba
# kind-control-plane, /kind-control-plane, /var/lib/docker/overlay2/114a2e3cda3bb7277f603d464cd2b4705f81abdf999a39ee2d110c1d84ff61ba/work
# 或者通过如下命令获取
docker ps -a --format "table {{.Size}}\t{{.Names}}" |grep GB
containerd 环境下
containerd 目录结构:
/var/lib/containerd
├── io.containerd.snapshotter.v1.overlayfs # 存放 overlayfs 存储驱动的镜像和容器数据,容易满
├── io.containerd.content
└── io.containerd.metadata
/var/lib/kubelet
|── pods # 存放 Pod 的数据,容易占满
|── plugins
....
/var/lib/kubelet 目录满
# 本地磁盘 /var/lib/kubelet 写满
# 会牵连该节点的所有pod
# 首先查看 /var/lib/kubelet/pods 目录中哪个 pod 目录占用最大
# 排除一些挂载的共享目录,如果还有其他的可以一起排除
du -sh /var/lib/kubelet/pods/* --exclude=“*nfs*” | sort -rh | head -20
# 确定目录之后可以查看对应的 pod 信息
cat /var/lib/kubelet/pods/xxxx-xxx-xxx-xxx/etc-hosts # 该文件是pod的hosts文件,默认最后一行是该pod的相关信息。
/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs 满
该目录下存放 overlayfs 存储驱动的镜像和容器数据,容易满。
可以通过以下命令查看该目录的空间占用情况:
# 查看 overlayfs 目录下的空间占用情况
du -sh /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/* | sort -rh | head -20
110G 102
.....
# 该目录是挂载点,通过 mount 命令查看具体挂载的相关信息
mount -l | grep --color -w 102
overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/0ae5aa673f58c317d0e82f69009f0a99052d0c45f5ded9ad66f035209fb39ad8/rootfs type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/101/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/98/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/97/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/102/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/102/work)
# 如上,回显信息中 .../k8s.io/ 后边跟的是 pod id 信息(前 13 位)
crictl ps | grep 0ae5aa673
0ae5aa673f58c f3b6c1524c314 6 days ago Running calico-kube-controllers 0 834c9e240bbb6 calico-kube-controllers-6ff746f7c5-bght2
# 根据 pods id 定位到 该 pod
# 该 pod 对应的命名空间为 kube-system
# 该 pod 对应的容器名称为 calico-kube-controllers
crictl pods | grep 834c9e240bbb6
834c9e240bbb6 6 days ago Ready calico-kube-controllers-6ff746f7c5-bght2 kube-system 1 (default)
/var/lib/containerd/io.containerd.containerd.grpc.v1.cri/containers/ 满(几乎不会)
但是这里也给一下定位思路
du -sh /var/lib/containerd/io.containerd.containerd.grpc.v1.cri/containers/* | sort -rh | head -20
# 回显最后的随机字符串位容器 id
# 根据容器 id 查询对应的 pod 信息
# 会获得:容器名称、Pod 名称、命名空间
crictl ps --id <容器 id> -o json | jq -r '
.containers[].labels."io.kubernetes.container.name",
.containers[].labels."io.kubernetes.pod.name",
.containers[].labels."io.kubernetes.pod.namespace"
'