Kubernetes Pod CrashLoopBackOff
· 3 min read
Pod STATUS CrashLoopBackOff 不是一種錯誤,
是「容器一直起不來、被 kubelet 反覆重啟」的統稱。
同樣的 STATUS,Root Cause可以完全不同。
今天刻意製造三種錯誤情境,查法各有差異。
note
CrashLoopBackOff 是 kubelet「反覆重啟容器、在重啟之間退避等待」的狀態,前提是 restartPolicy 會重啟(Always 或 OnFailure)。下面範例為求快速看根因都用 restartPolicy: Never,失敗的容器不會被重啟,STATUS 會直接停在 Error 或 OOMKilled——但查根因的方法完全一樣。想親眼看到 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下顯示Error,Always下為CrashLoopBackOff)。 - 排查過程:
kubectl logs crash-env --previous→REQUIRED 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,應用沒機會印任何字。要去
describe的 Last State 看。exit code 137 = 128 + 9(SIGKILL)。
Debug Summary
| STATUS | Container State | Kubectl | Root Cause |
|---|---|---|---|
| CrashLoopBackOff / Error | Terminated (then restarting) | kubectl logs --previous | command not found, missing env, exit code != 0 |
| OOMKilled | Terminated | kubectl describe -> Last State | Out Of Memory |
| ImagePullBackOff | Waiting | kubectl describe -> Events | Wrong image name/tag, missing imagePullSecrets |
