Skip to content

Pod 生命周期

Pod 是 Kubernetes 最小调度单元。排查 K8s 服务时,Pod 生命周期是最常看的部分:是否被调度、是否拉动镜像、是否挂载成功、容器是否启动、探针是否通过、退出后是否重启。

Pod 从创建到运行

常见阶段:

阶段说明常见问题
Pending尚未完成调度或依赖准备资源不足、污点、PVC 未绑定
ContainerCreating节点正在创建容器拉镜像、挂载卷、CNI 分配 IP
Running至少一个容器运行中应用不一定 Ready
Succeeded所有容器正常结束Job 常见
Failed容器异常结束且不再重启Job 或 restartPolicy 相关

Running 只是容器层状态,不等于业务可用。Service 是否接流量主要看 readiness probe。

initContainer

initContainer 在业务容器之前执行,全部成功后才会启动普通容器:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  initContainers:
    - name: wait-db
      image: busybox:1.36
      command: ["sh", "-c", "until nc -z mysql 3306; do sleep 2; done"]
      # 等待数据库端口可连,只适合做粗略依赖检查
  containers:
    - name: app
      image: nginx:1.26

initContainer 常用于初始化目录、等待依赖、生成配置、迁移简单文件。数据库 schema 迁移这类操作要谨慎——失败重试和并发执行都要设计清楚,initContainer 只保证顺序,不保证幂等。

重启策略

Pod 级别有 restartPolicy

策略含义
Always容器退出后总是重启——Deployment 默认
OnFailure非 0 退出码才重启——Job 常见
Never退出后不重启

Deployment 里的 Pod 通常是 Always。Job 更常用 OnFailureNever,否则任务失败后的行为难以判断。

三种探针

探针作用典型用法
startupProbe判断应用是否启动完成启动慢的服务用它保护,等启动完成后再让 livenessProbe 接管
readinessProbe判断是否可以接流量失败后从 Service 后端摘除,不影响容器进程
livenessProbe判断是否需要重启容器失败后 kubelet 重启容器——是修复手段,不要因为外部依赖挂了就杀容器
yaml
startupProbe:
  httpGet:
    path: /healthz
    port: 8080
  failureThreshold: 30   # 最多等 30 × 2 秒
  periodSeconds: 2
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  periodSeconds: 5
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  periodSeconds: 10
  failureThreshold: 3

没有 startupProbe 时,启动慢的应用可能被 livenessProbe 反复重启——应用还在初始化,liveness 已经判定失败。startupProbe 的作用就是覆盖启动窗口。

readinessProbe 决定了 Service 是否把流量发给这个 Pod。没有 readinessProbe 时,容器进程一启动就可能被认为可接流量——Java 服务、需要加载缓存的服务、启动后要连外部依赖的服务容易出现"Pod Running 但请求失败"。

容器状态

bash
kubectl get pod <pod-name> -n <namespace> -o wide
kubectl describe pod <pod-name> -n <namespace>
kubectl get pod <pod-name> -n <namespace> \
  -o jsonpath='{.status.containerStatuses[*].state}{"\n"}'

常见状态:

状态说明
Waiting等待中——拉镜像、创建容器、退避重启
Running容器进程运行中
Terminated容器已退出,有 exitCode 和 reason

查看上一次退出信息:

bash
kubectl get pod <pod-name> -n <namespace> \
  -o jsonpath='{.status.containerStatuses[0].lastState.terminated}{"\n"}'

日志和事件

bash
kubectl logs <pod-name> -n <namespace>             # 当前容器日志
kubectl logs <pod-name> -n <namespace> --previous  # 上一次崩溃前的日志
kubectl logs <pod-name> -n <namespace> -c <container-name>  # 多容器 Pod 指定容器
kubectl get events -n <namespace> --sort-by=.lastTimestamp

事件偏平台动作(调度、拉镜像、挂载卷),日志偏应用进程。ImagePullBackOff、FailedMount、FailedScheduling 这类问题,事件比应用日志更有用。平台还没把容器启动起来时,应用日志经常是空的。

常见状态处理

状态常见原因查看方向
Pending调度失败、PVC 未绑定describe pod、节点资源、PVC
ImagePullBackOff镜像名写错、仓库认证、网络不通Events、节点 crictl pull
ContainerCreatingCNI 分配 IP、挂载卷、运行时创建 sandboxEvents、kubelet 日志
CrashLoopBackOff程序启动后退出logs --previous、exitCode
OOMKilled内存超过 limit容器 lastState、资源配置

排查 Pod 时先看 Events 再查日志。如果 Events 显示还在 ContainerCreating,应用日志肯定还没有——从平台层开始,一层一层往里看。