← 中文资源

简体中文版本

零停机滚动更新配置变更

为 ConfigMap 增加校验和注解,以 maxUnavailable 0 逐步替换 Pod,并在配置缺失或非法时让就绪探针失败。

阅读英文原文

概述

修改 ConfigMap 看起来无害,但它会改变每个读取该配置的进程行为。Deployment 的 Pod 不会自动重启:一方面 Kubernetes 无法判断新配置是否可以安全地逐步生效,另一方面环境变量只在容器启动时读取一次。结果就是集群中一部分 Pod 使用新值、一部分使用旧值,而发布历史里没有任何记录。应把配置当作发布产物来管理。

步骤

  1. 增加校验和注解,让配置变更触发新的 ReplicaSet:
spec:
  template:
    metadata:
      annotations:
        checksum/config: "{{ include (print $.Template.BasePath \"/configmap.yaml\") . | sha256sum }}"
  1. 设置滚动策略,保证容量不下降:
strategy:
  rollingUpdate:
    maxUnavailable: 0
    maxSurge: 1
  1. 观察滚动过程并确认旧 Pod 逐个退出:
kubectl rollout status deployment/payments -n prod --timeout=300s
kubectl get pods -n prod -l app=payments -o wide
  1. 在启动时校验配置,非法值直接让就绪探针失败:
const timeout = Number(process.env.REQUEST_TIMEOUT_MS ?? 3000);
if (!Number.isFinite(timeout) || timeout <= 0) {
  throw new Error('invalid REQUEST_TIMEOUT_MS');
}

验证

滚动期间 kubectl get deployment 的可用副本数应始终不低于期望值,旧 Pod 只在新 Pod Ready 后才终止。修改配置后应产生新的 ReplicaSet,并可通过 kubectl rollout history 回滚。注入一个非法值后,新 Pod 应停留在未就绪状态,流量继续由旧 Pod 承载,而不是带着错误配置对外服务。

注意事项

  • maxUnavailable: 0 时若有 Pod 一直 Pending,发布会无限期阻塞,需要先确认资源充足。
  • 环境变量只在容器启动时读取,只有挂载卷会原地更新,应用还需监听文件变化。
  • 挂载卷的更新存在延迟,且多个 key 之间不是原子生效。
  • 零停机的前提是新旧配置在过渡期内都合法。
  • 日志中应记录生效配置(敏感值打码),便于事后判断 Pod 实际使用的值。