K8s Pod 状态详解:Running 不等于 Ready !

366 阅读5分钟

前言:那些年我们一起踩过的坑

我刚开始用 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 (运行中)

这是最迷惑人的状态!

大坑警告!这是新手最容易踩的坑,没有之一!

RunningReady

Running ≠ 服务可用

Running 仅仅表示 Pod 里的容器进程已经启动了。但你的应用程序可能还在初始化,或者正在等待依赖的服务就绪。它到底能不能处理请求,Running 状态说了不算。

那听谁的?听 Readiness Probe (就绪探针) 的。只有就绪探针检查通过了,K8s 才会认为这个 Pod 是“Ready”状态,并把它加入 Service 的后端 Endpoint 列表,开始接收流量。

3. Succeeded (成功) & Failed (失败)

这两个是终结状态,代表 Pod 的生命周期已经结束。通常在 JobCronJob 这类批处理任务中看到。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 只是个“假象”,按以下步骤排查:

  1. Ready 状态: 运行 kubectl get pod <pod-name>,看 READY 那一列是不是 1/1 (或者 n/n)。如果不是 1/1,说明就绪探针没通过。

  2. 查探针失败原因: 运行 kubectl describe pod <pod-name>,看 Events 里有没有 Readiness probe failed 的警告,它会告诉你探针失败的具体原因。

  3. 查容器日志: kubectl logs <pod-name>,看看你的应用程序是不是在启动时就报错了。

Q3: Pod 怎么就 Failed 了?

A: 程序挂了。

  1. 看退出码 (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 信号被正常终止。

  1. 查日志: kubectl logs --previous <pod-name> 可以看到上一次容器崩溃前的日志,这通常是定位问题的关键。

Q4: 为什么 Pod 状态是 Unknown

A: 节点失联了。

  1. 查节点状态: kubectl get nodes,看看出问题的 Pod 所在的节点是不是 NotReady 状态。

  2. 登录节点排查: 如果可以,SSH 到那个 NotReady 的节点上,检查 kubelet 服务的状态和日志 (journalctl -u kubelet),同时检查网络连接。

总结:告别“差不多先生”

希望这篇“踩坑”总结能帮你彻底搞懂 Pod 的状态。记住,最关键的一点是:不要再把 Running 当成 Ready 了!

理解了这些状态背后的真正含义,你就能从一个只会 kubectl apply 的“操作员”,进阶为能洞察系统状态、从容解决问题的“工程师”。下次再遇到 Pod 状态异常时,希望你不再慌张,而是能自信地打开终端,一步步定位问题。