1. CrashLoop 概念与现象

1.1 什么是 CrashLoopBackOff

CrashLoopBackOff 是 Kubernetes 中 Pod 处于反复启动-崩溃-再启动循环状态时的最终状态标识。当 Pod 内的容器在启动后短时间内持续退出(非 0 退出码),kubelet 会按照指数退避策略逐步增加重启间隔,并将 Pod 状态标记为 CrashLoopBackOff。

核心判定条件:Pod 状态为 CrashLoopBackOff 且 RESTARTS 列持续增长,即表明容器陷入崩溃循环。
状态名称 含义 触发条件
CrashLoopBackOff 容器崩溃循环,kubelet 正在退避等待 容器启动后短时间内退出,且重启次数 ≥ 1
Init:CrashLoopBackOff Init 容器崩溃循环 Init 容器启动后持续退出
Error 容器启动失败但未进入循环 容器退出码非 0,但尚未触发退避策略

1.2 Pod 重启策略

Pod 的 restartPolicy 字段决定了容器退出后 kubelet 的行为。三种策略对 CrashLoop 的影响截然不同:

  • Always(默认):无论退出码如何,kubelet 始终重启容器。这是 CrashLoop 最常见的触发策略。
  • OnFailure:仅在容器退出码非 0 时重启。若容器因 OOMKilled(退出码 137)退出,会触发重启;若正常退出(退出码 0),则不重启。
  • Never:从不重启容器。容器退出后 Pod 进入 Completed 或 Error 状态,不会产生 CrashLoop。
排障提示:排查 CrashLoop 时,首先确认 restartPolicy 是否为 Always 或 OnFailure。若为 Never,则不会出现 CrashLoopBackOff 状态。

1.3 CrashLoop 的典型表现

CrashLoop 在集群运维中有多个可观测维度,以下为最常见的表现特征:

  1. kubectl 输出特征:kubectl get pods 显示 STATUS 列为 CrashLoopBackOff,RESTARTS 列数值持续增长。
  2. Pod 生命周期短:容器从启动到退出通常不超过 30 秒,部分场景甚至不足 1 秒。
  3. 重启间隔指数增长:首次重启间隔 10 秒,后续依次为 20 秒、40 秒、80 秒……最大间隔 5 分钟。
  4. 日志重复出现:kubectl logs 每次查看均为相同的错误日志,无新输出。
  5. 事件风暴:kubectl describe pod 中 Events 区域出现大量 BackOff 或 CrashLoopBackOff 事件。
注意:CrashLoop 不等于 Pod 完全不可用。若 Pod 配置了 livenessProbe,探针失败也会导致容器重启,但此时退出码通常为 137(SIGKILL),与业务代码崩溃的退出码(如 1、2、139)需要区分对待。

1.4 CrashLoop 生命周期与退避机制

下图展示了 CrashLoop 从容器启动到进入退避循环的完整流程:

CrashLoop 生命周期与退避机制流程图 容器启动 运行检查(≤30s) 容器崩溃(退出码≠0) kubelet 检测到退出 指数退避等待 重启容器 状态标记为 CrashLoopBackOff 退避间隔序列:10s → 20s → 40s → 80s → 160s → 300s(上限)

1.5 常见退出码与根因对照

CrashLoop 的退出码是定位根因的第一线索。以下为 Kubernetes 场景中最常见的退出码对照表:

退出码 信号 常见原因 典型场景
0 — 正常退出(OnFailure 策略下不会重启) 一次性任务完成
1 — 通用应用错误 配置错误、依赖服务不可用
137 SIGKILL OOMKilled 或 livenessProbe 失败后被强制杀死 内存超限、健康检查失败
139 SIGSEGV 段错误(内存访问越界) 代码 bug、基础镜像兼容性问题
143 SIGTERM 优雅终止超时后被 SIGKILL 补杀 preStop 钩子执行时间过长
255 — 退出状态码溢出或未知错误 Shell 脚本异常、entrypoint 未找到

1.6 CrashLoop 与健康检查的交互

CrashLoop 并非总是由业务代码崩溃引起。当 Pod 配置了 livenessProbe 时,探针连续失败也会导致容器被 kubelet 杀死并重启,形成 CrashLoop。此时退出码通常为 137(SIGKILL),而非业务错误码。

关键区分:
• 业务崩溃 CrashLoop:退出码为 1/139/255 等,日志中有应用错误堆栈。
• 探针失败 CrashLoop:退出码为 137,日志中无应用错误,但 kubectl describe 的 Events 中可见 Liveness probe failed。

以下为 CrashLoop 场景下退出码与根因的关联关系图:

CrashLoop 退出码与根因关联图 CrashLoopBackOff 退出码 1 退出码 137 退出码 139 退出码 143 配置错误/依赖不可用 OOM / 探针失败 段错误 / 内存越界 优雅终止超时

1.7 快速诊断命令集

以下命令是 CrashLoop 场景下最常用的诊断工具,建议作为 SRE 的肌肉记忆:

# 查看 Pod 状态与重启次数
kubectl get pods -n <namespace> | grep CrashLoopBackOff

# 查看容器日志(注意 --previous 参数)
kubectl logs <pod-name> -n <namespace> --previous

# 查看 Pod 事件(定位退避原因)
kubectl describe pod <pod-name> -n <namespace>

# 查看容器退出码(通过 describe 的 Last State 字段)
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
最佳实践:在 CrashLoop 场景下,kubectl logs --previous 比 kubectl logs 更有价值,因为当前容器可能尚未输出任何日志就已崩溃,而前一次运行的日志往往保留了完整的错误堆栈。