system.exit 不能配合 kubernetes 存活探针实现平滑优雅降级,反而会跳过 shutdown hook、prestop 和 sigterm,导致请求中断、数据丢失;正确做法是用就绪探针摘流、污点驱逐或 prestop 配合 terminationgraceperiodseconds 实现受控终止。

System.exit 不能配合 Kubernetes 存活探针(liveness probe)实现“平滑优雅降级”,反而会破坏优雅退出机制,引发服务中断、数据丢失或状态不一致等严重问题。
存活探针触发 System.exit 的后果
存活探针失败时,Kubelet 会认为容器“不健康”,立即执行重启(取决于 restartPolicy),而非优雅终止。若应用在 probe 失败逻辑中调用 System.exit(1):
- 进程瞬间退出,跳过所有 JVM 关闭钩子(Shutdown Hook)和 Spring Boot 的优雅关闭流程;
- PreStop Hook 不会被触发(因为 Pod 还未进入 Terminating 状态);
- SIGTERM 信号不会被发送,应用无机会完成正在处理的请求、释放连接或刷盘数据;
- 若容器使用了网络或存储资源(如长连接、挂载卷),可能残留未清理状态,影响后续调度或导致数据损坏。
真正有效的平滑降级路径
节点或服务需要“主动降级”时,应绕开存活探针,改用受控的、面向生命周期的机制:
-
通过 Pod 污点(Taint)标记节点不可服务:手动给节点添加
node.kubernetes.io/out-of-service污点,驱逐无对应容忍度的 Pod;Pod 在新节点上重建前,原 Pod 仍可走完整优雅终止流程(含 PreStop + SIGTERM + gracePeriod); -
由应用自身响应降级信号:例如监听 ConfigMap 变更或自定义 HTTP 管理端点(如
/actuator/health/readiness),将 readiness probe 设为失败,让 kube-proxy 先切断流量,再等待一段时间后调用System.exit或自然终止; - 结合 terminationGracePeriodSeconds 与 PreStop:在 Pod 配置中设置足够长的宽限期(如 120s),并在 PreStop 中执行服务注销、连接 draining、本地缓存持久化等操作,确保外部流量已停止、内部任务已收尾后再退出。
存活探针的正确定位
存活探针只用于检测“进程是否卡死/假死”,不是业务降级开关:
- 它应在容器完全启动且持续健康时始终返回成功;
- 失败应代表不可恢复的崩溃(如 OOM 后线程全挂、死锁),需强制重启;
- 任何“可预期的、需协调的降级行为”都必须交由就绪探针(readiness probe)、污点驱逐、滚动更新或 Operator 控制流来管理。
用 System.exit 响应 liveness probe 是反模式。真正的平滑降级依赖的是 Kubernetes 的声明式生命周期控制,而不是进程级硬退出。











