bigywater.tech
Kubernetes · 29

Pod 生命周期:phase、conditions 与容器状态

kubectl get pod 的 STATUS 一栏、Pod 的 phase、conditions、容器 state,到底谁是谁?为什么 Running 的 Pod 还没就绪、为什么 Terminating 在 phase 里找不到?这篇用几个故意卡在不同位置的 Pod,把三层状态各自在什么时候变、和 kubectl 的显示怎么对应都量出来。

+0.0s → +0.7s
Pod ok 从 Pending 到 Running 的时间;Ready 还要等就绪探针通过
Running + Ready=False
就绪探针未通过时 Pod 的 phase 与 Ready 条件
Terminating 不是 phase
删除一个不响应 SIGTERM 的 Pod:phase 仍是 Running,21 秒后才消失

Running 不等于 Ready

实测 · 本机执行输出
  Pod ok(readinessProbe 检查 /tmp/ready 是否存在,一开始没有这个文件):
    + 0.0s phase=Pending   PodScheduled=True  Initialized=True  ContainersReady=False Ready=False 容器=waiting(ContainerCreating)
    + 0.7s phase=Running   PodScheduled=True  Initialized=True  ContainersReady=False Ready=False 容器=running
  在容器里创建 /tmp/ready 之后 2.5 秒:phase=Running Ready=True ContainersReady=True 容器 ready=True

带就绪探针的 Pod 启动过程:+0.0 秒 phase=Pending(容器 ContainerCreating),这时 PodScheduled、Initialized 已经是 True;+0.7 秒 phase=Running,容器已经启动,但 ContainersReady 和 Ready 仍是 False,因为探针检查的 /tmp/ready 还不存在。创建这个文件之后 Ready 才变成 True。Service 只会把 Ready 的 Pod 加入后端,所以“Running”并不意味着能收流量。

卡在不同位置的 Pod

实测 · 本机执行输出
  nosched   phase=Pending    Ready=None 容器状态=-;PodScheduled=False reason=Unschedulable message=0/3 nodes are available: 1 node(s) had untolerated taint(s), 2 node(s) didn't ma
  badimg    phase=Pending    Ready=False 容器状态=waiting(ContainerCreating);waiting.reason=ContainerCreating
  oneshot   phase=Succeeded  Ready=False 容器状态=terminated(Completed);exitCode=0 reason=Completed
  failing   phase=Failed     Ready=False 容器状态=terminated(Error);exitCode=3 reason=Error
  kubectl get pod 的 STATUS 列(和 phase 不是一回事):badimg=ContainerCreating | failing=Error | nosched=Pending | ok=Running | oneshot=Completed

nodeSelector 无节点匹配的 Pod:phase=Pending,PodScheduled=False,reason Unschedulable,message 0/3 nodes are available: …;镜像标签不存在的 Pod:phase=Pending,容器 waiting(ContainerCreating)——这台机器拉不到镜像,将近一分钟后还没有走到 ErrImagePull;restartPolicy: Never 的 echo 成功是 Succeeded,exit 3 是 Failed(容器 terminated(Error)、exitCode=3)。kubectl get 的 STATUS 列(ContainerCreating、Error、Completed……)是 kubectl 综合 phase 和容器状态算出来的,不是 phase。

Terminating

实测 · 本机执行输出
  Pod slow(sh -c "sleep 3600" 作为 1 号进程不处理 SIGTERM,terminationGracePeriodSeconds=20)执行 kubectl delete 1 秒后:phase=Running;metadata.deletionTimestamp=有;deletionGracePeriodSeconds=20;容器状态=running
  kubectl get pod slow 的 STATUS 列:Terminating
  最终在 21 秒后被 SIGKILL 并消失(Pod 对象被删除)

删除一个不处理 SIGTERM 的 Pod(sh -c "sleep 3600" 作 1 号进程):1 秒后 phase 仍是 Running,metadata.deletionTimestamp 已设置,deletionGracePeriodSeconds=20,容器还在运行,kubectl get 显示 Terminating。要等满 20 秒的宽限期,进程被 SIGKILL,Pod 对象才消失(这次 21 秒)。Terminating 是展示层的说法,不是 phase 的取值。

重启不改变 phase

实测 · 本机执行输出
  restartPolicy=OnFailure、容器 3 秒后 exit 1,30 秒后:phase=Running restartCount=2 当前 state=terminated lastState.terminated(exitCode=1,reason=Error)
  Ready=False(容器在两次重启之间不就绪);phase 一直是 Running,不会因为反复崩溃变成 Failed

restartPolicy: OnFailure、3 秒后 exit 1 的容器,30 秒内重启了 2 次:restartCount=2,当前 state=terminated,lastState.terminated 记着上一次的 exitCode=1、reason=Error;Ready=False(两次重启之间容器不就绪),phase 却一直是 Running。反复崩溃的 Pod 不会变成 Failed,看崩溃要看 restartCount 和 lastState。

分步演示

Pod 状态层次
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0);Pod 状态每 0.25 秒用 kubectl get pod -o json 读一次并记录变化;ok 的就绪探针是 exec 检查 /tmp/ready,periodSeconds=1;busybox:1.36 已预先加载进节点,所以 ok 的启动只用了不到 1 秒;badimg 用的镜像标签不存在,本机拉不到镜像,约 1 分钟时仍在 ContainerCreating;每种情形各一次
    • 没有验证:phase=Unknown(节点失联时);ImagePullBackOff / ErrImagePull 的状态切换(本机拉取失败太慢);init 容器、sidecar 对 conditions 的影响(后面有专门的文章);Pod 的 readinessGates 与 DisruptionTarget 等较新的 condition;kubectl get 计算 STATUS 列的完整规则;preStop 钩子对终止过程的影响
    京ICP备2026067502号-1京公网安备11010502063487号