init 容器怎么保证先于应用容器运行?失败了会怎样?它们的资源请求算不算?应用容器崩溃重启时会不会再来一遍?这篇用带时间戳的共享卷、STATUS 变化和调度结果,把这些问题一一量出来。
kubectl get pod seq 的 STATUS 变化:Init:0/3(+0.1s) → Init:1/3(+3.5s) → Init:2/3(+6.6s) → Running(+9.4s)
共享卷里的日志(时间是相对第一行的秒数):
i1 start + 0.00s
i1 end + 2.00s
i2 start + 2.96s
i2 end + 4.96s
i3 start + 5.74s
i3 end + 7.75s
app start + 8.75s
initContainerStatuses:i1=terminated(exitCode=0); i2=terminated(exitCode=0); i3=terminated(exitCode=0);Initialized=True三个 init 容器各睡 2 秒,往共享的 emptyDir 里写带时间的日志:i1 在 0.00~2.00 秒、i2 在 2.96~4.96 秒、i3 在 5.74~7.75 秒,应用容器 8.75 秒才启动。每个容器之间还有约 1 秒的启动开销。kubectl get 的 STATUS 显示 Init:0/3 → Init:1/3 → Init:2/3 → Running,三个 init 容器都以 exitCode=0 结束,Initialized 条件为 True。
init 容器前两次 exit 1、第三次成功(用 emptyDir 里的计数文件实现):STATUS 变化:Init:0/1(+0.1s) → Init:Error(+1.8s) → Init:CrashLoopBackOff(+12.8s) → Init:0/1(+13.3s) → PodInitializing(+13.7s) → Running(+14.1s) initContainerStatuses.restartCount=2;最终 phase=Running;应用容器 app 状态=running restartPolicy=Never 的 Pod,init 容器 exit 1:phase=Failed;STATUS 列=Init:Error;应用容器 app 状态=waiting(从未启动)
一个前两次 exit 1、第三次成功的 init 容器:STATUS 经过 Init:Error、Init:CrashLoopBackOff,等退避结束再重试,第三次成功后 PodInitializing → Running,restartCount=2,应用容器全程没有启动。restartPolicy: Never 的 Pod 里 init 容器失败一次,整个 Pod 就是 Failed(STATUS Init:Error),应用容器从未启动。
req-app(init 10m、应用 100m):phase=Running;PodScheduled=True;nodeName=kx-main-worker2 req-init-big(init 100 核、应用 100m):phase=Pending;PodScheduled=False reason=Unschedulable;0/3 nodes are available: 1 node(s) had untolerated taint(s), 2 Insufficient cpu. preemption: 0/ (每个节点 allocatable cpu=10 核)
调度器按“所有 init 容器里最大的请求”和“所有应用容器请求之和”两者的较大值来算 Pod 的有效请求。init 容器 10m、应用 100m 的 Pod 正常调度;init 容器请求 100 核、应用只要 100m 的 Pod 保持 Pending,reason Unschedulable,message 里 2 Insufficient cpu(每个节点 10 核)——尽管 init 容器很快就会退出。
应用容器 2 秒后 exit 1,28 秒内重启了 2 次;最近一次应用容器 cat 出的共享卷日志里 setup-ran 出现 1 次、app-start 出现 3 次(每次启动应用容器都追加一行);init 容器 setup 的 restartCount=0
应用容器 2 秒后 exit 1 反复重启(28 秒内 2 次),共享卷日志里 setup-ran 只有 1 行、app-start 有 3 行,init 容器 setup 的 restartCount 仍是 0。init 容器是给 Pod 启动做准备的一次性步骤,应用容器重启不会重新运行它们;要让它们重做只能重建 Pod。