Kubernetes CrashLoopBackOff 排查全流程:从 describe 到日志到 exit code

📅 发布时间:2026/7/23 22:50:20
Kubernetes CrashLoopBackOff 排查全流程:从 describe 到日志到 exit code Kubernetes CrashLoopBackOff 排查全流程:从 describe 到日志到 exit code线上发个版,Pod 状态突然变成CrashLoopBackOff,重启次数噌噌往上涨,服务 502。这几乎是每个用 K8s 的人都会撞上的场景。很多人第一反应是kubectl delete pod让它重建——但如果是配置或代码问题,重建再多次也是白搭,反而把现场删没了。这篇按「看状态 → 看事件 → 看日志 → 看退出码」的顺序,把排查流程走一遍,每一步该敲什么命令、看什么关键字,讲清楚。先搞懂 CrashLoopBackOff 是什么它不是一种错误,而是一种状态:容器启动 → 崩溃退出 → kubelet 按退避策略(10s、20s、40s……最长 5min)等一会儿再重启 → 又崩。BackOff指的就是这个越来越长的重启间隔。所以 CrashLoopBackOff 只告诉你「容器起来就挂」,真正的原因藏在崩溃的那一下。排查的核心是抓住崩溃瞬间的信息。第一步:kubectl get describe 看全貌# 看重启次数和状态,RESTARTS 高且在涨就是它kubectl get pod-nmyns# 关键:describe 看 Events 和上一次容器的退出状态kubectl describe pod my-app-7d9f-nmynsdescribe输出里盯三个地方:Last State: Terminated Reason: Error Exit Code: 1 # ← 退出码是最重要的线索 Started: ... Finished: ... State: Waiting Reason: CrashLoopBackOff底部的Events区域也要看,像镜像拉不下来(ErrImagePull)、探针失败(Liveness probe failed)、OOM 都会在这里留痕。第二步:退出码直接缩小范围Exit Code是判断方向最快的信号,几个高频值背下来:Exit Code含义常见原因0正常退出容器主进程跑完就退了(比如把一次性脚本当常驻服务)1应用异常代码抛未捕获异常、配置读不到137被 SIGKILL(1289)OOMKilled内存超限,或 liveness 探针杀的143被 SIGTERM(12815)优雅关闭,通常是被正常调度掉126/127命令不可执行/找不到entrypoint 路径错、脚本没加执行权限看到 137 别急着改代码,先确认是不是内存的事:kubectl describe pod my-app-7d9f-nmyns|grep-ioom# 输出 Reason: OOMKilled 就实锤了内存超限第三步:看日志,重点是「上一个」容器的日志这是最容易踩的坑。Pod 已经重启了,kubectl logs默认给你的是当前这个容器的日志——它可能刚起来还没崩,啥也看不到。真正有价值的是崩掉的那个容器:# -p / --previous 看上一个已终止容器的日志,这才是崩溃现场kubectl logs my-app-7d9f-nmyns--previous# 多容器 Pod 要指定容器名kubectl logs my-app-7d9f-nmyns-capp--previous崩溃日志里通常直接写着原因:数据库连不上、环境变量缺失、端口被占、配置文件解析失败。绝大多数 Exit Code 1 都能在--previous日志里找到根因。第四步:如果日志也是空的有些容器崩得太快,--previous也捞不到东西(比如 entrypoint 直接报错、进程秒退)。这时换思路,让容器别崩,进去手动跑:# 临时把 command 覆盖成 sleep,让 Pod 能起来供你调试apiVersion:v1kind:Podmetadata:name:debug-appspec:containers:-name:appimage:myrepo/my-app:v1.2.3# 用出问题的同一个镜像command:[sh,-c,sleep 3600]# 覆盖原 entrypoint,先撑住kubectl apply-fdebug-app.yaml kubectlexec-itdebug-app --sh# 进去后手动执行原来的启动命令,报错就直接打在你眼前/app/entrypoint.sh这招能把「容器秒崩看不到日志」变成「命令行里直接报错」,屡试不爽。高频根因对照排查多了会发现,CrashLoopBackOff 翻来覆去就那么几类:配置缺失:ConfigMap/Secret 没挂上,或 key 名写错,应用读不到必需配置直接退。kubectl describe里Environment和Mounts能对一遍。依赖没就绪:启动时强连数据库/Redis,连不上就 panic。正确做法是加重试或用 initContainer 探测依赖。liveness 探针太激进:应用启动慢(比如 JVM 预热),但initialDelaySeconds给太短,还没起来就被探针判死重启。表现是日志正常却反复重启,Events里有Liveness probe failed。改大initialDelaySeconds或改用startupProbe。OOMKilled(137):limits.memory给低了,或应用真漏内存。先把 limit 调合理,再排查是不是真泄漏。把一次性任务当服务跑(Exit 0):脚本跑完就退,Deployment 又拉起来。这种应该用 Job 而不是 Deployment。小结CrashLoopBackOff 排查记住这条链路:kubectl get pod确认重启在涨 →kubectl describe pod看Exit Code和Events。退出码先分方向:137 查 OOM,1 查应用异常,126/127 查启动命令。kubectl logs --previous才是崩溃现场,别看当前容器日志。日志也捞不到,就用command: sleep覆盖 entrypoint,进容器手动跑复现。一句话记忆点:别急着 delete pod,先 describe 看退出码、logs 加--previous看崩溃现场——删了就没现场了。