滚动发布期间,新 ReplicaSet 已经建立,但旧 Pod 长时间显示为 Terminating,Deployment 的更新副本数迟迟没有达到期望值。排查时应把问题拆成三段:控制器是否允许继续推进、节点是否完成容器终止、应用及流量入口是否完成连接排空。对象仍显示在 API 中,并不能单独说明是哪一段阻塞。
这类排查适用于更新进度长期不变、旧副本无法缩减,或发布超出团队设定的完成时限。先保留状态与事件的时间线,避免只凭一次快照下结论。🧭
判断原则:先确认控制器在等什么,再确认容器退出卡在哪里,最后验证流量是否按预期迁移。终止宽限期只是进程退出的时间预算,不等于连接排空机制。
Pod 被删除后,API 对象进入终止状态并记录删除时间。节点上的 kubelet 随后请求容器运行时停止容器。配置的 terminationGracePeriodSeconds 为优雅终止提供时间上限;容器通常先收到 SIGTERM,超过期限仍未退出时才会被强制终止。配置了 preStop hook 时,hook 会在容器停止信号前运行,其耗时也包含在这个终止预算中。
因此,一个耗时过长或等待条件永不满足的 hook,可能先耗掉大部分预算,留给应用处理信号和完成请求的时间便很少。宽限期届满后,强制终止可能中断在途请求、后台任务或尚未完成的清理。🕰️
先比较 Deployment 的期望副本、已更新副本、可用副本和已观测 generation。检查是否出现 ProgressDeadlineExceeded,并查看该状态何时产生。随后核对新旧 ReplicaSet 的期望数和实际 Pod 数,结合 maxSurge 与 maxUnavailable 判断缩容是否受发布策略约束:新副本未就绪时,控制器可能无法按预期减少旧副本。
对目标 Pod 记录 deletionTimestamp、deletionGracePeriodSeconds、容器状态、所在节点及相关事件。按时间排序观察 Killing、FailedPreStopHook、卷卸载失败或运行时相关事件。事件有保留期限且可能未被采集;没有事件只能说明当前看不到相应记录,不能证明容器已正常退出。📋
Pod 进入终止流程时,就绪状态和 EndpointSlice 会发生变化;代理、负载均衡器及客户端需要传播变化并停止向旧实例发送新请求。应用还要处理已有请求。HTTP 长连接、WebSocket、流式响应和后台消费者可能持续占用进程,所以应对照活跃连接数、请求时延、错误率、就绪变化时间和应用退出日志。
应用收到 SIGTERM 后通常需要停止接收新工作,完成或在限定时间内结束在途工作,再让主进程退出。readiness 变化不一定能瞬时传到所有代理,因而应把传播延迟计入排空计划。扩长宽限期本身不会让代理断开连接,也不会替代应用的信号处理。📡
预算核对:把 hook 耗时、入口停止发送新请求的传播时间、最长在途请求和应用清理时间放在同一条时间线上。总预算需要落在宽限期内,并为波动留出合理余量。🧪
把所有 Terminating Pod 都视作控制器故障,会忽略应用退出、节点状态和卷清理等原因;把宽限期无限延长,也会让发布等待更久,却不能解决不响应信号的进程。为赶进度强制删除 Pod 可能让控制面先移除对象,而节点上的进程或连接尚未安全结束。应先用证据定位,再选择最小范围的调整。
验收时观察一次完整滚动发布:新 Pod 按预期变为就绪,旧 Pod 在核定预算内退出,EndpointSlice 不再将新请求导向旧实例,Deployment 的更新副本和可用副本最终达到期望值。还应确认终止 Pod 没有持续累积,错误率、请求时延和被中断任务没有出现异常。若这些现象一致,才说明发布阻塞已得到解决。✅