要让 pod 关闭不中断请求、不丢数据、不锁资源,关键在于主动设计关闭节奏:1. 提前摘流量,依赖就绪探针及时失败;2. 合理设置 terminationgraceperiodseconds,覆盖 prestop 与清理耗时;3. 正确使用 prestop hook 并确保应用捕获 sigterm;4. 多容器需协同关闭,边车应与主容器生命周期对齐。

要让 Pod 关闭不中断请求、不丢数据、不锁资源,关键不是“等它自己停”,而是主动设计关闭节奏。核心是三件事:提前摘流量、留出清理时间、确保信号真正生效。
1. 确保流量在关闭前被摘除
Kubernetes 不会等应用处理完请求才摘流量——它靠就绪探针(Readiness Probe)和端点同步来控制。Pod 一旦进入 Terminating 状态,Endpoint Controller 就会从 Service 的 endpoints 列表中移除它的 IP,但 kube-proxy、Ingress 控制器、CoreDNS 等组件同步有延迟。
- 必须配置就绪探针,且探针路径在关闭逻辑启动后立即返回失败(例如返回 HTTP 503 或直接退出健康检查进程)
- 避免依赖“默认就绪”:没配就绪探针的 Pod,kube-proxy 会在删除请求发出后才开始摘流,此时已有新连接进来
- 对长连接服务(如 WebSocket、gRPC 流),需配合客户端重连机制,不能只靠服务端摘流
2. 合理设置 terminationGracePeriodSeconds
这个字段定义了从发送 SIGTERM 到强制发 SIGKILL 的总等待时间,默认 30 秒。它不是“额外给的时间”,而是整个终止流程的上限,包含 preStop 执行、SIGTERM 处理、应用自行退出全过程。
针对 Kubernetes 仪表板和 Web UI 的浏览器自动化。适用于与 Kubernetes Dashboard、Grafana、ArgoCD UI 或其他 Web 界面交互。需要设置 MCP_BROWSER_ENABLED=true。
- 对普通 Web 服务,30 秒通常够用;对批处理或大事务场景,应设为 120–300 秒
- 该值需大于 preStop 脚本执行时间 + 应用实际清理耗时,否则会被截断
- 可通过
kubectl delete pod --grace-period=60临时覆盖,但生产环境建议写死在 Pod 模板中
3. 正确使用 preStop Hook 和 SIGTERM 处理
preStop 不是“替代 SIGTERM”,而是前置动作;SIGTERM 也不是可选通知,而是必须响应的退出信号。
-
preStop exec 示例(Nginx):
lifecycle: preStop: exec: command: ["/usr/sbin/nginx", "-s", "quit"]—— 直接优雅停止 Nginx 主进程,比等它收 SIGTERM 更可靠 -
preStop http 示例(Spring Boot):
lifecycle: preStop: httpGet: path: /actuator/shutdown port: 8080—— 触发内置 shutdown endpoint,自动注销注册中心、关闭线程池 - 应用代码必须捕获 SIGTERM:Java 用 ShutdownHook,Go 用 signal.Notify,Node.js 监听
process.on('SIGTERM', ...);主进程收到后应拒绝新请求、等待活跃请求完成、再退出 - 注意:Shell 启动脚本常导致信号丢失——若容器 entrypoint 是
/bin/sh -c 'java -jar app.jar',SIGTERM 只发给 sh,不会透传给 Java 进程;应改用 exec 形式:ENTRYPOINT ["java", "-jar", "app.jar"]
4. 多容器与边车协同关闭
Pod 内多个容器各自独立收 SIGTERM,没有默认顺序。边车(如日志收集、metrics exporter)需与主应用协调生命周期。
- 主容器退出前,边车可能还在运行;若边车依赖主容器(如读取其 stdout),应在主容器 preStop 中触发边车关闭,或用共享卷+文件信号等方式同步状态
- init 容器不参与终止流程,无需处理
- 对 Istio sidecar,启用
sidecar.istio.io/inject: "true"后,Istio 代理会自动配合主容器关闭:先停止监听新连接,再等待连接空闲超时(默认 5 秒),最后退出










