前言:那些年我们一起踩过的坑
我刚开始用 K8s 那会儿,经常被 Pod 的各种状态搞得晕头转向。最经典的一次,我看到一个 Pod明明显示 Running,但服务死活访问不通。我对着屏幕抓耳挠腮,查了半天日志,最后才发现——Running 状态,并不代表你的应用就真的“准备好”对外服务了!
这个坑,几乎每个 K8s 新手都会踩。为了让大家少走弯路,今天我就以一个“过来人”的身份,带你彻底搞懂 Pod 的生命周期和状态,让你下次排查问题时,能像老司机一样从容不迫。
把 Pod 生命周期想象成一笔“外卖订单”
官方的定义总是干巴巴的,我们不妨用一个更接地气的比喻来理解 Pod 的生命周期:
-
Pending (待接单): 你刚下完单,系统已经收到了你的请求,但还没分配骑手。
-
对应到 K8s,就是 Pod 创建请求已被接受,但容器还没创建好。可能是在找合适的节点(饭店),或者在下载镜像(备餐)。
-
Running (配送中): 骑手已经取餐,正在飞速赶来。
-
对应到 K8s,就是 Pod 已经绑定到节点上,容器也创建好了。但注意! 骑手在路上可能遇到堵车(应用还在启动),或者走错路(应用启动失败在疯狂重启)。
-
Succeeded (订单完成): 外卖已送达,你心满意足地给了五星好评。
-
对应到 K8s,就是 Pod 里的所有容器都正常执行完毕并退出了。这通常用于一次性的任务,比如一个
Job。 -
Failed (订单异常): 骑手送错了地址,或者餐厅漏做了你的菜,订单失败。
-
对应到 K8s,就是 Pod 里至少有一个容器异常退出了(比如程序 bug、OOMKilled)。
-
Unknown (联系不上骑手): 你完全看不到骑手的实时位置,电话也打不通。
-
对应到 K8s,就是因为某些原因(比如节点失联),
kubelet无法上报 Pod 的状态。
核心状态详解:别只看表面!
1. Pending (悬决)
当你看到这个状态,别慌,它只是在告诉你:“我正在准备,请稍等”。
常见原因:
-
调度不成功: 集群里没有节点能满足 Pod 的资源要求(CPU、内存、GPU等)。
-
镜像拉取慢: 镜像太大了,或者网络不给力。
-
存储卷未就绪: Pod 依赖的 PVC 还没准备好。
2. Running (运行中)
这是最迷惑人的状态!
大坑警告!这是新手最容易踩的坑,没有之一!
Running≠Ready
Running≠ 服务可用
Running 仅仅表示 Pod 里的容器进程已经启动了。但你的应用程序可能还在初始化,或者正在等待依赖的服务就绪。它到底能不能处理请求,Running 状态说了不算。
那听谁的?听 Readiness Probe (就绪探针) 的。只有就绪探针检查通过了,K8s 才会认为这个 Pod 是“Ready”状态,并把它加入 Service 的后端 Endpoint 列表,开始接收流量。
3. Succeeded (成功) & Failed (失败)
这两个是终结状态,代表 Pod 的生命周期已经结束。通常在 Job 或 CronJob 这类批处理任务中看到。Succeeded 是圆满完成,Failed 是不幸翻车。
4. Unknown (未知)
这是最不希望看到的状态。它意味着节点“失联”了,kubelet 无法向主节点汇报心跳和 Pod 状态。通常是节点宕机或者网络分区导致的。
实战排查指南:我的 Pod 怎么了?
遇到问题别怕,我们用 Q&A 的形式来快速定位。
Q1: 我的 Pod 为什么一直是 Pending?
A: 这是在“等资源”。用 kubectl describe pod <pod-name> 查看 Events 部分,通常会告诉你原因:
-
0/3 nodes are available: 3 Insufficient cpu.-> 资源不足,要么加节点,要么减少 Pod 的 request。 -
Failed to pull image "my-app:v2": rpc error: code = Unknown desc = Error response from daemon: manifest for my-app:v2 not found-> 镜像拉取失败,检查镜像名称和 Tag 是否正确。 -
pod has unbound immediate PersistentVolumeClaims-> PVC 未绑定,检查你的 StorageClass 和 PV/PVC 配置。
Q2: Pod 状态是 Running,为什么服务还是访问不通?
A: 经典问题!Running 只是个“假象”,按以下步骤排查:
-
查
Ready状态: 运行kubectl get pod <pod-name>,看READY那一列是不是1/1(或者n/n)。如果不是1/1,说明就绪探针没通过。 -
查探针失败原因: 运行
kubectl describe pod <pod-name>,看Events里有没有Readiness probe failed的警告,它会告诉你探针失败的具体原因。 -
查容器日志:
kubectl logs <pod-name>,看看你的应用程序是不是在启动时就报错了。
Q3: Pod 怎么就 Failed 了?
A: 程序挂了。
- 看退出码 (Exit Code):
kubectl describe pod <pod-name>,找到State: Terminated下的Exit Code。
-
Exit Code: 0表示正常退出。 -
Exit Code: 1通常是通用错误。 -
Exit Code: 137表示被OOMKilled(内存超限)。 -
Exit Code: 143表示收到了SIGTERM信号被正常终止。
-
查日志:
kubectl logs --previous <pod-name>可以看到上一次容器崩溃前的日志,这通常是定位问题的关键。
Q4: 为什么 Pod 状态是 Unknown?
A: 节点失联了。
-
查节点状态:
kubectl get nodes,看看出问题的 Pod 所在的节点是不是NotReady状态。 -
登录节点排查: 如果可以,SSH 到那个
NotReady的节点上,检查kubelet服务的状态和日志 (journalctl -u kubelet),同时检查网络连接。
总结:告别“差不多先生”
希望这篇“踩坑”总结能帮你彻底搞懂 Pod 的状态。记住,最关键的一点是:不要再把 Running 当成 Ready 了!
理解了这些状态背后的真正含义,你就能从一个只会 kubectl apply 的“操作员”,进阶为能洞察系统状态、从容解决问题的“工程师”。下次再遇到 Pod 状态异常时,希望你不再慌张,而是能自信地打开终端,一步步定位问题。