问题现象
node节点状态频繁ready、notready
排查记录
- 为避免业务影响,将异常节点标记为不可调度,并把
master-3
节点的不可调度污点删掉(master充当node角色),将node-222
节点上的pod驱逐到其他节点。
$ kubectl cordon node-222
$ kubectl taint node master-2 node-role.kubernetes.io/master-
$ kubectl drain node-222 --ignore-daemonsets --delete-local-data
# 在驱逐时,发现一直卡死,强制驱逐
$ kubectl drain node-222 --ignore-daemonsets --delete-local-data --force
- 通过kubelet日志发现,
PLEG is not healthy
。
PLEG指的是pod lifecycle event generator。是kubelet用来检查容器runtime的健康检查机制。
PLEG定期检查节点上Pod运行情况,并且会把pod 的变化包装成Event发送给Kubelet的主同步机制syncLoop去处理。但是,在PLEG的Pod检查机制不能定期执行的时候,NodeStatus机制就会认为这个节点的状况是不对的,从而把这种状况同步到API Server,我们就会看到 not ready。
可以看到kubelet去同步容器的状态信息时出现了超时的状态,可以理解为调用链路出现了问题
# 调用链路
kubelet -> dockerd-shim -> dockerd --> containerd
出现 pleg not healthy,一般有以下几种可能:
- 容器运行时无响应或响应超时,如 docker进程响应超时(比较常见)
- 该节点上容器数量过多,导致 relist 的过程无法在 3 分钟内完成
- relist 出现了死锁,该 bug 已在 Kubernetes 1.14 中修复。
- 网络
- 通过日志可以分析出,kubelet当前调用dockerd时出现了超时
且当前之前被强制驱逐pod,runtime仍然在监测。说明已经失联
- 既然kubelet调不通,采取手动删除docker容器的方式
手动删除docker容器的时候也出现了卡死,基本可以定位为dockerd问题
- 咨询社区大佬得到反馈
这种一般是节点僵尸进程,pod因为device busy等,docker无法正确结束容器引起的
检查节点的io情况,io正常
检查进程,发现有一个Prometheus的僵尸进程
该进程的父进程为containerd-shim,尝试kill 僵尸进程。
$ kill -9 112455
强制杀死失败,并且被systemd
所接管,被systemd
所接管的进程是无法回收的。
问题定位
notready原因: 异常容器虽然已经僵死,kubelet得不到该容器反馈,在PLEG的Pod检查机制不能定期执行的时候,NodeStatus机制就会认为这个节点的状况是不对的会标记为notready
僵尸进程原因: 登录排查时发现Prometheus的pod是三个容器,其中一个容器一直在crash,可能在pleg期间的延迟,导致新旧容器同时存在的情况,而异常容器并没有终止成功导致出现僵尸进程
问题解决
涉及到systemd
所接管的僵尸进程,只能以重启服务器的方式进行解决
参考文档:https://mp.weixin.qq.com/s/G8g0asFhGIFh1WbTrw2Cbw