terminating状态分析及POD各种状态的分析思路

栏目:云苍穹知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

terminating状态分析及POD各种状态的分析思路

本文介绍的分析步骤和思路,也适用pod的各种状态的分析。


1 现像及分析步骤

当重启k8s容器容器服务,或者k8s运行过程中出现了node节点异常,会出现pod状态为terminating的现像,并且pod无法删除,且不会重新调度创建新的pod。



当出现terminating状态时,除了自身pod问题,一般都与node节点相关,所以需要收集和分析所在的节点异常信息。


问题查看步骤参考如下,并不一定按顺序执行。


1. 查看pod的状态:kubectl describe pod xxxx -n xxxx


2. 查看pod的日志:kubectl logs -f --tail 100 xxxx -n xxxx


3. 查看节点状态:kubectl get nodes



4. 执行:kubectl describe node xxx,进一步查看节点状态和事件。


5. 到异常node节点上,查看系统日志:/var/log/messages,查看异常信息。

rpc errors,exits with error context deadline exceeded,以及PLEG is not healthy事件,是常见的导致pod无法删除的原因之一,删除node节点,重启系统重新加入节点,是简单快速的解决方案。


6. 使用系统命令df、ls查看一下磁盘状态,以及挂载点路径,如果执行命令卡住无响应,表明磁盘或挂载点有问题,会影响到pod的回收与调度,比如挂载的NFS路径异常。


7. 如果只有某个pod处于terminating状态,进一步,我们可以删除下同一节点下的其它(非重要)pod,来确认一下是某个pod出了问题,还是该节点存在问题。


2 原因分析

1. 对象需要优雅删除,但k8s控制器不能完成删除。比如 Pod 因为 kubelet 无法下线节点上 node 容器、存储卷而无法删除。比较常见有以下原因:

kubelet 无法通过 container runtime 杀死进程。可能是挂载了外部存储,或者可能是运行时或操作内核遇到 bug 等,一般不能走正常流程让 kubelet 杀死进程,需要恢复挂载的存储,或重启操作系统才能解决。

kubelet 进程停止或者 node 失去联系。 该情况下,并没有 kubelet 运行或者运行中的 kubelet 与 apiserver 已经断开,无法收到 pod 需要删除下线的消息。所以,没有执行者来进行优雅删除。该情况下,需要恢复节点以及 kubelet 的运行即可。


2. 对象存在 finalizers,关联的控制器故障未能执行或执行 finalizer 函数卡住。该原因是k8s的删除机制,不用深究,可以通过一条命令删除terminating状态的pod来临时解决,但这也无法解决节点异常造成的问题。


3 解决办法

对于出现terminating状态的pod的情况下,主要有两种常见问题场景和应对方法。


1. 某个node节点上,只是一个pod出现terminating状态,并且无法正常通过kubelet delete pod删除。同一节点上的其它pod能正常删除,正常调度。

这种场景,只需要解决单个pod的问题。

强制删除:

kubectl delete pod xxx -n xxx --force --grace-period=0

如果强制删除还不行,设置finalizers为空:

kubectl patch pod xxx -n xxx -p '{"metadata":{"finalizers":null}}'


如果是挂载了nfs存储,则考虑挂载的存储是否正常,不正常需要先解决存储问题。


上面的方法都解决不了,则同样可使用下面第2种场景的方法解决。


2. 由于node节点异常,导致节点上的pod出现terminating状态。

这种情况下,往往可以从/var/log/messages中看到些异常和原因,比如rpc errors,exits with error context deadline exceeded,PLEG is not healthy等,是由docker或系统异常导致。另外执行docker命令响应(docker卡死),df 无响应(挂载存储卡死)等,也是导致容器运行异常的常见原因。解决的办法是删除node节点,再重启,具体步骤如下:

第一步:首先是在master上先删除异常的节点:

kubectl delete node xxxx

如果还有其它节点,并且资源足够的话,k8s会调度到其它节点,这样能够快速恢复业务pod。


第二步:在被删除的异常节点上,如果还能够执行命令docker ps,则通过docker ps查看,确保容器全部停止,再reboot重启主机。5分钟后,如果容器还一直运行,或者残留几个容器,直接reboot重启也可以。


第三步:主机节点重启后,该节点可以重新加入k8s集群,如果没有其它问题,就可以正常使用。

验证:通过重启服务或删除其它节点正常的pod,让k8s尝试调度新的pod到恢复的节点,确认集群恢复正常。

如果是因为挂载存储导致的异常,那重启后,需要确认存储挂载是否成功。

如果重启主机后,无法恢复,考虑主机的其它问题,需要进一步排查。


第四步:给刚删除的node,重新打上master或node标签。

kubectl label node [name-name]  node-role.kubernetes.io/master=master

kubectl label node [name-name]  node-role.kubernetes.io/node=node


4 其它状态

同样地,pod出现其它状态,也可以按上述的方法进行分析。

比如pod状态为ContainerCreating,那可以先确认是由单个pod引起的,还是因为节点异常造成的,再进一步排错。比如下图中,我们发现,117这个节点上的pod,大量出现ContainerCreating状态,通过kubectl describe pod命令就可以发现主要是由节点异常引起的,同时节点117也无法ssh登录。



