Kubernetes Pod 状态详解:从 Pending 到 CrashLoopBackOff,运维工程师必备
1. 什么是 Pod?为啥要关注它的状态?
2. Pod 的常见状态
2.1 Pending(等待中)
2.2 Running(运行中)
2.3 Succeeded(成功)
2.4 Failed(失败)
2.5 CrashLoopBackOff(容器反复崩溃重启)
2.6 Unknown(未知)
3. 总结:Pod 状态,运维的眼睛
4. 附录:常用 kubectl 命令
嘿,老兄!我是老码农,一个在 K8s 摸爬滚打多年的老家伙。今天咱们聊聊 Kubernetes 里面 Pod 的状态。这玩意儿可太重要了,就像你家里的电表,得随时关注,不然出问题了都不知道。这篇文章,我把 Pod 的各种状态都给你扒个底朝天,顺便再说说遇到问题怎么排查,保证让你看完就能独当一面!
1. 什么是 Pod?为啥要关注它的状态?
首先,简单回顾一下。Pod 是 Kubernetes 里面最小的部署单元,你可以把它理解成一个或多个容器的集合。容器嘛,就是跑你应用的地方。所以,Pod 状态就代表了你的应用跑得怎么样。状态正常,说明应用正常运行;状态异常,那你得赶紧看看出啥事了,不然用户可要骂娘了!
2. Pod 的常见状态
K8s 里面 Pod 的状态有很多,但最常见的就这几个:
- Pending(等待中)
- Running(运行中)
- Succeeded(成功)
- Failed(失败)
- CrashLoopBackOff(容器反复崩溃重启)
- Unknown(未知)
下面咱们一个个详细说说。
2.1 Pending(等待中)
含义: Pod 已经被 Kubernetes API Server 接受了,但一个或多个容器还没创建起来,或者还没跑起来。这就像你下单了快递,商家已经接单了,但快递还没发货。
常见原因:
- 资源不足: 你的集群里没有足够的资源(比如 CPU、内存)来运行 Pod。就像你买了个大件,但家里没地方放。
- 镜像拉取问题: K8s 无法从镜像仓库(比如 Docker Hub、私有仓库)拉取镜像。可能是网络问题,也可能是镜像名写错了。
- 调度问题: K8s 找不到合适的 Node 来运行 Pod。比如,你的 Pod 声明了特定的 NodeSelector,但集群里没有符合条件的 Node。
- PV/PVC 问题: 如果 Pod 需要使用 PersistentVolumeClaim (PVC) 来存储数据,PVC 还没有绑定到 PV 上,Pod 也会处于 Pending 状态。
排查方法:
查看 Pod 的详细信息: 使用
kubectl describe pod <pod-name> -n <namespace>
命令,看看 Events 部分,那里会告诉你为什么 Pod 处于 Pending 状态。就像看快递物流信息。kubectl describe pod my-pod -n my-namespace
重点关注 Events 部分,它会告诉你 K8s 在干嘛,为啥卡住了。
Events: Type Reason Age From Message ---- ------ ---- ---- ------ Warning FailedScheduling 5m (x2 over 5m) default-scheduler 0/3 nodes are available: 3 node(s) had taints that the pod didn't tolerate. Warning FailedMount 2m (x2 over 2m) kubelet MountVolume.SetUp failed for volume "data" : failed to attach volume "pvc-xxx" to instance "node-xxx" 从上面的例子可以看出,可能是调度失败或者挂载卷失败。
检查 Node 的资源使用情况: 使用
kubectl get nodes
命令,查看 Node 的 CPU、内存使用情况。如果资源紧张,赶紧加机器或者优化你的应用。kubectl get nodes
检查镜像仓库是否可达: 尝试手动拉取镜像,看看能不能拉下来。如果不行,检查网络配置、镜像名称是否正确。
docker pull <image-name>:<tag>
检查 PVC 和 PV 的绑定情况: 使用
kubectl get pvc -n <namespace>
和kubectl get pv
命令,确保 PVC 已经绑定到 PV 上了。kubectl get pvc -n my-namespace kubectl get pv
2.2 Running(运行中)
含义: Pod 已经绑定到了一个 Node 上,并且所有容器都创建起来了,至少有一个容器是 Running 状态。但要注意,这不代表你的应用就一定正常运行了。就像快递已经发货了,但可能还在路上。
排查方法:
查看 Pod 的状态: 使用
kubectl get pod <pod-name> -n <namespace>
命令,确保 Pod 的状态是 Running。kubectl get pod my-pod -n my-namespace
NAME READY STATUS RESTARTS AGE my-pod 1/1 Running 0 10m READY
显示 1/1,表示容器都起来了。STATUS
显示 Running,表示 Pod 正在运行。查看容器的日志: 使用
kubectl logs <pod-name> -c <container-name> -n <namespace>
命令,查看容器的日志,看看有没有报错信息。kubectl logs my-pod -c my-container -n my-namespace
如果日志里有错误,赶紧修复。
进入容器内部调试: 使用
kubectl exec -it <pod-name> -c <container-name> -- /bin/bash
命令,进入容器内部,进行调试。比如,你可以测试网络连通性、检查文件是否存在等等。kubectl exec -it my-pod -c my-container -- /bin/bash
检查服务是否正常: 如果你的 Pod 暴露了服务(Service),使用
kubectl get svc -n <namespace>
命令,查看服务的状态,并尝试访问服务,看看是否能正常访问。kubectl get svc -n my-namespace
然后,你可以通过服务对应的 Cluster IP 或者 NodePort 访问你的应用。
2.3 Succeeded(成功)
含义: Pod 里面的所有容器都成功退出了。通常用于一次性任务,比如数据备份、数据库迁移等。就像你的任务完成了。
常见原因:
- 任务正常完成: 你的 Pod 里的程序执行完毕,没有错误。
排查方法:
查看 Pod 的状态: 使用
kubectl get pod <pod-name> -n <namespace>
命令,确保 Pod 的状态是 Succeeded。kubectl get pod my-job -n my-namespace
NAME READY STATUS RESTARTS AGE my-job 0/1 Succeeded 0 5m 查看 Pod 的日志: 使用
kubectl logs <pod-name> -c <container-name> -n <namespace>
命令,查看容器的日志,确认任务是否正常完成。kubectl logs my-job -c my-container -n my-namespace
2.4 Failed(失败)
含义: Pod 里面的一个或多个容器失败了。这可能是程序出错了,也可能是容器启动失败了。就像你的任务失败了。
常见原因:
- 程序崩溃: 容器里的程序出现异常,导致容器退出。
- 容器启动失败: 容器启动时出现错误,比如配置错误、依赖缺失等。
- 资源不足: 容器申请的资源超过了限制。
- 镜像问题: 镜像有问题,导致容器无法启动。
排查方法:
查看 Pod 的状态: 使用
kubectl get pod <pod-name> -n <namespace>
命令,确保 Pod 的状态是 Failed。kubectl get pod my-job -n my-namespace
NAME READY STATUS RESTARTS AGE my-job 0/1 Failed 0 5m 查看 Pod 的详细信息: 使用
kubectl describe pod <pod-name> -n <namespace>
命令,查看 Events 部分,找到失败的原因。kubectl describe pod my-job -n my-namespace
重点关注 Events 部分,它会告诉你为啥失败。
查看容器的日志: 使用
kubectl logs <pod-name> -c <container-name> -n <namespace>
命令,查看容器的日志,看看有没有报错信息。kubectl logs my-job -c my-container -n my-namespace
进入容器内部调试: 如果容器允许进入,使用
kubectl exec -it <pod-name> -c <container-name> -- /bin/bash
命令,进入容器内部,进行调试。kubectl exec -it my-job -c my-container -- /bin/bash
2.5 CrashLoopBackOff(容器反复崩溃重启)
含义: 容器启动后立即崩溃,然后 K8s 尝试重启它,但又崩溃,如此循环往复。这就像你的应用不停地死循环。
常见原因:
- 程序错误: 程序存在 bug,导致容器启动后立即崩溃。
- 配置错误: 容器的配置有问题,比如环境变量、配置文件等。就像你给错了机器的启动参数。
- 依赖问题: 容器依赖的其他服务或者资源不可用。就像你缺了启动需要的零件。
- 资源限制: 容器申请的资源超过了限制,导致容器被 OOM kill。
排查方法:
查看 Pod 的状态: 使用
kubectl get pod <pod-name> -n <namespace>
命令,确保 Pod 的状态是 CrashLoopBackOff。kubectl get pod my-app -n my-namespace
NAME READY STATUS RESTARTS AGE my-app 0/1 CrashLoopBackOff 5 10m RESTARTS
字段表示容器重启的次数,重启次数越多,问题越严重。查看 Pod 的详细信息: 使用
kubectl describe pod <pod-name> -n <namespace>
命令,查看 Events 部分,找到失败的原因。重点关注 Last State 部分,它会告诉你容器最后一次退出时的信息,比如退出码、错误信息等。kubectl describe pod my-app -n my-namespace
Events: Type Reason Age From Message ---- ------ ---- ---- ------ Normal Scheduled 10m default-scheduler Successfully assigned my-app-xxx to node-xxx Normal Pulling 10m kubelet Pulling image "my-image:latest" Normal Pulled 10m kubelet Successfully pulled image "my-image:latest" Normal Created 10m kubelet Created container my-container Normal Started 10m kubelet Started container my-container Warning BackOff 2m (x10 over 9m) kubelet Back-off restarting failed container my-container in pod my-app-xxx Warning Unhealthy 1m (x2 over 2m) kubelet Readiness probe failed: HTTP probe failed with statuscode: 503 Last State: Terminated: Exit Code: 1 Reason: Error Message: Application startup failed 从上面的例子可以看出,应用程序启动失败,导致容器退出。
查看容器的日志: 使用
kubectl logs <pod-name> -c <container-name> -n <namespace>
命令,查看容器的日志,看看有没有报错信息。注意要加上--previous
参数,查看之前的日志,因为容器可能已经重启了。kubectl logs my-app -c my-container -n my-namespace --previous
如果日志里有错误,赶紧修复。如果日志里没有错误,可以尝试增加日志级别,或者在容器启动时输出更多的调试信息。
进入容器内部调试: 如果容器允许进入,使用
kubectl exec -it <pod-name> -c <container-name> -- /bin/bash
命令,进入容器内部,进行调试。注意,由于容器一直在崩溃重启,你可能需要快速进入容器,才能进行调试。kubectl exec -it my-app -c my-container -- /bin/bash
检查资源限制: 检查 Pod 的资源限制(CPU、内存),看看是否超过了 Node 的可用资源。如果超过了,可以调整资源限制,或者优化你的应用。
2.6 Unknown(未知)
含义: K8s 无法获取 Pod 的状态。通常是因为 K8s 与 Node 的连接出现了问题。就像你联系不上你的快递员了。
常见原因:
- 网络问题: K8s 集群的网络出现问题,导致 K8s 无法与 Node 通信。
- Node 故障: Node 出现故障,比如宕机、网络中断等。
- kubelet 故障: Node 上的 kubelet 服务出现问题,导致 K8s 无法获取 Pod 的状态。
排查方法:
检查 Node 的状态: 使用
kubectl get nodes
命令,查看 Node 的状态。如果 Node 状态是 NotReady,说明 Node 出现了问题。kubectl get nodes
NAME STATUS ROLES AGE VERSION node-xxx Ready <none> 1d v1.20.0 node-yyy NotReady <none> 1d v1.20.0 检查 K8s 集群的网络: 检查 K8s 集群的网络配置,确保网络正常。可以使用
kubectl get pods -A
命令,查看所有 Pod 的状态,看看是否所有 Pod 都处于 Unknown 状态,或者只有部分 Pod 处于 Unknown 状态。如果只有部分 Pod 处于 Unknown 状态,可能是 Node 上的网络问题。kubectl get pods -A
检查 Node 的日志: 登录到 Node 上,查看 kubelet 的日志,看看是否有错误信息。
journalctl -u kubelet
重启 kubelet: 如果 kubelet 出现问题,可以尝试重启 kubelet 服务。
systemctl restart kubelet
3. 总结:Pod 状态,运维的眼睛
Pod 的状态就像运维的眼睛,时刻监视着应用的运行状况。掌握 Pod 的各种状态,了解导致这些状态的原因,以及如何排查问题,是每个 K8s 运维工程师必备的技能。希望这篇文章能帮到你,让你在 K8s 的世界里畅游无阻!
记住,遇到问题别慌,多查日志,多用 kubectl
命令,你就能搞定!加油,老兄!
4. 附录:常用 kubectl 命令
kubectl get pod <pod-name> -n <namespace>
:查看 Pod 的状态kubectl describe pod <pod-name> -n <namespace>
:查看 Pod 的详细信息,包括 Eventskubectl logs <pod-name> -c <container-name> -n <namespace>
:查看容器的日志kubectl logs <pod-name> -c <container-name> -n <namespace> --previous
:查看容器之前的日志kubectl exec -it <pod-name> -c <container-name> -- /bin/bash
:进入容器内部调试kubectl get nodes
:查看 Node 的状态kubectl get pvc -n <namespace>
:查看 PVC 的状态kubectl get pv
:查看 PV 的状态kubectl get svc -n <namespace>
:查看服务的状态kubectl get pods -A
:查看所有 Pod 的状态
希望这些命令能帮助你更好地排查问题!