Terminating Pod 是业务容器化后遇到的一个典型问题,诱因不一。本文记录了网易数帆-轻舟 Kubernetes 增强技术团队如何一步步排查,发现 Docker Volume 目录过多导致 Terminating Pod 问题的经历,并给出了解决方案。希望本文的分享对读者排查及规避同类问题有所帮助。
问题背景
最近用户的集群中又出现了某个节点上的 Pod 长时间处于 Terminating 状态的问题。起初我们以为是 18.06.3 版本的几个经典的 Docker 和 Containerd 问题导致的,但是登陆出现问题的节点后发现环境如下:
Component | Version |
---|---|
OS | Debian GNU/Linux 10 (buster) |
Kernel | 4.19.87-netease |
Docker | 18.09.9 |
Containerd | 1.2.10 |
Kubernetes | v1.13.12-netease |
Terminating Pod 的元数据如下:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-09-17T06:59:28Z"
deletionGracePeriodSeconds: 60
deletionTimestamp: "2020-10-09T07:33:11Z"
name: face-compare-for-music-4-achieve-848f89dfdf-4v7p6
namespace: ai-cv-team
# ......
spec:
# ......
status:
# ......
containerStatuses:
- containerID: docker://de6d3812bfc8b6bef915d663c3d0e0cf5b3f95a41c2a98c867a1376dbccd30d3
lastState: {
}
name: docker-image
ready: false
restartCount: 0
state:
running:
startedAt: "2020-09-17T06:59:30Z"
hostIP: 10.194.172.224
phase: Running
podIP: 10.178.132.136
qosClass: Guaranteed
startTime: "2020-09-17T06:59:28Z"
在节点上通过 docker
命令查看发现 Terminating Pod 下的业务容器 de6d3812bfc8
仍然未被删除:
$ docker ps -a | grep de6d3812bfc8
de6d3812bfc8 91f062eaa3a0 "java -Xms4096m -Xmx…" 3 weeks ago Up 3 weeks k8s_docker-image_face-compare-for-music-4-achieve-......
再通过 ctr
命令查看发现 Containerd 中仍然存有该容器的元数据:
$ ctr --address /var/run/containerd/containerd.sock --namespace moby container list | grep de6d3812bfc8
de6d3812bfc8b6bef915d663c3d0e0cf5b3f95a41c2a98c867a1376dbccd30d3 - io.containerd.runtime.v1.linux
我们怀疑是 Shim 的进程回收出现了问题,通过 ps
命令查找 de6d3812bfc8
容器的 Shim 进程准备获取栈进行分析,但是此时无法找到该容器的 Shim 进程以及业务进程。日志中查看到 Docker 和 Containerd 已经处理容器退出:
Oct 9 15:46:36 ai-data-k8s-3 dockerd[10017]: time="2020-10-09T15:46:36.824919188+08:00" level=debug msg=event module=libcontainerd namespace=moby topic=/tasks/exit
Oct 9 15:46:36 ai-data-k8s-3 containerd[1965]: time="2020-10-09T15:46:36.863630606+08:00" level=info msg="shim reaped" id=de6d3812bfc8b6bef915d663c3d0e0cf5b3f95a41c2a98c867a1376dbccd30d3
Oct 9 15:46:36 ai-data-k8s-3 dockerd[10017]: time="2020-10-09T15:46:36.873487822+08:00" level=debug msg=event module=libcontainerd namespace=moby topic=/tasks/delete
Oct 9 15:46:36 ai-data-k8s-3 dockerd[10017]: time="2020-10-09T15:46:36.873531302+08:00" level=info msg="ignoring event" module=libcontainerd namespace=moby topic=/tasks/delete type="*events.TaskDelete"
此时又有多个新的业务 Pod 被调度到该节点上,新调度 Pod 的容器一直处于 Created 状态。该现象和我们已知的几个 Docker 和 Containerd 问题是不同的:
$ docker ps -a | grep Created
03fed51454c2 c2e6abc00a12 "java -Xms8092m -Xmx…" 3 minutes ago Created k8s_docker-image_dynamic-bg-service-cpu-28-achieve-......
......
综上所述,当前观察到的现象如下:
- Kubelet 删除 Pod 的逻辑已被触发。
- Docker 已经接收并处理 Kubelet 删除容器的请求。
- 该容器的 Shim 进程以及业务进程已经被清理。
- 某种原因导致 Docker 和 Containerd 中的元数据一直无法被删除。
- 此后创建的容器一直处于 Created 状态。
原因分析
通过查看监控我们发现出现问题时该节点的磁盘利用率非常高并且 CPU 负载异常:
我们初步猜测该问题和异常的节点磁盘利用率有关。
为什么新调度 Pod 的容器一直处于 Created 状态
新调度 Pod 的容器一直处于 Created 状态是我们在 Docker 版本为 18.09.9 的环境遇到的新现象。针对该现象入手,我们在 Docker 栈中发现多个阻塞在包含 github.com/docker/docker/daemon.(*Daemon).ContainerCreate
函数的 Goroutine,并且阻塞的原因是 semacquire
。其中一个 Goroutine 内容如下:
goroutine 19962397 [semacquire, 8 minutes]:
sync.runtime_SemacquireMutex(0xc0