此时,通过kubectl delete node命令把117这节点删除进行快速恢复,因为删除node节点后,pod会调度到其它节点。kubectl delete node命令后,就可以正常登录117节点,同时查看/var/log/messages就可以发现异常。


/var/log/messages日志:

Mar 22 15:23:22 v-docker-k6 dockerd: time="2023-03-22T15:23:22.849523296+08:00" level=warning msg="failed to retrieve runc version: fork/exec /usr/bin/runc: resource temporarily unavailable"

Mar 22 15:23:22 v-docker-k6 dockerd: time="2023-03-22T15:23:22.849865329+08:00" level=warning msg="failed to retrieve docker-init version: fork/exec /usr/bin/docker-init: resource temporarily unavailable"

Mar 22 15:23:23 v-docker-k6 dockerd: time="2023-03-22T15:23:23.925019553+08:00" level=warning msg="failed to retrieve runc version: fork/exec /usr/bin/runc: resource temporarily unavailable"

Mar 22 15:23:23 v-docker-k6 dockerd: time="2023-03-22T15:23:23.925146016+08:00" level=warning msg="failed to retrieve docker-init version: fork/exec /usr/bin/docker-init: resource temporarily unavailable"

Mar 22 15:23:23 v-docker-k6 systemd-udevd: fork of '/usr/lib/systemd/systemd-sysctl --prefix=/net/ipv4/conf/calico_tmp_B --prefix=/net/ipv4/neigh/calico_tmp_B --prefix=/net/ipv6/conf/calico_tmp_B --prefix=/net/ipv6/neigh/calico_tmp_B' failed: Resource temporarily unavailable

Mar 22 15:23:23 v-docker-k6 systemd-udevd: fork of child failed: Resource temporarily unavailable

Mar 22 15:23:25 v-docker-k6 systemd-udevd: fork of child failed: Resource temporarily unavailable

Mar 22 15:23:25 v-docker-k6 systemd-udevd: fork of child failed: Resource temporarily unavailable

Mar 22 15:23:25 v-docker-k6 systemd-udevd: fork of '/usr/lib/systemd/systemd-sysctl --prefix=/net/ipv4/conf/calico_tmp_B --prefix=/net/ipv4/neigh/calico_tmp_B --prefix=/net/ipv6/conf/calico_tmp_B --prefix=/net/ipv6/neigh/calico_tmp_B' failed: Resource temporarily unavailable

Mar 22 15:23:25 v-docker-k6 systemd-udevd: fork of child failed: Resource temporarily unavailable

Mar 22 15:23:25 v-docker-k6 systemd-udevd: fork of child failed: Resource temporarily unavailable

Mar 22 15:23:27 v-docker-k6 kube-proxy: E0322 15:23:27.490837    3904 proxier.go:1520] Failed to execute iptables-save, syncing all rules: fork/exec /usr/sbin/iptables-save: resource temporarily unavailable

Mar 22 15:23:27 v-docker-k6 kube-proxy: E0322 15:23:27.490977    3904 proxier.go:1520] Failed to execute iptables-save, syncing all rules: fork/exec /usr/sbin/iptables-save: resource temporarily unavailable

Mar 22 15:23:27 v-docker-k6 kube-proxy: E0322 15:23:27.491093    3904 proxier.go:1469] Failed to ensure that nat chain KUBE-SERVICES exists: error creating chain "KUBE-SERVICES": fork/exec /usr/sbin/iptables: resource temporarily unavailable:

Mar 22 15:23:27 v-docker-k6 kube-proxy: E0322 15:23:27.491234    3904 ipset.go:172] Failed to make sure ip set: &{{KUBE-LOAD-BALANCER-LOCAL hash:ip,port inet 1024 65536 0-65535 Kubernetes service load balancer ip + port with externalTrafficPolicy=local} map[] 0xc0002178d0} exist, error: error creating ipset KUBE-LOAD-BALANCER-LOCAL, error: fork/exec /usr/sbin/ipset: resource temporarily unavailable

Mar 22 15:23:27 v-docker-k6 dockerd: time="2023-03-22T15:23:27.855087150+08:00" level=warning msg="failed to retrieve runc version: fork/exec /usr/bin/runc: resource temporarily unavailable"

Mar 22 15:23:27 v-docker-k6 dockerd: time="2023-03-22T15:23:27.855308912+08:00" level=warning msg="failed to retrieve docker-init version: fork/exec /usr/bin/docker-init: resource temporarily unavailable"


经搜查,上述日志说明是系统上的进程数量太多了,达到了命令"ulimit -u"的限制。我们可以根据日志,对系统参数进行优化,然后reboot一下主机。reboot后,117节点会重新加入k8s集群(确保kubelet进程自动启动)。


kubernetes各种状态的说明,可参考文章:服务实例状态说明,介绍了CrashLoopBackOff、Unschedulable、Evicted、CrashLoopBackOff、Pending、ImagePullBackOff/ErrImagePull等常见状态,熟悉这些状态,以及分析思路,可以快速定位和解决k8s遇到的问题。

terminating状态分析及POD各种状态的分析思路

本文介绍的分析步骤和思路,也适用pod的各种状态的分析。1 现像及分析步骤当重启k8s容器容器服务,或者k8s运行过程中出现了node节点异常,...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息