prestop钩子在kubernetes终止pod前同步执行,先于sigterm信号,为长连接业务提供优雅退出窗口;需配合nginx主动摘除上游节点、拒绝新连接但保活存量连接,并按序完成通知停止接入、等待连接释放、触发业务关闭。

PreStop钩子的作用与触发时机
PreStop钩子在Kubernetes终止Pod前执行,属于容器生命周期的最后一个同步阶段。它会在kubelet发送SIGTERM信号前被调用,为应用预留“优雅退出窗口”。对长连接业务(如WebSocket、gRPC流、HTTP/2连接)而言,这个窗口至关重要——必须确保新流量不再进入,存量连接有足够时间完成或安全断开。
Nginx作为反向代理需配合的两个关键动作
仅靠PreStop执行脚本不够,Nginx必须同步“下线”该Pod的上游节点,否则仍会转发新请求。需同时做到:
- 主动摘除上游健康状态:通过Nginx Plus的API或OpenResty+Consul等服务发现机制,让Nginx立即标记该Pod为不健康;若用开源Nginx,可借助upstream check模块或外部脚本动态更新upstream配置并重载(注意reload的原子性与开销)
-
拒绝新连接,但保持已有连接活跃:在PreStop中调用Nginx内部指令(如
nginx -s reload不中断连接),或更稳妥地——在PreStop里先关闭Nginx监听端口(如nginx -s stop会强制断连,不可取),推荐改用nginx -s quit,它等待工作进程处理完当前请求后退出,天然支持长连接保活
典型PreStop脚本设计要点
以容器内运行Nginx + 后端业务为例,PreStop应按顺序完成三件事:
-
通知Nginx停止接受新连接:向Nginx发送QUIT信号(
kill -QUIT $(cat /var/run/nginx.pid)),避免新建TCP握手和TLS协商 -
等待存量连接自然释放:用
sleep或主动轮询Nginx状态(如ss -tn state established | grep :80 | wc -l)确认活跃连接数趋近于0,建议设上限(如30秒)防止无限等待 -
可选:触发业务层优雅关闭:若后端服务与Nginx同容器,可在quit后调用业务健康检查接口(如
curl -X POST http://localhost:8080/shutdown)使其停止消费新消息、完成积压任务
验证与兜底策略
零无损的关键是可观测与容错:
- 在PreStop中记录日志(如
echo "$(date) - PreStop started" >> /var/log/prestop.log),结合Prometheus监控Nginx upstream状态码(502/503突增说明摘除失败) - 设置合理的
terminationGracePeriodSeconds(建议≥60秒),确保PreStop有足够时间执行;若超时,kubelet将强制发送SIGKILL,此时Nginx可能残留连接 - 客户端需实现重试+指数退避,服务端返回503时明确告知“正在维护”,避免雪崩重试











