首页 > Technology > 正文

K8s Pod 反复崩溃重启?排错思路

fenij 2026-08-18 38 Technology

Kubernetes 里最常见的一种状态就是 CrashLoopBackOff:Pod 启动、崩溃、重启,然后再次崩溃,循环往复。它本身不是错误原因,而是一个症状。要修好它,必须先找出容器为什么起不来。

常见根因速查

现象 最可能原因 优先排查命令
启动几秒后退出 应用启动报错、配置缺失 kubectl logs --previous
状态 OOMKilled 内存限制太小 kubectl describe pod
一直 ImagePullBackOff 镜像名/标签写错或鉴权失败 kubectl describe pod
健康检查失败 探针路径/端口配置错误 kubectl get events

四步排错法

1. 看日志,优先加上 –previous

容器已经崩溃时,当前日志可能是空的,必须用 --previous 看上一次运行的日志。

kubectl logs deployment/myapp --previous
kubectl logs -p pod/myapp-xxx-yyy

2. 用 describe 看事件和退出码

kubectl describe pod 会显示 Last StateExit Code,对判断是应用报错还是资源不足非常关键。

kubectl describe pod myapp-xxx-yyy | grep -A 5 "Last State"

3. 检查资源限制

如果 Exit Code: 137,基本就是 SIGKILL,多半来自 OOM。把 memory limit 调大,或优化应用内存。

kubectl get pod myapp-xxx-yyy -o yaml | grep -A 4 resources

4. 本地复现镜像

把相同镜像在本地用同样的 entrypoint 启动一次,是最快的验证方式:

docker run --rm -it your-image:latest
📝
看日志
🔍
describe
查资源
🐳
本地复现

踩坑实录

之前给一个 Spring Boot 服务写 Deployment,参考网上示例把 resources.limits.memory 设成了 128Mi。镜像启动后立刻 CrashLoopBackOffkubectl logs --previous 只看到 JVM 报 OutOfMemoryError: Java heap space

我一开始以为是代码内存泄漏,花了半小时看 heap dump。后来执行 kubectl describe pod 发现:

Last State: Terminated
  Reason:    OOMKilled
  Exit Code: 137

原来是限制给得太低。把 limit 从 128Mi 调到 512Mi,Pod 稳定运行。这个坑说明:日志里看到的报错不一定反映真实原因,describe 里的 Reason 往往更直接。

让容器稳定运行的配置建议

  • 合理设置 requests 和 limits。 requests 用来调度,limits 是硬顶。给得太低会被 OOM,给得太高浪费资源。
  • 不要随便复制探针配置。 网上很多示例把 initialDelaySeconds 设得很短,应用还没启动完就被判为不健康。
  • 滚动更新前先做副本数冗余。minReadySecondsmaxSurge 控制更新节奏,避免新版本崩溃导致服务全挂。
readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

常见问题

Q:CrashLoopBackOff 会一直重启吗?
A:会,但重启间隔会指数退避,最长可能到 5 分钟。修好后第一次启动成功,状态就会恢复正常。

Q:怎么看容器是不是被 OOMKilled?
A:kubectl describe podLast State 显示 Reason: OOMKilled,且 Exit Code: 137

Q:应用日志正常但状态还是 CrashLoopBackOff?
A:检查 entrypoint 是否执行完就退出。容器里必须有一个长期运行的前台进程,否则 Kubernetes 认为它结束了。

你在 K8s 排障时还遇到过哪些奇怪的 CrashLoopBackOff 场景?欢迎在 fenij.com 留言交流。

排错自查清单

  • ☐ 常见根因速查
  • ☐ 四步排错法:容器已经崩溃时,当前日志可能是空的,必须用 --previous 看上一次运行的日志。
  • ☐ 踩坑实录:之前给一个 Spring Boot 服务写 Deployment,参考网上示例把 resources.limi
  • ☐ 让容器稳定运行的配置建议
  • ☐ 常见问题:Q:CrashLoopBackOff 会一直重启吗?A:会,但重启间隔会指数退避,最长可能到 5 分钟。修好后

关键命令速查

  • kubectl logs deployment/myapp --previous kubectl logs -p pod/myapp-xxx-yyy
  • kubectl describe pod myapp-xxx-yyy | grep -A 5 "Last State"
  • kubectl get pod myapp-xxx-yyy -o yaml | grep -A 4 resources
  • docker run --rm -it your-image:latest
  • Last State: Terminated Reason: OOMKilled Exit Code: 137
  • readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 1

相关延伸

更系统的排查思路,见 Technology 分类归档

补充:CrashLoopBackOff 优先 kubectl logs --previous 看上一次崩溃现场,再 describe 查 Events。八成是探针太严或依赖没就绪——把 startupProbe 放宽比直接改 liveness 更稳,不然容器还没起来就被杀,陷入死循环。排错时把 kubectl 输出贴进笔记,对比多次重启的时间点,往往能看出是周期性任务还是流量高峰触发,定位快得多。

相关完整手册

系统化的排查与配置思路,建议顺手收藏这几篇完整手册: