深色模式
Pod 生命周期与重启策略
摘要:本文面向生产 SRE 与平台工程师,系统讲解 Pod 从创建到终止的完整生命周期,重点剖析
phase、容器状态、restartPolicy与优雅终止。覆盖 Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+(文中
phase行为、terminationGracePeriodSeconds等以 v1.27+ 为准) - 工具:
kubectl - 前提:已具备集群访问权限,了解 Pod 基本结构
背景与问题
Pod 是 Kubernetes 中最小的可部署单元,但“最小”并不等于“简单”。一个 Pod 在集群中的真实状态往往与直觉不符:你看到的 STATUS 是 kubectl 的展示字段(CrashLoopBackOff、Terminating 等),而 API 数据模型里的 status.phase 只有五个取值。混淆二者是排障时最常见的误区之一。理解 Pod 生命周期,是理解探针、重启、驱逐、滚动更新一切机制的基础。
核心概念:Pod phase
Pod 的 status.phase 是对其生命周期位置的高层摘要,取值被严格限定为五个:
| phase | 含义 |
|---|---|
Pending | 已被集群接受,但至少一个容器尚未创建并运行(含调度等待、镜像拉取) |
Running | 已绑定节点,所有容器已创建,且至少一个容器在运行/启动/重启中 |
Succeeded | 所有容器成功终止,且不会被重启 |
Failed | 所有容器终止,且至少一个以失败方式终止(非 0 退出或被系统终止) |
Unknown | 无法获取 Pod 状态,通常因节点与控制面通信失败 |
注意
CrashLoopBackOff 与 Terminating 是 kubectl 展示用字段,不是 phase。phase 是显式数据模型字段,不要混用。例如一个反复启动失败的 Pod,其 phase 可能仍是 Running(因为容器在反复重启中),而 STATUS 显示为 CrashLoopBackOff。
容器状态
Pod 内的每个容器有三个状态:Waiting、Running、Terminated。
Waiting:仍在做启动前的准备(拉镜像、挂载 Secret 等),可通过Reason字段判断卡点。Running:正在执行;若配了postStarthook,则在postStart完成后才进入。Terminated:已执行完毕或失败,可见Reason、Exit Code、起止时间。若配了preStophook,则在进入Terminated前执行。
bash
kubectl describe pod <pod-name>
# 查看容器状态与 Reason,定位 Pending/Waiting 卡点
kubectl get pod <pod-name> -o jsonpath='{.status.phase}'
# 直接读取数据模型中的 phase,而非依赖 STATUS 展示字段1
2
3
4
5
2
3
4
5
重启策略 restartPolicy
Pod 级别的 spec.restartPolicy 决定容器退出后 kubelet 如何处理,取值为 Always、OnFailure、Never,默认 Always。它适用于应用容器与常规 init 容器。
yaml
apiVersion: v1
kind: Pod
metadata:
name: restart-demo
labels:
app: restart-demo
spec:
restartPolicy: OnFailure # Always / OnFailure / Never
containers:
- name: app
image: busybox:1.28
command: ['sh', '-c', 'echo running; sleep 30; exit 1']1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
三种策略的语义:
Always:无论退出码如何都重启。适合长期运行的服务(Deployment/ReplicaSet 默认)。OnFailure:仅非零退出码时重启。适合需要重试一次的批处理。Never:绝不重启,容器状态保持Terminated。适合一次性任务(Job 使用)。
版本相关
Init 容器若失败,kubelet 会按 Pod 级 restartPolicy 为 OnFailure 或 Always 时重试;若 Pod 级为 Never 且 init 失败,整个 Pod 被判为失败。自 v1.20 起,修改 init 容器镜像不会重启 Pod。Sidecar 容器(定义在 initContainers 且 restartPolicy: Always)忽略 Pod 级 restartPolicy,详见《Init Container 与 Sidecar 模式》。
优雅终止机制
Pod 被删除时,kubelet 给容器发送 SIGTERM,并等待优雅终止窗口(默认 30 秒,由 terminationGracePeriodSeconds 控制)。窗口耗尽后发送 SIGKILL。
yaml
spec:
terminationGracePeriodSeconds: 30 # 生产建议显式设置,给业务足够排水时间1
2
2
自 Kubernetes v1.27 起,被删除的 Pod(除静态 Pod 与无 finalizer 的强制删除外)在从 API server 移除前,会先被 kubelet 转为终态(Succeeded 或 Failed,取决于容器退出状态)。
生产实践
- 明确设置
terminationGracePeriodSeconds:默认 30s 对需要排水连接、刷盘的服务可能不足。结合preStophook 做连接排水(如从 LB 摘除)。 - 不要依赖
STATUS做自动化判断:告警与脚本应读取status.phase与status.conditions。 restartPolicy与控制器匹配:Deployment/StatefulSet 内 Pod 应Always;Job 必须OnFailure或Never(Job 禁止Always)。- 节点失联后的终态:节点宕机或失联,控制面会在超时后将节点上所有 Pod 的
phase置为Failed,这些 Pod 不会被自动重建到其它节点(除非由控制器管理)。
生产危险
强制删除 Pod(kubectl delete pod --force --grace-period=0)会跳过优雅终止,可能导致数据损坏或请求被中断。仅在 Pod 已卡死、无法优雅退出时作为最后手段,且执行前确认业务影响。
故障排查
| 现象 | 可能原因 | 排查命令 |
|---|---|---|
Pending 长时间 | 调度失败(资源不足、污点、PVC 未绑定) | kubectl describe pod 看 Events;kubectl get events |
ImagePullBackOff | 镜像名错误、仓库不可达、Secret 缺失 | kubectl describe pod 的 Reason |
CrashLoopBackOff | 应用启动即退出、探针误配、依赖未就绪 | kubectl logs <pod> 与 kubectl describe |
Terminating 卡住 | finalizer 未释放、宽限期过长、preStop 阻塞 | kubectl get pod -o yaml 看 finalizers |
常见坑
--force删除跳过了SIGTERM,容易掩盖真正的退出原因。- init 容器失败会导致整个 Pod 卡在
Init:N/M,主容器永远不会启动。 - 节点
NotReady后,其上 Pod 进入Unknown,但控制器(如 Deployment)会在其它节点重建副本,可能造成“双写”或短暂重复处理,需业务幂等。
替代方案与权衡
- 对于需要稳定身份与存储的工作负载,Pod 本身不够,应使用 StatefulSet(见《StatefulSet 有状态应用编排》)。
- 对于一次性任务,直接用 Job 而非裸 Pod,可获得重试与完成跟踪。
- 对于节点级常驻守护进程,使用 DaemonSet 而非手动裸 Pod,以获得自愈与滚动更新。
FAQ
Q:phase=Running 但应用实际不可用,为什么? A:phase 只表示容器进程在运行,不代表业务健康。健康与否由 Readiness 探针决定,详见《健康检查三大探针》。
Q:Pod 一直 Unknown 能恢复吗? A:取决于节点是否回归。节点恢复通信后状态会重新上报;若节点永久丢失,需依赖上层控制器在其它节点重建(裸 Pod 不会)。
参考资料
- Pod Lifecycle - Kubernetes 官方文档,访问日期:2026-10-08。
- Container Probes - Kubernetes 官方文档,访问日期:2026-10-08。
- Pod 终止与优雅退出 - Kubernetes 官方文档,访问日期:2026-10-08。