K8s Pod 频繁 CrashLoopBackOff 排查
2026-08-11 00:53:03 # Kubernetes

Pod 状态在 CrashLoopBackOffRunning 之间反复横跳,RESTARTS 计数持续增长。这说明容器启动后很快退出,kubelet 不断按退避策略重启它。本文给出从「看现象」到「定位根因」再到「修复」的完整路径。

问题现象与背景原因

1
2
3
kubectl get pod
NAME READY STATUS RESTARTS AGE
api-6f9c8b7d-xk2p 0/1 CrashLoopBackOff 7 6m

CrashLoopBackOff 本身不是错误原因,而是结果:容器主进程异常退出,被 kubelet 反复拉起。常见根因:

  1. 应用启动即退出:启动命令写错、依赖服务(数据库 / 配置中心)不可达、配置文件 / 环境变量缺失,导致进程跑起来马上退出(Exit Code 0 / 1 / 2)。
  2. OOMKilled:容器内存超过 limits.memory,被 cgroup 杀掉(Exit Code 137)。
  3. 存活探针(livenessProbe)配置不当:初始延迟 initialDelaySeconds 太短,或探测路径 / 端口错误,容器还没就绪就被判定失败杀死。
  4. 依赖未就绪 / 端口冲突:应用绑定的端口被占用,或需要的服务地址错误。
  5. 镜像问题:打错的镜像、entrypoint 与 CMD 冲突。

排查过程(思路与定位方法)

第一步:看退出码与最后状态。 describeLast State 会告诉你容器是怎么死的,这是定位的第一手信息:

1
kubectl describe pod api-6f9c8b7d-xk2p

关注 Last StateEvents

1
2
3
4
5
Last State:     Terminated
Reason: OOMKilled
Exit Code: 137
State: Waiting
Reason: CrashLoopBackOff

不同 Exit Code 指向不同方向:

Exit Code 含义 排查方向
0 / 1 / 2 应用自身退出 应用日志、启动命令、依赖
137 被 SIGKILL(OOM) 内存 limit、内存泄漏
139 SIGSEGV 段错误 应用 bug、原生库
143 SIGTERM 优雅退出 被探针 / PreStop 杀掉

第二步:看崩溃前的日志(关键)。 容器已重启,当前日志可能不是崩溃那次的,必须加 --previous 看上一次:

1
2
kubectl logs api-6f9c8b7d-xk2p --previous
kubectl logs api-6f9c8b7d-xk2p # 当前这次(若能起来)

第三步:判断是不是探针问题。describe 的 Events 里反复出现 Unhealthy: Liveness probe failed,说明是探针误杀:

1
kubectl describe pod api-6f9c8b7d-xk2p | grep -i -A3 Unhealthy

提示:--previous 是排查 CrashLoopBackOff 的必杀技。很多同学只 kubectl logs 当前容器,看到空日志就以为没输出,其实是看错了那一次。

最终的解决方法

  • 应用退出(Exit 0 / 1 / 2):修正启动命令、补齐缺失的 ConfigMap / Secret / 环境变量;确认依赖服务地址可达。先用 kubectl run 起一个临时调试容器进相同镜像排查。
  • OOMKilled(137):调大 resources.limits.memory,或排查应用内存泄漏。临时先把 limit 调大让 Pod 先跑起来再优化。
  • 探针误杀:调大 initialDelaySeconds(给应用足够启动时间),或把过严的 livenessProbe 先改成 readinessProbe,排除探针本身的问题后再恢复。
  • 端口 / 依赖冲突:检查 containerPort 与实际监听端口是否一致,依赖地址是否从环境变量 / Service 名正确注入。

临时排错时可先去掉 livenessProbe 让容器保持 Running,再进容器内部调试:

1
kubectl exec -it api-6f9c8b7d-xk2p -- sh

操作命令(可直接复制执行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 看状态与重启次数
kubectl get pod -o wide

# 2. 看退出原因与最后状态(核心)
kubectl describe pod <pod-name> | grep -A6 'Last State'
kubectl describe pod <pod-name> | grep -i -A3 Unhealthy

# 3. 看上一次崩溃日志(关键)
kubectl logs <pod-name> --previous
kubectl logs <pod-name>

# 4. 看事件时间线
kubectl get events --sort-by=.lastTimestamp | tail -20

# 5. 进容器内部调试
kubectl exec -it <pod-name> -- sh

# 6. 临时起一个同镜像调试容器(不挂载探针)
kubectl run debug --rm -it --image=<image> -- sh