已采纳
回答正文
回复
讨论正文
该问题的正文、回答与讨论。
12 节点(16C64G),Kubernetes 1.28.9,containerd 1.7.13,cgroup v2。 订单服务 Pod 里两个容器:
-Xmx3g,CPU 2C / Mem 4G,业务 drain 耗时 P99 ≈ 8s/var/log/app/*.log,镜像是安全团队统一基线,不可改 entrypoint 和退出逻辑共享一个 emptyDir(/var/log/app)做 shutdown gate:main 收到 SIGTERM 后先 drain,drain 完成写 /var/log/app/.shutdown 标记;filebeat 侧用一个 inotify 脚本(sidecar 镜像里自带的 supervisor 进程)监听该文件,看到后 flush 完再退。
滚动更新时:kubectl describe pod 看到 sidecar 比 main 早退出 2-3s,最后 1-2 条请求日志被截断(filebeat 已 flush 完退出,main 的 access log 最后一段没被采集到 ES)。
force delete / 节点 NotReady 时:更糟——kubelet 对两个容器几乎同时 SIGTERM,filebeat 的 inotify 回调还没触发就被 SIGKILL 了,整段日志丢失。
terminationGracePeriodSeconds: 60:已设,但 kubelet 对 Pod 内所有容器是并行发 SIGTERM 的,sidecar 和 main 没有先后保证。preStop: ["sh","-c","sleep 15"]:让 main 多等 15s 再真正 drain,理论上给 sidecar 留时间。但实际效果是 main 的 drain 被推迟,sidecar 反而更早完成 inotify 回调退出(因为 .shutdown 文件还没写),窗口没缩小,反而 main 的总退出时间变长了。preStop: ["sh","-c","sleep 30"]:想让 sidecar 多等 30s。但 sidecar 的 entrypoint 是 supervisord,preStop 只杀 supervisord 主进程,子进程 filebeat 变成孤儿继续跑,30s 后 SIGKILL 直接砍掉,日志照样丢。stopPod → stopPodSandboxes → 对 Pod 内所有容器并行调 containerRuntime.StopContainer,没有 per-container 退出顺序控制。在 K8s 1.28 老式 sidecar(非
initContainers + restartPolicy: Always)模式下,只改 Pod spec(不动 sidecar 镜像),有没有办法让 sidecar 严格等主容器退出之后再退出?
具体想问:
lifecycle、terminationGracePeriodSeconds、restartPolicy 组合等)能实现 per-container 退出顺序?command: ["tail","-f","/dev/null"] 覆盖 entrypoint 后手动拉起 filebeat)能实现"sidecar 严格后于 main 退出"?@timestamp 做后补对齐?有没有更优雅的兜底?lifecycle、terminationGracePeriodSeconds 等关键字段)+ 一段验证方法(怎么确认 sidecar 确实后于 main 退出)