一、Pod启动阶段(相位 phase)
pod创建完之后,一直到持久运行起来,中间有很多步骤,也就有很多出错的可能,因此会有很多不同的状态。
Pod的启动过程如下:
0)controller-manager管理的控制器创建Pod资源
1)scheduler调度器根据调度算法选择最适合的node节点调度Pod
2)kubelet拉取镜像
3)kubelet挂载存储卷
4)kubelet创建并运行容器
5)kubelet根据容器探针的探测结果设置Pod状态
二、pod状态
●Pending:表示APIServer创建了Pod资源对象并已经存入了etcd中,但是它并未被调度完成(比如还没有调度到某台node上),或者仍然处于从仓库下载镜像的过程中。
●Running:Pod已经被调度到某节点之上,并且Pod中所有容器都已经被kubelet创建。至少有一个容器正在运行,或者正处于启动或者重启状态(也就是说Running状态下的Pod不一定能被正常访问)。
●Succeeded:有些pod不是长久运行的,比如job、cronjob,一段时间后Pod中的所有容器都被成功终止,并且不会再重启。需要反馈任务执行的结果。
●Failed:Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止,比如 command 写的有问题。
●Unknown:表示无法读取 Pod 状态,通常是 kube-controller-manager 无法与 Pod 通信。Pod 所在的 Node 出了问题或失联,从而导致 Pod 的状态为 Unknown
注:Pod生命周期起始于Pending阶段,如果至少有一个容器正常运行,则进入Running阶段,之后取决于Pod是否有容器以失败状态退出而进入Succeeded或Failed阶段。
pod异常场景
-
在 Pod 进行调度并创建容器过程中发生异常,此时 Pod 将卡在 Pending 阶段。
-
Pod 容器运行中发生异常,此时 Pod 按照具体场景处在不同阶段。
pod的常见异常场景如下图所示:
什么情况下会导致pod状态为pending?
Pod处于Pending状态通常意味着Pod调度失败或者调度器还没有为其分配节点资源。
可能原因如下:
1、没有合适的node节点调度
-
节点资源不足,需要进行扩容
-
超过 Namespace 资源配额
-
不满足亲和性
-
节点存在污点
-
没有可用节点
2、镜像拉取失败
-
镜像名字拼写错误或配置了错误的镜像
-
私有仓库的免密配置错误
-
网络不通
-
镜像拉取超时
-
同时拉取多个镜像,触发并行度控制
3、存储卷挂载失败
如何删除 Unknown 状态的 Pod ?
●从集群中删除有问题的 Node。使用公有云时,kube-controller-manager 会在 VM 删除后自动删除对应的 Node。 而在物理机部署的集群中,需要管理员手动删除 Node(kubectl delete node <node_name>)。
●被动等待 Node 恢复正常,Kubelet 会重新跟 kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些 Pod。
●主动删除 Pod,通过执行 kubectl delete pod <pod_name> --grace-period=0 --force 强制删除 Pod。但是这里需要注意的是,除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法。特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或者数据丢失等问题。
Worker Node 节点宕机后 Pod 的驱逐流程
1)K8S 的节点生命控制器在超出一定时间后不能与 kubelet 通信,就会标记该节点为 unknown 状态,并自动创建 NoExecute 污点防止调度器调度新 Pod 到该节点。
2)而那些已经在 Node 节点上运行的 Pod,在经过容忍度时间后(默认tolerationSeconds: 300),会被 NoExecute 污点自动驱逐。
三、K8S常见的排障手段
kubectl get -n <命名空间> pods -o wide #查看Pod的运行状态和就绪状态
kubectl describe -n <命名空间> pods <资源名称> #查看Pod的详细信息和事件描述,主要针对处于Pending状态的故障
kubectl logs -n <命名空间> <pod资源名称> -c <容器名称> -f -p #查看Pod容器的日志,主要针对进入Running状态后的故障,比如Failed异常问题
kubectl exec -n <命名空间> -it <pod资源名称> -c <容器名称> -- sh|bash|命令 #进入Pod容器中查看容器内部的相关状态信息,比如应用进程、端口、文件、流量等状态信息
kubectl debug -n <命名空间> -it <pod资源名称> --image=<临时工具容器的镜像名> --target=<目标容器> #在Pod中创建临时工具容器进入目标容器进行调试,针对没有调试工具的容器使用
nsenter -n -t <容器PID> #在Pod容器宿主机使用nsenter切换网络命名空间,直接在宿主机环境中进入目标容器的网络命名空间进行抓包等调试工作
kubectl get nodes #查看node节点的运行状态
kubectl get cs #查看master组件的健康状态
kubectl describe nodes <节点名称> #查看node节点的详细信息和资源使用情况
journalctl -u kubelet -f #跟踪查看kubelet进程日志
kubectl get -n <命名空间> svc #查看service资源的相关信息,比如类型、clusterIP、port、nodePort等
kubectl describe -n <命名空间> svc <资源名称> #查看service资源的详细信息,比如标签选择器、endpoints端点等
kubectl get -n <命名空间> pods --show-labels #查看Pod标签和就绪状态
Pod故障排除步骤
查看Pod事件
kubectl describe TYPE NAME_PREFIX
查看Pod日志(Failed状态下)
kubectl logs <POD_NAME> [-c Container_NAME] [–p]
进入Pod(状态为running,但是服务没有提供)
kubectl exec –it <POD_NAME> bash
kubectl debug -it <POD_NAME> --image=busybox:1.28 --target=${container_name}
查看集群信息
kubectl get nodes
发现集群状态正常
kubectl cluster-info
查看kubelet日志发现
journalctl -xefu kubelet