CrashLoopBackOff 不是 Pod 的一种失败状态,而是 kubelet 在两次重启之间的等待。这篇让一个容器每秒崩溃一次,观察将近 6 分钟,把每次重启前真正等了多久量出来,再看 STATUS 列、多容器 Pod 和重建 Pod 时的表现。
Pod crash(容器 sleep 1 后 exit 1,restartPolicy 默认 Always)共观察 345 秒,restartCount 到 6:
第 1 次重启:上一个容器 运行 1 秒后崩溃,等了 1 秒才启动新容器(新容器启动时刻 距 Pod 第一次启动 2 秒)
第 2 次重启:上一个容器 运行 1 秒后崩溃,等了 14 秒才启动新容器(新容器启动时刻 距 Pod 第一次启动 17 秒)
第 3 次重启:上一个容器 运行 1 秒后崩溃,等了 26 秒才启动新容器(新容器启动时刻 距 Pod 第一次启动 44 秒)
第 4 次重启:上一个容器 运行 1 秒后崩溃,等了 45 秒才启动新容器(新容器启动时刻 距 Pod 第一次启动 90 秒)
第 5 次重启:上一个容器 运行 1 秒后崩溃,等了 83 秒才启动新容器(新容器启动时刻 距 Pod 第一次启动 174 秒)
第 6 次重启:上一个容器 运行 1 秒后崩溃,等了 161 秒才启动新容器(新容器启动时刻 距 Pod 第一次启动 336 秒)
容器 state 的变化(每秒读一次,只记变化):waiting:ContainerCreating(+0s) → running(+1s) → terminated:Error(+6s) → running(+19s) → terminated:Error(+20s) → running(+46s) → terminated:Error(+48s) → running(+92s) → terminated:Error(+93s) → running(+175s) → terminated:Error(+176s) → waiting:CrashLoopBackOff(+254s) → running(+338s) → terminated:Error(+339s)
kubectl get pod 的 STATUS 列的变化:ContainerCreating(+0s) → Running(+1s) → Error(+6s) → Running(+19s) → Error(+20s) → Running(+46s) → Error(+48s) → Running(+92s) → Error(+93s) → Running(+175s) → Error(+176s) → CrashLoopBackOff(+254s) → Running(+338s) → Error(+339s)
事件 BackOff:count=8;Back-off restarting failed container c in pod crash_k25(459cd0d9-b031-44df-bf91-f7d7ceee42d7)容器 sleep 1 后 exit 1。第 1 次重启等了 1 秒(几乎立刻),之后每次崩溃等待翻倍:14、26、45、83、161 秒,约等于 10、20、40、80、160 秒再加 1~5 秒的启动与同步开销;第 6 次重启发生在 Pod 第一次启动后 336 秒,而每个容器实例只运行了 1 秒。再往后会封顶在 5 分钟。
kubectl get 的 STATUS 大部分时间是 Error(上一个容器的终止原因),容器刚起来的那 1 秒是 Running,CrashLoopBackOff 只在第 254 到 338 秒出现了一次;事件 BackOff 的 count 累计到 8。所以别指望总能在 STATUS 里看到这几个字,判断崩溃循环要看 restartCount、lastState 和事件。
Pod mixed(good 一直运行,bad 立刻 exit 2):phase=Running;kubectl get 的 STATUS=Error;READY=1/2
容器 bad:restartCount=6 state=terminated ready=False
容器 good:restartCount=0 state=running ready=True多容器 Pod 里 bad 立刻崩溃(restartCount=6),good 一直 running(restartCount=0),Pod 的 phase 仍是 Running,READY 是 1/2,STATUS 显示 Error。退避是按容器计的。
Pod never:phase=Failed;restartCount=0;state=terminated(exitCode=1);kubectl get STATUS=Error
restartPolicy: Never 的 Pod 崩溃后 phase=Failed、restartCount=0,不会重启,所以不存在 CrashLoopBackOff;STATUS 只是 Error。
重新创建的 Pod crash 前 50 秒:第 1 次重启前等了 0 秒;第 2 次重启前等了 14 秒;第 3 次重启前等了 27 秒(又是从最短的等待开始,不是接着之前的 5 分钟)
删掉 crash 再创建同名 Pod:前 50 秒第 1 次重启等 0 秒,第 2 次 14 秒,第 3 次 27 秒——退避重新从最短开始,不是接着之前的 5 分钟。想让崩溃的容器立刻重试,把 Pod 重建一次就行;但根因不修,它只是把同样的退避重走一遍。