4. Pod 故障域:Pod 生命周期与状态机

Pod 是 Kubernetes 中最小的调度与故障单元。理解 Pod 的状态机转换,是定位容器级故障的前提。本章从架构视角拆解 Pending → Running → Failed 的完整路径,并重点分析 Sidecar 模式下的多容器故障隔离策略。

4.1 Pod 状态机与故障注入点

Pod 的状态由 status.phase 字段定义,共 5 个阶段。SRE 排错时,需要根据当前阶段快速定位故障域:

Phase 含义 常见故障原因 kubectl debug 切入点
Pending Pod 已被 API Server 接受,但尚未调度或镜像拉取中 资源不足、PVC 绑定失败、镜像不存在、节点选择器不匹配 kubectl describe pod 查看 Events
Running 至少一个容器正在运行,或正在启动/重启 容器 CrashLoopBackOff、Readiness 探测失败、OOMKill kubectl logs --previous + kubectl exec
Succeeded 所有容器正常退出(退出码 0) Job 完成,通常无需排错 —
Failed 至少一个容器以非零退出码终止 应用崩溃、配置错误、资源耗尽 kubectl logs --tail=50 + 查看 exit code
Unknown 节点失联或 kubelet 未上报状态 节点宕机、网络分区、kubelet 挂死 kubectl get node + 节点级排查
排错黄金法则: 先看 kubectl get pod -o wide 确认 Pod 所在节点与 IP,再用 kubectl describe pod 检查 Conditions 与 Events 字段。80% 的 Pending 故障在 Events 中直接暴露原因。

4.2 Pending 阶段:调度与初始化故障域

Pod 停留在 Pending 阶段,意味着调度器尚未将 Pod 分配到节点,或 kubelet 在启动容器前被阻塞。故障域分为两层:

  • 调度层(Scheduler): 节点资源不足(CPU/Memory/GPU)、节点亲和性/反亲和性不满足、污点容忍度缺失、PVC 未绑定。
  • 初始化层(kubelet): 镜像拉取失败(ImagePullBackOff)、Secret 不存在、卷挂载失败、Init 容器异常退出。
快速定位技巧: 使用 kubectl get events --field-selector involvedObject.name=<pod-name> --sort-by=.lastTimestamp 按时间排序事件,第一条 Warning 事件通常就是根因。

4.3 Running 阶段:容器运行时故障域

Pod 进入 Running 阶段后,故障域从调度层转移到容器运行时层。此时需要区分 临时故障 与 永久故障:

故障模式 kubectl 观测指标 典型根因 隔离手段
CrashLoopBackOff kubectl logs --previous 显示退出码非 0 应用初始化失败、配置错误、依赖服务不可用 临时副本替换 + 保留旧 Pod 日志
OOMKilled kubectl describe pod 显示 OOMKilled 状态 内存 limit 设置过小、内存泄漏 调整 resources.limits.memory
Readiness 探测失败 Pod 状态 Running 但 Ready 列为 0/1 应用未就绪、健康检查路径错误 kubectl exec 手动探测端点
Liveness 探测失败 Pod 频繁重启,restarts 计数递增 应用死锁、goroutine 泄漏、死循环 临时关闭探测 + 抓取堆栈

4.4 Pod 生命周期状态机 SVG

下图展示了 Pod 从创建到终止的完整状态转换路径,以及每个阶段对应的故障注入点:

Pod 生命周期状态机与故障域 Pod 生命周期状态机与故障域 Pending 调度/镜像/卷 Running 容器运行时 Succeeded 正常退出 Failed 非零退出码 Unknown 节点失联 故障域划分说明: • Pending → Running:调度故障域(资源、亲和性、PVC)与初始化故障域(镜像、卷、Init 容器) • Running → Failed:运行时故障域(CrashLoopBackOff、OOM、探测失败) • Running → Unknown:节点故障域(kubelet 失联、网络分区)

4.5 Pod 内多容器故障隔离:Sidecar 模式

