首页 > Technology > 正文

K8s Pod 一直 CrashLoopBackOff 怎么办?六步定位崩溃根因

fenij 2026-08-07 2 Technology

Pod 状态列写着 CrashLoopBackOff,RESTARTS 数字每隔几十秒涨一次。这不是一个错误码,而是 kubelet 在告诉你:容器起来了、又挂了,我正按退避策略重试。真正的原因藏在容器进程里,不在这行状态上。下面这套顺序我用了很久,基本能在五分钟内定位到根因。

先分清楚是哪一类崩溃

先跑一条命令,把退出码拿到手:

kubectl describe pod <pod-name> -n <namespace> | grep -A5 "Last State"

退出码决定了后面往哪个方向查,别跳过这步。

退出码 含义 先查什么
1 应用自己抛异常退出 容器日志、配置项、依赖服务是否可达
137 被 SIGKILL,多半是 OOM memory limit、JVM/Node 堆参数
126 / 127 命令不可执行或找不到 command/args 写法、镜像里有没有这个二进制
0 正常退出但 Pod 期望常驻 主进程跑完就结束了,前台没挂住

六步排查顺序

1看上一次崩溃的日志:kubectl logs <pod> --previous,当前容器的日志往往是空的
2看 Events 区:kubectl describe pod 底部会写 OOMKilled、Liveness probe failed、ImagePullBackOff
3确认健康检查没有误杀:initialDelaySeconds 太短是高发问题
4核对 ConfigMap / Secret 是否挂上,键名拼错会让应用启动时读到空值
5检查依赖:数据库、Redis、注册中心连不上时应用通常直接退出
6还查不到就改 command 为 sleep 3600,进容器手动跑启动命令看报错

OOMKilled 的处理

如果 Events 里明确写了 OOMKilled,先确认是 limit 给少了,还是应用本身内存参数没跟着 limit 走。Java 应用常见的坑是容器 limit 设了 512Mi,JVM 却按宿主机内存算堆大小。加上这两个参数能让 JVM 感知 cgroup 限制:

-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0

Node 应用同理,用 --max-old-space-size 显式限制。改完再看实际用量:

kubectl top pod <pod> -n <namespace>
🔧
137
最常见的崩溃退出码
⏱️
300s
退避重试的最长间隔
📋
–previous
拿到崩溃现场的关键参数

健康检查误杀怎么改

Spring Boot、Django 这类应用冷启动要十几秒,探针如果 5 秒就开始探,容器会被反复重启,日志里还看不出应用报错。给启动慢的服务加 startupProbe 比调大 initialDelaySeconds 更稳妥:

startupProbe:
  httpGet:
    path: /actuator/health
    port: 8080
  failureThreshold: 30
  periodSeconds: 5

这样最长给 150 秒启动窗口,启动成功后 livenessProbe 才开始生效。

常见问题

问:kubectl logs 什么都不输出怎么办?
答:容器可能在几毫秒内就退出了,日志没来得及刷。加 --previous 读上一次的;还是空的话把 command 换成 ["/bin/sh","-c","sleep 3600"],然后 kubectl exec -it 进去手动执行原命令。

问:RESTARTS 一直涨但业务其实正常,要处理吗?
答:要。多半是 livenessProbe 路径写错或超时太短,服务在被周期性杀掉,只是流量被其他副本顶住了。先把探针路径用 curl 在容器内验一遍。

问:只有某个节点上的 Pod 崩,其他节点正常?
答:查那台节点的资源和内核参数。kubectl describe node 看 MemoryPressure、DiskPressure,再看看是不是本地挂载路径或时间不同步导致的。

你在集群里遇到过哪种奇怪的 CrashLoopBackOff?欢迎到 fenij.com 留言说说,我把有代表性的场景补进这篇。