Kubernetes 零停机部署实战:滚动更新、蓝绿发布与金丝雀发布全解析

为什么零停机部署至关重要?

在云原生时代,频繁发布是常态。传统的”停机维护”模式已无法满足 7×24 小时业务需求。Kubernetes 提供了多种零停机部署策略,本文深入解析三种主流方案:滚动更新(Rolling Update)、蓝绿发布(Blue-Green)、金丝雀发布(Canary Release),并提供完整可运行的 YAML 配置。

方案一:滚动更新(Rolling Update)

滚动更新是 Kubernetes Deployment 的默认策略,逐步替换旧 Pod,全程保持服务可用。

配置示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
spec:
  replicas: 6
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2        # 允许超出 replicas 的最大 Pod 数(绝对值或百分比)
      maxUnavailable: 1  # 更新期间最大不可用 Pod 数
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: my-app:v2.0
        ports:
        - containerPort: 8080
        readinessProbe:          # 就绪探针:确保新 Pod 真正就绪后再切流量
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          failureThreshold: 3
        livenessProbe:           # 存活探针:Pod 异常时自动重启
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

关键参数说明

  • maxSurge:更新时允许创建的额外 Pod 数,越大更新越快但资源消耗越多
  • maxUnavailable:设为 0 可保证全程无中断,但更新速度较慢
  • readinessProbe:必须配置!没有就绪探针会导致流量提前导入未就绪的 Pod

回滚命令

# 查看历史版本
kubectl rollout history deployment/my-app

# 回滚到上一个版本
kubectl rollout undo deployment/my-app

# 回滚到指定版本
kubectl rollout undo deployment/my-app --to-revision=3

# 监控更新状态
kubectl rollout status deployment/my-app

方案二:蓝绿发布(Blue-Green Deployment)

蓝绿发布维护两套完全独立的环境:蓝(当前生产)和绿(新版本),通过切换 Service 选择器实现瞬间切换,回滚只需一条命令。

# blue-deployment.yaml(当前生产版本)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-blue
spec:
  replicas: 4
  selector:
    matchLabels:
      app: my-app
      version: blue
  template:
    metadata:
      labels:
        app: my-app
        version: blue
    spec:
      containers:
      - name: my-app
        image: my-app:v1.0

---
# green-deployment.yaml(新版本,预先部署好)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-green
spec:
  replicas: 4
  selector:
    matchLabels:
      app: my-app
      version: green
  template:
    metadata:
      labels:
        app: my-app
        version: green
    spec:
      containers:
      - name: my-app
        image: my-app:v2.0

---
# service.yaml(通过修改 selector 切换流量)
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
spec:
  selector:
    app: my-app
    version: blue    # 改为 green 即完成切换
  ports:
  - port: 80
    targetPort: 8080
# 切换到绿环境(生产上线)
kubectl patch service my-app-svc -p '{"spec":{"selector":{"version":"green"}}}'

# 验证无误后,删除蓝环境
kubectl delete deployment my-app-blue

# 如需回滚,切换回蓝环境
kubectl patch service my-app-svc -p '{"spec":{"selector":{"version":"blue"}}}'

方案三:金丝雀发布(Canary Release)

金丝雀发布将少量流量导入新版本,验证无误后逐步扩大比例,风险最低。

# 保持稳定版本 9 个副本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-stable
spec:
  replicas: 9
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        track: stable
    spec:
      containers:
      - name: my-app
        image: my-app:v1.0

---
# 金丝雀版本 1 个副本(约 10% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        track: canary
    spec:
      containers:
      - name: my-app
        image: my-app:v2.0

通过调整 canary 副本数逐步扩大流量比例(1/10 → 3/10 → 5/10 → 全量),每步之间观察监控指标(错误率、延迟、业务转化率)。

三种方案对比

方案资源开销回滚速度风险适用场景
滚动更新低(少量额外 Pod)中(需重新拉取镜像)通用场景,Deployment 默认
蓝绿发布高(双倍资源)极快(秒级切换)数据库 Schema 变更、重大重构
金丝雀发布低(少量金丝雀 Pod)极低高流量核心服务、A/B 测试

生产实践建议

  1. 必须配置就绪探针:这是零停机部署的核心保障,缺少探针会导致请求打到未就绪的 Pod
  2. 设置 PodDisruptionBudget:防止节点维护时 Pod 被驱逐导致服务中断
  3. 配置 preStop 钩子:在 Pod 终止前等待请求处理完成,避免连接中断
  4. 监控先行:在发布过程中实时监控错误率和 P99 延迟,设置自动回滚阈值
  5. 镜像使用固定 Tag:生产环境禁止使用 latest,使用 Git Commit Hash 或语义版本
# PodDisruptionBudget 示例
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 3    # 至少保持 3 个 Pod 可用
  selector:
    matchLabels:
      app: my-app

---
# preStop 钩子配置
lifecycle:
  preStop:
    exec:
      command: ["/bin/sh", "-c", "sleep 15"]  # 等待 15 秒让 LB 摘除该节点

总结

Kubernetes 的三种零停机部署策略各有侧重:日常更新用滚动升级,重大变更用蓝绿发布,核心服务灰度用金丝雀。合理选择发布策略,配合就绪探针和监控告警,可以将线上故障率降至最低。