我们在K8S环境中常见的一些POD状态这里进行罗列,然后根据每种状态来看看对应的解决方案有哪些
POD常见有以下几种状态
1、Pending
Pod创建已经提交给k8s,但是因为某种原因不能顺利创建,例如下载镜像慢,调度不成功等
故障分析:
Pending 说明 Pod 还没有调度到某个 Node 上面。可以通过 kubectl describe pod <pod-name> 命令查看到当前 Pod 的事件,进而判断为什么没有调度。可能的原因包括资源不足,集群内所有的Node都不满足该Pod请求的CPU、内存、GPU等资源
2、Running
Pod已经绑定到一个节点上了,并且已经创建了所有容器。只是有一个容器正在运行,或者在启动中,这个是属于POD的正常状态
3、Waiting
容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数
故障分析:
镜像拉取失败,比如配置了镜像错误、Kubelet无法访问镜像、私有镜像的密钥配置错误、镜像太大,拉取超时等CNI网络错误,一般需要检查 CNI 网络插件的配置,比如无法配置Pod、无法分配IP地址,可以通过通过kubectl describe pod <pod-name>命令查看到当前Pod的事件
4、ImagePullBackOff
这也是我们测试环境常见的,通常是镜像拉取失败。
故障分析:
这种情况可以使用 docker pull <image> 来验证镜像是否可以正常拉取。或者docker images | grep <images>查看镜像是否存在(系统有时会因为资源问题自动删除一部分镜像)
4、CrashLoopBackOff
CrashLoopBackOff状态说明容器曾经启动了,但可能又异常退出了,可能是健康检查失败,容器进程退出等问题
故障分析:
此时可以先查看一下容器的日志,可以使用kubectl logs kubectl logs --previous这个命令来查看
5、Error
通常处于Error状态说明Pod启动过程中发生了错误
故障分析:
依赖的 ConfigMap、Secret 或者 PV 等不存在,请求的资源超过了管理员设置的限制,比如超过了LimitRange等违反集群的安全策略,比如违反了 PodSecurityPolicy等容器无权操作集群内的资源,比如开启RBAC后,需要为ServiceAccount配置角色绑定
6、Unkown
由于某中原因apiserver无法获取到Pod的状态。通常是由于Master与pod所在的主机失去连接了
故障分析:
从v1.5开始,Kubernetes不会因为Node失联而删除其上正在运行的Pod,而是将其标记为Terminating或Unknown状态,想要删除这些状态的 Pod 有三种方法
1)从集群中删除该Node。使用公有云时,kube-controller-manager 会在VM删除后自动删除对应的Node。而在物理机部署的集群中,需要管理员手动删除 Node(如 kubectl delete node <node-name>。
2)Node恢复正常。Kubelet会重新跟kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些Pod。
3)用户强制删除。用户可以执行 kubectl delete pods <pod> --grace-period=0 --force 强制删除 Pod。除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法。特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或者数据丢失等问题。
7、Evicted
出现这种情况,多见于系统内存或硬盘资源不足,可df-h查看docker存储所在目录的资源使用情况,如果百分比大于85%,就要及时清理下资源,尤其是一些大文件、docker镜像。
清除状态为Evicted的pod:
kubectl get pods | grep Evicted | awk '{print $1}' | xargs kubectl delete pod
删除所有状态异常的pod:
kubectl delete pods $(kubectl get pods | grep -v Running | awk '{print $1}')
最后我们整理下,常用的排障命令基本都是一下这些命令
kubectl get pod <pod-name> -o yaml 查看 Pod 的配置是否正确 kubectl describe pod <pod-name> 查看 Pod 的事件 kubectl logs <pod-name> [-c <container-name>] 查看容器日志 kubectl exec -it <pod-name> -- /bin/bash #进入容器查看