生产环境中,Pod 内常包含多个容器(Sidecar 模式),例如日志采集、指标暴露、网络代理等辅助容器。多容器共享同一网络命名空间与存储卷,但 故障域相互独立。

4.6 Sidecar 故障隔离原则

  • 进程级隔离: 每个容器拥有独立的 PID 命名空间(默认不共享),一个容器的 OOM 或崩溃不会直接杀死其他容器。
  • 资源隔离: 每个容器独立设置 resources.requests/limits,Sidecar 的 CPU 争抢不会导致主容器饥饿。
  • 健康检查独立: Liveness/Readiness 探测按容器配置,Sidecar 挂死不影响主容器的 Ready 状态(除非自定义 Readiness 聚合)。
  • 日志与监控隔离: 使用 kubectl logs -c <container-name> 按容器过滤日志,避免 Sidecar 日志淹没主容器错误。
常见陷阱: 部分团队将 Sidecar 与主容器放在同一个 securityContext 下,或错误地共享 shareProcessNamespace: true,导致 Sidecar 崩溃后主容器也被迫重启。除非明确需要进程间通信,否则不要开启进程命名空间共享。

4.7 多容器故障隔离 SVG

下图展示了 Sidecar 模式下,主容器与辅助容器的故障隔离边界:

Sidecar 模式多容器故障隔离 Sidecar 模式多容器故障隔离 Pod 边界(共享 Network + Volume) 主容器 应用进程 Liveness / Readiness 探测 资源: CPU 2 / Mem 4Gi PID 命名空间: 独立 退出码: 非 0 → Pod Failed 故障隔离墙 Sidecar 容器 日志采集 / 指标暴露 Liveness / Readiness 探测 资源: CPU 0.5 / Mem 512Mi PID 命名空间: 独立 退出码: 非 0 → 仅重启 Sidecar 共享网络命名空间(localhost 通信) + 共享 EmptyDir Volume(日志文件交换)

4.8 Sidecar 故障场景与排错命令

故障场景 现象 排错命令 隔离效果
Sidecar OOMKilled 主容器正常运行,Sidecar 不断重启 kubectl logs -c sidecar --previous 主容器无影响,仅 Sidecar 重启
Sidecar 死锁导致 Liveness 失败 Sidecar 被 kubelet 重启,主容器不受影响 kubectl describe pod 查看 Sidecar 容器状态 主容器继续服务,Sidecar 自动恢复
主容器崩溃退出 Pod 进入 CrashLoopBackOff,Sidecar 也被迫停止 kubectl logs --previous -c main Pod 整体重启,Sidecar 随 Pod 重建
Sidecar 日志阻塞磁盘 主容器写日志失败,但进程未崩溃 kubectl exec -c sidecar -- df -h 共享卷写满,影响所有容器
架构建议: 对于关键 Sidecar(如 Istio Proxy、日志采集器),应设置独立的 resources.requests 与 resources.limits,并配置 restartPolicy: Always。同时使用 kubectl top pod --containers 按容器维度监控资源消耗,避免 Sidecar 资源泄漏影响主容器。

4.9 排错流程总结

  1. 确定 Pod Phase: kubectl get pod <name> -o jsonpath='{.status.phase}'
  2. 检查 Events: kubectl describe pod <name> | grep -A 10 Events
  3. 按容器过滤日志: kubectl logs <name> -c <container> --tail=100
  4. 检查容器退出码: kubectl get pod <name> -o jsonpath='{.status.containerStatuses[*].state.terminated.exitCode}'
  5. 资源隔离验证: kubectl exec -c main -- cat /sys/fs/cgroup/memory/memory.limit_in_bytes
  6. 网络隔离验证: kubectl exec -c sidecar -- curl localhost:8080/healthz
生产级排错技巧: 在 Sidecar 容器中预装 curl、tcpdump、strace 等调试工具,并暴露一个专用的调试端口(如 10001),避免在主容器中安装额外二进制。使用 kubectl debug -c sidecar --image=nicolaka/netshoot:latest --target=sidecar 启动临时调试容器,不污染生产容器。