3、升级窗口定义:滚动更新策略、PodDisruptionBudget、优雅关闭与流量排空

Ingress 控制器的升级窗口是集群流量管理中最关键的时段。如果升级策略配置不当,轻则导致少量请求 502/503,重则引发整个集群入口瘫痪。本章从三个核心维度拆解升级窗口的防御体系:滚动更新策略控制 Pod 替换节奏,PodDisruptionBudget 保障最小可用副本数,优雅关闭与流量排空确保存量连接安全终止。

3.1 滚动更新策略:控制替换节奏

Kubernetes 默认的 RollingUpdate 策略会逐个替换 Pod,但对于 Ingress 控制器这类承载七层流量的组件,默认行为往往过于激进。你需要显式配置 maxSurge 和 maxUnavailable 来限制并发替换数。

参数 默认值 推荐值(Ingress 控制器) 说明
maxSurge 25% 1 或 10% 升级期间允许超出期望副本数的最大 Pod 数,避免同时启动过多新 Pod 造成后端过载
maxUnavailable 25% 0 升级期间允许不可用 Pod 的最大数量,设为 0 可保证至少保留全部副本数,但会延长升级时间
生产建议:对于 3 副本的 Ingress 控制器,推荐配置 maxSurge: 1 和 maxUnavailable: 0。这样每次只替换 1 个 Pod,且替换期间始终保持 3 个 Pod 处理流量,避免容量瞬间下降。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    spec:
      containers:
      - name: controller
        image: registry.k8s.io/ingress-nginx/controller:v1.11.0
        ports:
        - containerPort: 80
        - containerPort: 443
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 30"]

3.2 PodDisruptionBudget:保障最小可用副本

PodDisruptionBudget(PDB)是集群管理员对抗节点级故障和主动运维操作的防御层。即使节点被 drain 或集群触发自动缩容,PDB 也能阻止 Ingress 控制器的可用副本数低于阈值。

常见误区:PDB 只保护 自愿中断(如 kubectl drain、cluster autoscaler 缩容),不保护非自愿中断(如节点宕机、硬件故障)。非自愿中断需要依靠多副本 + 反亲和性来应对。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: ingress-nginx-pdb
  namespace: ingress-nginx
spec:
  minAvailable: 2          # 至少保留 2 个副本
  selector:
    matchLabels:
      app.kubernetes.io/component: controller

PDB 的两种配置模式对比:

模式 表达式 适用场景
最小可用数 minAvailable: 2 固定副本数场景(如 3 副本集群),明确要求至少保留 2 个
最大不可用百分比 maxUnavailable: 33% 动态副本数场景(HPA 自动扩缩),按比例控制中断容忍度

3.3 优雅关闭与流量排空

Ingress 控制器的优雅关闭分为两个阶段:从负载均衡器摘除和存量连接排空。如果只依赖默认的 SIGTERM 处理,Kubelet 会在 terminationGracePeriodSeconds 到期后强制杀死进程,导致正在处理的请求被截断。

Ingress 控制器优雅关闭与流量排空流程 阶段 1:PreStop 延迟 sleep 30 秒 等待负载均衡器摘除 阶段 2:SIGTERM 信号 关闭新连接监听 开始排空存量连接 阶段 3:连接排空 等待活跃请求完成 超时后强制关闭 时间线 → 从 PreStop 开始到 terminationGracePeriodSeconds 结束 关键配置参数 • terminationGracePeriodSeconds:120s • PreStop sleep:30s(摘除时间) • worker-shutdown-timeout:60s(Nginx) • max-worker-connections:65536 • 排空等待时间:30s(Ingress 内部) 排空效果 • 新连接:被负载均衡器路由到其他副本 • 存量连接:继续处理,不中断 • 长连接:等待超时或自然关闭 • WebSocket:等待握手完成或超时 • 超时后:Kubelet 强制 SIGKILL

3.4 排空参数调优清单

以下参数需要根据业务请求的典型耗时进行联动调整:

参数 位置 推荐值 调优依据
terminationGracePeriodSeconds Deployment.spec.template.spec 120s 必须大于 PreStop + 排空超时之和
lifecycle.preStop.sleep Container 定义 30s 负载均衡器健康检查间隔的 2~3 倍
--worker-shutdown-timeout Ingress 控制器启动参数 60s Nginx worker 等待活跃请求完成的最大时间
--max-worker-connections ConfigMap / 启动参数 65536 根据并发量调整,过大可能导致排空变慢
排空验证命令:在升级窗口期间,持续观察 Ingress 控制器 Pod 的日志和指标,确认排空行为符合预期。
# 观察排空日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller \
  --tail=50 | grep -E "shutdown|drain|graceful|closing"

# 监控活跃连接数(Prometheus 指标)
nginx_ingress_controller_nginx_process_connections{state="active"}

# 检查 PDB 是否阻止了中断
kubectl get pdb -n ingress-nginx -o wide

3.5 升级窗口的完整防御链

将上述三个组件串联起来,形成 Ingress 控制器升级窗口的完整防御链:

  1. PDB 前置检查:升级操作发起前,Kubernetes 先检查 PDB 是否允许中断。如果当前可用副本数 ≤ minAvailable,操作被阻塞。
  2. 滚动更新节奏控制:maxUnavailable=0 确保每次只替换 1 个 Pod,且替换期间总副本数不下降。
  3. PreStop 延迟摘除:新 Pod 启动后,旧 Pod 进入 PreStop 阶段,sleep 30 秒等待负载均衡器完成摘除。
  4. SIGTERM 触发排空:PreStop 结束后,Ingress 控制器收到 SIGTERM,关闭新连接监听,启动内部排空计时器。
  5. 连接排空完成或超时:worker-shutdown-timeout 内等待活跃请求完成,超时后强制关闭。
  6. Kubelet 强制终止:terminationGracePeriodSeconds 到期后,Kubelet 发送 SIGKILL 清理残留进程。
排空失败典型场景:如果 terminationGracePeriodSeconds 设置过短(如 30s),而 PreStop sleep 已占用 30s,则排空阶段实际可用时间为 0s,所有存量连接都会被 SIGKILL 截断,导致 502 错误。务必保证 terminationGracePeriodSeconds ≥ PreStop sleep + worker-shutdown-timeout + 10s 缓冲。

3.6 升级窗口的可观测性检查点

在升级窗口期间,以下检查点可以帮助你快速定位排空问题:

检查点 观测对象 正常行为 异常信号
PDB 状态 kubectl describe pdb DisruptionsAllowed ≥ 1 DisruptionsAllowed = 0,升级被阻塞
Pod 事件 kubectl describe pod PreStop 执行成功,无 FailedPreStopHook PreStop 超时或执行失败
Ingress 日志 控制器日志 输出 "Shutting down worker processes" 后正常退出 无排空日志,或出现 "worker process exited with fatal"
上游 5xx 指标 Prometheus / 负载均衡器 升级期间 5xx 无显著增加 502/503 突增,表明排空未生效