删除 Pod 时发生了什么
删除 Pod 时有两件事并行发生:把该 Pod 从 Service 的 Endpoints 中摘除,以及向容器内的 PID 1 发送 SIGTERM;随后等待 terminationGracePeriodSeconds(默认 30 秒),超时未退出就发送 SIGKILL。这意味着应用必须在宽限期内处理 SIGTERM 并自行退出,同时还要考虑端点摘除存在传播延迟——负载均衡可能仍在往这个 Pod 送请求。
基本信息
| 流程 | 摘除端点 → 发送 SIGTERM → 等待宽限期 → SIGKILL |
|---|---|
| 宽限期 | terminationGracePeriodSeconds,默认 30 秒,可按服务特性调整 |
| preStop | 先执行钩子(例如 sleep 5 等在途请求走完)再发 SIGTERM |
| 应用侧要求 | 处理 SIGTERM;长连接与长任务要自查能否安全中断 |
| 验证方式 | 滚动更新时观察连接是否被重置、终止耗时是否合理 |
| 与 PDB 配合 | PDB 限制同时不可用的副本数,与宽限期一起决定发布的平滑程度 |
典型使用场景
- 滚动更新时避免在途请求被硬断,用户侧看不到 502
- 消费类服务退出前提交位点、释放分布式锁,防止重复消费
- 长连接服务(WebSocket、gRPC 流)主动通知客户端重连后再退出
- 批处理任务收到信号后落盘进度,下次从断点继续
- 数据库与缓存连接池优雅关闭,避免留下悬挂的慢查询
preStop 示例
preStop 示例
containers:
- name: web
image: registry.example.com/team/web:1.2.3
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 5"] # 先等在途请求走完再开始停机
# 容器内进程需自行处理 SIGTERM 并在宽限期内退出
验证终止过程
验证终止过程
kubectl rollout restart deploy/web # 触发滚动更新
kubectl get pod -w # 观察 Terminating 停留时长
kubectl describe pod web-xxx | tail -20 # 看事件与终止原因
kubectl get pod web-xxx -o jsonpath='{.spec.terminationGracePeriodSeconds}' # 确认宽限期取值参数与现象读法
| 项 | 含义 | 异常表现 |
|---|---|---|
| terminationGracePeriodSeconds | 优雅停止窗口 | 设得过小则在途请求被硬断 |
| preStop | 停机前执行的钩子 | 缺失时端点摘除延迟会直接吃掉在途请求 |
| SIGTERM | 应用的退出信号 | 未处理则等满宽限期后被 SIGKILL |
| SIGKILL | 强制终止 | 日志没有收尾记录,连接被重置 |
| Terminating 状态 | Pod 处于终止流程中 | 长时间停留说明进程未按预期退出 |
| PDB | 中断预算 | 决定同时不可用的副本下限,与宽限期共同影响发布 |
preStop 里 sleep 是对「端点摘除存在延迟」的经验补偿:让负载均衡先把本实例摘掉,再开始真正停机。sleep 时长要结合端点传播速度与会话保持时间设置,过长会拖慢发布节奏。
宽限期设 0 或极短会让滚动更新期间 502 刷屏;反过来设得过长,一个卡住的进程就能拖住整批发布与缩容。两种取值都应在验证环境压测后再定,而不是照抄默认值。