开放问答
K8s 滚动发布时在途请求被 SIGTERM 打断:preStop sleep 到底该怎么配才对
该问题的正文、回答与评论。
提问者 沈清和 · 状态 open
Kubernetes滚动发布优雅下线preStop连接排空
【背景】 我负责一个 3 节点 K8s 1.28 集群(containerd 1.7,CNI 是 Calico 路由模式),跑 Spring Boot 3 / Java 17 的无状态订单服务,入口是集群内 Service + 一个 Envoy sidecar 做 L4 转发。每次发版都是默认 RollingUpdate:maxUnavailable=0、maxSurge=1。
【现象】 每次发布,下游监控里都会看到一小撮(大概 0.3%~1%)请求返回 5xx 或客户端 499,时间窗口正好落在旧 Pod 被杀的 10 秒里。抓下来看:readiness 摘除确实发生了,但摘除后还有新连接打进旧 Pod,旧 Pod 处理到一半被 SIGTERM 打断,Spring 的 graceful shutdown 没跑完就 SIGKILL 了。我怀疑是「kube-proxy / iptables 的摘除延迟」+「sidecar 的连接没被主动 drain」两件事叠加。
【已尝试的排查】
- 把
terminationGracePeriodSeconds从默认 30 调到 60,preStop加sleep 10,5xx 从 ~1% 降到 ~0.4%,但没有归零; - 在应用层注册
SIGTERM钩子,先调 readiness 摘除接口、sleep 5s、再 close server,效果同上; - 抓了
iptables -t nat和 calico 的 ipset,确认摘除是异步的,实测从 readiness 变 NotReady 到流量真正切走,有 2~4 秒的窗口; - 没试过:Envoy 主动 drain、
preStop里直接iptables -t filter -I INPUT -j DROP这种硬切。
【期望的回答】 想听听大家生产环境里真正生效的组合拳:
terminationGracePeriodSeconds一般配多大?跟preStop sleep怎么配合?sleep的秒数到底该按什么算(iptables 延迟?sidecar drain?业务 P99 耗时?);- 有没有人踩过「sleep 加到 30s 反而更糟」的坑?为什么?
- L4 sidecar / kube-proxy 场景下,除了 sleep 还有没有更确定性的摘流手段?
- 如果是 L7(Envoy / nginx ingress),连接级 drain 该怎么配?
已采纳
回答者
回答正文
评论
暂无评论。