Skip to main content

Kubernetes Pod CrashLoopBackOff

· 3 min read
Charles Wang
DevOps / Backend Engineer

Pod STATUS CrashLoopBackOff 不是一種錯誤,
是「容器一直起不來、被 kubelet 反覆重啟」的統稱
同樣的 STATUS,Root Cause可以完全不同。
今天刻意製造三種錯誤情境,查法各有差異。

note

CrashLoopBackOff 是 kubelet「反覆重啟容器、在重啟之間退避等待」的狀態,前提是 restartPolicy 會重啟(AlwaysOnFailure)。下面範例為求快速看根因都用 restartPolicy: Never,失敗的容器不會被重啟,STATUS 會直接停在 ErrorOOMKilled——但查根因的方法完全一樣。想親眼看到 CrashLoopBackOff,把 --restart=Never 拿掉、用預設的 Always 即可,RESTARTS 會一路往上加。

Pitfall 1:command not found

kubectl run crash-cmd --image=busybox --restart=Never -- /bin/sh -c "notacommand"
  • 狀況:restart=Never 下 STATUS 停在 Error、RESTARTS 為 0;改用預設 Always 則會看到 CrashLoopBackOff、RESTARTS 一路遞增。
  • 排查過程:kubectl logs crash-cmd --previous → 看到 notacommand: not found
  • 原因:entrypoint 指令本身不存在,容器一啟動就 exit。
  • 修法:改成正確指令。
  • 觀念:CrashLoop 是「一直重啟」不是「排程不上」。容器有跑起來、只是馬上掛,所以 logs 裡看得到應用層的錯。

Pitfall 2:missing env

kubectl run crash-env --image=busybox --restart=Never -- /bin/sh -c 'test -n "$REQUIRED" || (echo "REQUIRED missing"; exit 2)'
  • 狀況:同樣失敗(Never 下顯示 ErrorAlways 下為 CrashLoopBackOff)。
  • 排查過程:kubectl logs crash-env --previousREQUIRED missing、exit code 2。
  • 原因:程式啟動時自檢必要環境變數,缺了就主動 exit
  • 修法:補上 env(--env=REQUIRED=x,或在 Deployment 的 env: / 用 ConfigMap、Secret 注入)。
  • 觀念:exit code 不是 0 就會被當失敗重啟。這類「應用自己決定退出」的錯,logs 通常會講原因——先看 logs 最省事。

Pitfall 3:OOMKilled

# memory limit 設極小,再跑吃記憶體的動作
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata: { name: crash-oom }
spec:
restartPolicy: Never
containers:
- name: stress
image: polinux/stress
resources: { limits: { memory: "20Mi" } }
command: ["stress"]
args: ["--vm","1","--vm-bytes","100M","--vm-hang","1"]
EOF
  • 狀況:STATUS 顯示 OOMKilled,但 kubectl logs --previous 看不出原因(甚至空的)。
  • 排查過程:kubectl describe pod crash-oom → 看 Last State: Terminated, Reason: OOMKilled,exit code 137。
  • 原因:容器用量超過 memory limit,被 kernel OOM killer 殺掉——不是應用自己 exit,是被外力幹掉。
  • 修法:調高 resources.limits.memory,或修掉真正的記憶體洩漏 / 降低用量。
  • 觀念:OOMKilled 不會進 logs,因為 logs 是「容器 stdout/stderr」,而 OOM 是 kernel 直接送 SIGKILL,應用沒機會印任何字。要去 describeLast State 看。exit code 137 = 128 + 9(SIGKILL)。

Debug Summary

STATUSContainer StateKubectlRoot Cause
CrashLoopBackOff / ErrorTerminated (then restarting)kubectl logs --previouscommand not found, missing env, exit code != 0
OOMKilledTerminatedkubectl describe -> Last StateOut Of Memory
ImagePullBackOffWaitingkubectl describe -> EventsWrong image name/tag, missing imagePullSecrets