如何为 StatefulSet 配置“podManagementPolicy=Parallel”加速滚动升级?

解读

在国内云原生面试中,CouchDB 通常以 StatefulSet 形式部署在 Kubernetes 集群
默认 StatefulSet 采用 OrderedReady 策略:Pod 按序创建、按序删除,导致滚动升级时必须等待前一个 Pod 完全就绪并删除旧版本后才能继续,升级 10 个副本就可能耗时 10×(就绪探针+优雅下线+镜像拉取) 时间。
podManagementPolicy 设为 Parallel 后,控制器会并发创建/删除所有 Pod,显著缩短整体升级窗口,特别适合 CouchDB 这种对等节点、无主从区分、通过内部集群协议自协商拓扑的场景
但并发带来的“惊群”重启可能触发集群瞬时不稳定、复制延迟峰值、客户端连接重试风暴,必须配套就绪探针、滚动策略、反亲和、资源配额、网络策略等治理手段,否则面试官会质疑你“只图快不顾稳”。

知识点

  1. StatefulSet 的两种 Pod 管理策略:OrderedReady(默认)与 Parallel。
  2. Parallel 策略仅影响“创建/删除顺序”,不替代 RollingUpdate 的 maxUnavailable/maxSurge 语义;StatefulSet 本身仍按 partition 字段做灰度。
  3. CouchDB 节点通过 /_membership/_cluster_setup 接口自动发现彼此,重启后依赖持久卷中的 _nodes 数据库快速回队,因此并发重启不会丢数据,但可能造成瞬时分片重平衡
  4. 国内主流发行版(ACK、TKE、CCE)对 Parallel 策略支持完整,但部分托管侧会强制注入 PodDisruptionBudget,需提前 kubectl edit pdb 放宽或删除,否则并行删除会被限流。
  5. 必须给 CouchDB 容器配置 graceful shutdown
    • 预停钩子执行 curl -X POST http://127.0.0.1:5986/_node/_local/_system -d '"shutdown"' 让节点主动离开集群;
    • terminationGracePeriodSeconds ≥ 60 s,保证 mnesia 事务落盘。
  6. 就绪探针建议探测 /_up/_membership 双重接口,确认节点既存活又已被集群接受,防止业务流量提前切入
  7. 若使用 TKE 超级节点阿里云 ECI 弹性实例,并发拉起可能触发库存不足,需提前预热镜像缓存、开启虚拟节点水平伸缩

答案

在 Helm 或原生 YAML 中,把 StatefulSet 的 spec 字段显式声明:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: couchdb
spec:
  podManagementPolicy: Parallel        # 关键行
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0                     # 0 表示全量并发升级
  replicas: 5
  template:
    metadata:
      labels:
        app: couchdb
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: couchdb
        image: couchdb:3.3.2
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh","-c","curl -X POST http://127.0.0.1:5986/_node/_local/_system -d '\\\"shutdown\\\"'"]
        readinessProbe:
          httpGet:
            path: /_up
            port: 5986
          initialDelaySeconds: 5
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        livenessProbe:
          httpGet:
            path: /_up
            port: 5986
          initialDelaySeconds: 30
          periodSeconds: 10
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: couchdb
            topologyKey: kubernetes.io/hostname

随后执行:

kubectl apply -f couchdb-sts.yaml

观察事件:

kubectl get po -l app=couchdb -w

可见 5 个 Pod 同时进入 Terminating → Running → Ready,升级总时长从默认 300 s 缩短到 60 s 以内

拓展思考

  1. 灰度场景:若业务要求先升 20% 节点观察 30 min,可将 partition 设为 replicas-1,利用 Parallel+partition 组合实现“并发灰度”,而非传统 StatefulSet 的串行灰度。
  2. 双活数据中心:跨可用区部署时,给 Parallel 策略加上 podAntiAffinity + zone 拓扑分布,防止并发重启把同一分片的所有副本赶出同一 AZ,造成脑裂或读写不可用
  3. 监控对冲:在 Prometheus 中增加 couchdb_cluster_nodes_number < replicas 的告警,并行升级期间若节点数持续低于预期,立即熔断 CI/CD,人工介入。
  4. 极限并发:在 100+ 节点大集群中,可临时调高 kube-controller-manager 的 concurrent-statefulset-syncs 参数(默认 5)到 20,避免控制器侧成为瓶颈;此操作需提交变更工单给平台组,国内金融场景需走夜间维护窗口。