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 在集群运维中有多个可观测维度,以下为最常见的表现特征:
- kubectl 输出特征:
kubectl get pods显示STATUS列为CrashLoopBackOff,RESTARTS列数值持续增长。 - Pod 生命周期短:容器从启动到退出通常不超过 30 秒,部分场景甚至不足 1 秒。
- 重启间隔指数增长:首次重启间隔 10 秒,后续依次为 20 秒、40 秒、80 秒……最大间隔 5 分钟。
- 日志重复出现:
kubectl logs每次查看均为相同的错误日志,无新输出。 - 事件风暴:
kubectl describe pod中 Events 区域出现大量BackOff或CrashLoopBackOff事件。
注意:CrashLoop 不等于 Pod 完全不可用。若 Pod 配置了
livenessProbe,探针失败也会导致容器重启,但此时退出码通常为 137(SIGKILL),与业务代码崩溃的退出码(如 1、2、139)需要区分对待。
1.4 CrashLoop 生命周期与退避机制
下图展示了 CrashLoop 从容器启动到进入退避循环的完整流程:
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,日志中无应用错误,但
• 业务崩溃 CrashLoop:退出码为 1/139/255 等,日志中有应用错误堆栈。
• 探针失败 CrashLoop:退出码为 137,日志中无应用错误,但
kubectl describe 的 Events 中可见 Liveness probe failed。
以下为 CrashLoop 场景下退出码与根因的关联关系图:
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 更有价值,因为当前容器可能尚未输出任何日志就已崩溃,而前一次运行的日志往往保留了完整的错误堆栈。