日志收集、服务网格代理这类“伴随容器”以前只能写在 containers 里,起得不一定早、停得不一定晚、还会让 Job 永远不结束。原生 sidecar 解决了这三件事。这篇逐项验证:启动顺序、Job 能否完成、终止顺序,以及 sidecar 的探针和崩溃对 Pod 的影响。
STATUS 变化:Init:0/2(+0.1s) → Init:1/2(+3.5s) → PodInitializing(+4.7s) → Running(+5.5s)
setup-start + 0.00s
setup-end + 2.01s
side-start + 2.64s
app-start + 4.65s
initContainerStatuses:setup=terminated; side=running;containerStatuses:app=running;Initialized=True
sidecar 是 init 容器,但它在 Pod 运行期间一直 running(普通 init 容器必须 exit 0 才算完成)普通 init 容器必须 exit 0 才算完成;在 initContainers 里给容器加上 restartPolicy: Always 就成了原生 sidecar:setup 在 0.00~2.01 秒结束,side 在 +2.64 秒启动,它的 startupProbe 通过之后 app 才在 +4.65 秒启动。STATUS 经过 Init:0/2、Init:1/2、PodInitializing 到 Running,Initialized 为 True 时 side 仍在运行。
Job native(sidecar 写在 initContainers 里(restartPolicy: Always)):25 秒后 Job 状态 ['SuccessCriteriaMet', 'Complete'];succeeded=1;Pod phase=Succeeded;kubectl get STATUS=Completed Job classic(sidecar 写在 containers 里):25 秒后 Job 状态 (未完成);succeeded=0;Pod phase=Running;kubectl get STATUS=NotReady
同样是 main 3 秒后结束、旁边有个 sleep 3600 的 sidecar:写在 initContainers 里时,main 一结束 sidecar 就被自动终止,25 秒后 Job 是 Complete,Pod Succeeded、STATUS Completed;写在 containers 里时,sidecar 一直不退出,Job 25 秒后仍未完成,Pod 是 Running、STATUS NotReady。过去不得不让应用容器去“杀掉” sidecar 的那些 hack 不再需要了。
日志(hostPath 卷,Pod 删掉后从节点上读;时间相对第一行):
side-start + 0.00s
app-start + 0.05s
app-sigterm + 2.26s
app-exit + 5.26s
side-sigterm + 5.30s
side-exit + 6.30s
app 收到 SIGTERM 与 sidecar 收到 SIGTERM 相差 3.04 秒;app 退出后 0.04 秒 sidecar 才收到 SIGTERM删除 Pod 时顺序和启动相反:app 先收到 SIGTERM(+2.26 秒),它的 trap 里睡了 3 秒,+5.26 秒退出;sidecar 在 +5.30 秒才收到 SIGTERM,比 app 的 SIGTERM 晚 3.04 秒,+6.30 秒退出。日志收集、代理这类 sidecar 因此能一直服务到应用结束,最后一批日志和请求不会丢。
sidecar 的 readinessProbe 一直失败(/tmp/ready 不存在),应用容器本身没有探针:Initialized=True ContainersReady=False Ready=False;app 容器 ready=True;sidecar ready=False 在 sidecar 里创建 /tmp/ready 之后 0.8 秒 Pod Ready=True sidecar 每 3 秒崩溃一次:25 秒后 sidecar restartCount=2;app 容器 restartCount=0 state=running;Pod phase=Running
sidecar 的 readinessProbe 计入 Pod 的就绪:sidecar 探针一直失败,即使 app 本身 ready,Pod 的 ContainersReady 和 Ready 也是 False;在 sidecar 里创建 /tmp/ready 后 0.8 秒 Pod 变 Ready。sidecar 崩溃(每 3 秒 exit 1)只有它自己按退避重启(25 秒内 2 次),app 的 restartCount 仍是 0,Pod 一直 Running。