K8s 滚动更新期间部分请求 502 与就绪探针配置排查
2026-08-11 00:53:03 # Kubernetes

问题现象与背景原因

发布新版本过程中,部分用户请求返回 502。观察发现:新 Pod 已是 Running 状态,但应用其实还在启动中(如 Spring Boot 加载上下文、连接数据库)。旧 Pod 被终止后,流量被转发到尚未就绪的新 Pod,而新 Pod 此时还无法处理请求,于是返回 502。

本质原因:缺少或配置不当的就绪探针(Readiness Probe),以及滚动更新策略没能保证”新 Pod 真正能接流量前不杀旧 Pod”。

排查过程(思路与定位方法)

看 Pod 是否 READY(1/1 才是就绪):

1
2
3
kubectl get pods -n <ns>
# 若 READY 显示 0/1,说明就绪探针未通过
kubectl describe pod <pod> -n <ns> | grep -A10 "Readiness"

检查 Deployment 的探针与滚动策略配置:

1
kubectl get deploy <deploy> -n <ns> -o yaml | grep -A20 "readinessProbe\|strategy\|maxSurge\|maxUnavailable"

若没有 readinessProbe,或 initialDelaySeconds 远大于应用实际启动时间(导致探针还没开始探,旧 Pod 已被删),都会触发 502。

解决方法

配置就绪探针,确保探针通过前流量不进 Pod;并用 startupProbe 覆盖”启动慢”场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health
port: 8080
periodSeconds: 10
startupProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 30
periodSeconds: 5 # 允许最长 150s 启动

滚动策略控制新旧交替:

1
2
3
4
5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多多起 1 个新 Pod
maxUnavailable: 0 # 不允许少可用,保证容量

优雅终止,避免请求被半路掐断:

1
2
3
4
5
terminationGracePeriodSeconds: 60
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"] # 先停收流量再退出

操作命令速查

1
2
3
kubectl rollout status deploy/<deploy> -n <ns>     # 观察滚动过程
kubectl rollout undo deploy/<deploy> -n <ns> # 异常时回滚
kubectl get pods -n <ns> # 看 READY 状态

经验总结

  • readinessProbe 控制”是否接流量”,livenessProbe 控制”是否重启”,两者职责不同,别混用。
  • 启动慢的应用务必配 startupProbe,避免 liveness 在启动期误杀。
  • maxUnavailable: 0 + maxSurge: 1 是零停机发布的稳妥组合。
  • 发布期间 502 优先查探针与滚动策略,而不是应用代码。