跳过正文
  1. Posts/

发布策略详解:滚动、蓝绿、金丝雀与多批次发布

·1377 字·7 分钟
王二麻
作者
王二麻
混迹 Linux 运维多年,专注 Kubernetes 生产实战、Golang 工具开发与稳定性工程。写点踩坑心得,聊聊技术人生。
发布平台实战 - 这篇文章属于一个选集。
§ 2: 本文

发布策略是保障生产环境稳定性的关键。本文将详细介绍四种主流发布策略:滚动发布、蓝绿发布、金丝雀发布和多批次发布,分析它们的原理、优缺点及适用场景。

策略概览
#

flowchart TB
    subgraph 滚动发布
        R1[v1] --> R2[v1+v2混合] --> R3[v2]
    end
    
    subgraph 蓝绿发布
        B1[v1 蓝] --> B2[v2 绿准备] --> B3[切换到 v2]
    end
    
    subgraph 金丝雀发布
        C1[v1 100%] --> C2[v1 90% + v2 10%] --> C3[v2 100%]
    end
    
    subgraph 多批次发布
        M1[批次1: 10%] --> M2[批次2: 30%] --> M3[批次3: 60%] --> M4[批次4: 100%]
    end
策略资源占用回滚速度风险控制复杂度适用场景
滚动发布常规更新
蓝绿发布高(2倍)关键服务
金丝雀发布高风险变更
多批次发布大规模集群

滚动发布(Rolling Update)
#

原理
#

滚动发布逐步替换旧版本实例,是 Kubernetes Deployment 的默认策略。

sequenceDiagram
    participant LB as 负载均衡
    participant V1_1 as Pod v1-1
    participant V1_2 as Pod v1-2
    participant V1_3 as Pod v1-3
    participant V2_1 as Pod v2-1
    participant V2_2 as Pod v2-2
    participant V2_3 as Pod v2-3

    Note over V1_1,V1_3: 初始状态: 3 个 v1 Pod
    
    rect rgb(200, 255, 200)
        Note over V2_1: 创建 v2-1
        V2_1->>LB: Ready
        V1_1->>LB: Terminating
        Note over V1_1: 删除 v1-1
    end
    
    rect rgb(200, 255, 200)
        Note over V2_2: 创建 v2-2
        V2_2->>LB: Ready
        V1_2->>LB: Terminating
        Note over V1_2: 删除 v1-2
    end
    
    rect rgb(200, 255, 200)
        Note over V2_3: 创建 v2-3
        V2_3->>LB: Ready
        V1_3->>LB: Terminating
        Note over V1_3: 删除 v1-3
    end
    
    Note over V2_1,V2_3: 完成: 3 个 v2 Pod

Kubernetes 配置
#

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%        # 最多可超出期望副本数的比例
      maxUnavailable: 25%  # 最多不可用的副本比例
  template:
    spec:
      containers:
      - name: app
        image: my-app:v2
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 10

关键参数
#

参数说明示例
maxSurge滚动更新时最多可超出期望副本数25%2
maxUnavailable滚动更新时最多不可用的副本数25%1

计算示例(replicas=10, maxSurge=25%, maxUnavailable=25%):

  • 最多同时存在:10 + 10×25% = 12 个 Pod
  • 最少可用:10 - 10×25% = 7 个 Pod

优缺点
#

优点

  • 资源占用低,不需要双倍资源
  • Kubernetes 原生支持,配置简单
  • 自动进行健康检查

缺点

  • 发布过程中新旧版本共存,可能导致兼容性问题
  • 回滚需要时间(再次滚动更新)
  • 无法精确控制流量比例

适用场景
#

  • 常规版本更新
  • 向后兼容的变更
  • 资源有限的环境

蓝绿发布(Blue-Green Deployment)
#

原理
#

蓝绿发布维护两套完全相同的环境,通过一次性全量切换流量实现发布。

注意:蓝绿发布的核心是"全切"(0% → 100%)。如果是逐步切换流量(5% → 30% → 100%),那就是金丝雀发布,不是蓝绿发布。

flowchart TB
    subgraph 阶段1["阶段 1: 初始状态"]
        direction LR
        LB1[负载均衡] --> Blue1[蓝环境 v1
3 Pods] Green1[绿环境
空闲] end 阶段1 --> 阶段2 subgraph 阶段2["阶段 2: 部署新版本"] direction LR LB2[负载均衡] --> Blue2[蓝环境 v1
3 Pods] Green2[绿环境 v2
3 Pods 准备中] end 阶段2 --> 阶段3 subgraph 阶段3["阶段 3: 切换流量"] direction LR Blue3[蓝环境 v1
空闲] LB3[负载均衡] --> Green3[绿环境 v2
3 Pods] end

Kubernetes 实现
#

方式一:Service Selector 切换

# 蓝环境 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      version: blue
  template:
    metadata:
      labels:
        app: my-app
        version: blue
    spec:
      containers:
      - name: app
        image: my-app:v1
---
# 绿环境 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      version: green
  template:
    metadata:
      labels:
        app: my-app
        version: green
    spec:
      containers:
      - name: app
        image: my-app:v2
---
# Service(通过修改 selector 切换流量)
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-app
    version: blue  # 切换时改为 green
  ports:
  - port: 80
    targetPort: 8080

切换脚本

#!/bin/bash
# blue-green-switch.sh

CURRENT=$(kubectl get svc my-app -o jsonpath='{.spec.selector.version}')

if [ "$CURRENT" = "blue" ]; then
    echo "Switching from blue to green..."
    kubectl patch svc my-app -p '{"spec":{"selector":{"version":"green"}}}'
else
    echo "Switching from green to blue..."
    kubectl patch svc my-app -p '{"spec":{"selector":{"version":"blue"}}}'
fi

echo "Current version: $(kubectl get svc my-app -o jsonpath='{.spec.selector.version}')"

优缺点
#

优点

  • 切换速度快(秒级)
  • 回滚快速(切回旧环境)
  • 新旧版本完全隔离,无兼容性问题
  • 可以充分测试新版本后再切换

缺点

  • 资源占用高(需要双倍资源)
  • 数据库变更需要特殊处理
  • 长连接切换可能有问题

适用场景
#

  • 关键业务服务
  • 需要快速回滚的场景
  • 重大版本升级

金丝雀发布(Canary Release)
#

原理
#

金丝雀发布先将小部分流量导向新版本,验证无问题后逐步扩大比例。

flowchart TB
    subgraph 阶段1["阶段 1: 初始"]
        LB1[负载均衡]
        LB1 -->|100%| V1_1[v1 Pods]
    end
    
    subgraph 阶段2["阶段 2: 金丝雀 5%"]
        LB2[负载均衡]
        LB2 -->|95%| V1_2[v1 Pods]
        LB2 -->|5%| V2_2[v2 Pod]
    end
    
    subgraph 阶段3["阶段 3: 扩大 30%"]
        LB3[负载均衡]
        LB3 -->|70%| V1_3[v1 Pods]
        LB3 -->|30%| V2_3[v2 Pods]
    end
    
    subgraph 阶段4["阶段 4: 全量"]
        LB4[负载均衡]
        LB4 -->|100%| V2_4[v2 Pods]
    end

Kruise Rollouts 实现
#

Kruise Rollouts 是阿里开源的渐进式交付组件,特点是 Bypass 模式,不需要修改原有 Deployment:

apiVersion: rollouts.kruise.io/v1beta1
kind: Rollout
metadata:
  name: my-app-rollout
spec:
  # 关联原有 Deployment(不需要修改 Deployment)
  workloadRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  
  strategy:
    canary:
      steps:
      # 金丝雀:10% Pod
      - replicas: 10%
        pause:
          duration: 300  # 5 分钟后自动继续
      
      # 扩大:30%
      - replicas: 30%
        pause: {}  # 手动确认继续
      
      # 扩大:60%
      - replicas: 60%
        pause:
          duration: 600
      
      # 全量
      - replicas: 100%
      
      # 流量路由配置
      trafficRoutings:
      - service: my-app
        # 支持 Nginx Ingress
        ingress:
          classType: nginx
          name: my-app-ingress
        # 或者 Gateway API
        # gateway:
        #   httpRouteName: my-app-route

手动控制发布

# 查看发布状态
kubectl get rollout my-app-rollout

# 手动继续下一批次
kubectl-kruise rollout approve rollout/my-app-rollout

# 回滚
kubectl-kruise rollout undo rollout/my-app-rollout

Kruise Rollouts 优势

  • Bypass 模式:与原有 Deployment 解耦,随时可添加/删除
  • 兼容 HPA:不影响 HPA 自动扩缩容
  • 多流量支持:Nginx Ingress、Gateway API、Istio
  • Lua 扩展:通过 Lua 脚本扩展新的工作负载和流量类型

基于特征的金丝雀
#

Kruise Rollouts 支持通过 trafficRoutings 配合 Ingress/Gateway 实现基于 Header 的流量路由:

apiVersion: rollouts.kruise.io/v1beta1
kind: Rollout
metadata:
  name: my-app-rollout
spec:
  workloadRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  strategy:
    canary:
      steps:
      # 第一步:只对内部用户开放
      - replicas: 1
        matches:
        - headers:
          - name: x-user-type
            value: internal
        pause: {}  # 手动确认
      
      # 第二步:扩大到 10% 用户
      - replicas: 10%
        pause:
          duration: 1800
      
      # 第三步:全量
      - replicas: 100%
      
      trafficRoutings:
      - service: my-app
        ingress:
          classType: nginx
          name: my-app-ingress

优缺点
#

优点

  • 风险可控,问题影响范围小
  • 可以基于实际生产流量验证
  • 支持按用户特征灰度
  • 支持自动化分析和回滚

缺点

  • 配置复杂,需要流量管理组件
  • 新旧版本共存,需考虑兼容性
  • 监控和指标要求高

适用场景
#

  • 高风险变更
  • 新功能验证
  • 核心业务服务
  • 需要按用户特征发布

多批次发布(Batch Deployment)
#

原理
#

多批次发布将集群分成多个批次,逐批更新,每批次完成后观察一段时间再继续。

gantt
    title 多批次发布流程
    dateFormat  HH:mm
    axisFormat %H:%M
    
    section 批次1 (10%)
    部署         :a1, 10:00, 5m
    观察         :a2, after a1, 30m
    
    section 批次2 (30%)
    部署         :b1, after a2, 10m
    观察         :b2, after b1, 30m
    
    section 批次3 (60%)
    部署         :c1, after b2, 15m
    观察         :c2, after c1, 30m
    
    section 批次4 (100%)
    部署         :d1, after c2, 20m
    完成         :d2, after d1, 5m

Kruise Rollouts 实现
#

Kruise Rollouts 是 OpenKruise 提供的渐进式交付组件,支持金丝雀、多批次和 A/B 测试,兼容 Deployment、CloneSet、StatefulSet 等多种工作负载。

# 安装 Kruise Rollouts
# helm install kruise-rollouts https://... -n kruise-rollouts-system

# Rollout 资源定义
apiVersion: rollouts.kruise.io/v1beta1
kind: Rollout
metadata:
  name: my-app-rollout
spec:
  workloadRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  strategy:
    canary:
      steps:
      # 批次 1: 10%
      - replicas: 10%
        pause:
          duration: 1800  # 30 分钟
      
      # 批次 2: 30%
      - replicas: 30%
        pause:
          duration: 1800
      
      # 批次 3: 60%
      - replicas: 60%
        pause:
          duration: 1800
      
      # 批次 4: 100%
      - replicas: 100%
      
      # 流量路由(可选,配合 Ingress/Gateway)
      trafficRoutings:
      - service: my-app
        ingress:
          classType: nginx
          name: my-app-ingress

Kruise Rollouts 特点

  • Bypass 模式:不修改原有 Deployment,通过 Rollout 资源控制发布
  • 即插即用:可随时添加或删除,不影响原有工作负载
  • 多工作负载支持:Deployment、CloneSet、StatefulSet、DaemonSet
  • 流量编排:支持 Nginx Ingress、Gateway API、Istio 等

优缺点
#

优点

  • 风险分散,每批次影响范围有限
  • 观察时间充足,问题发现及时
  • 适合大规模集群
  • 可以按区域/机房分批

缺点

  • 发布时间长
  • 需要额外的编排工具
  • 管理复杂度高

适用场景
#

  • 大规模集群(100+ 节点)
  • 多区域/多机房部署
  • 需要严格风险控制
  • 监管要求严格的行业

策略对比与选型
#

详细对比
#

对比项滚动发布蓝绿发布金丝雀发布多批次发布
资源占用低(+25%)高(2倍)中(+10%)中(分批)
发布时间最长
回滚时间秒级秒级分批回滚
流量控制全切精确比例按批次
版本共存短暂较长较长
复杂度
K8s 原生需配置需 Istio需工具

选型决策树
#

是否需要精确流量控制?
├── 是 → 是否需要按用户特征灰度?
│        ├── 是 → 金丝雀发布
│        └── 否 → 是否是大规模集群?
│                 ├── 是 → 多批次发布
│                 └── 否 → 金丝雀发布
└── 否 → 是否需要快速回滚?
         ├── 是 → 蓝绿发布
         └── 否 → 是否资源有限?
                  ├── 是 → 滚动发布
                  └── 否 → 蓝绿发布

组合策略
#

实际生产中,常常组合使用多种策略:

金丝雀 + 多批次组合:

阶段 1: 金丝雀 5%(验证功能)
    ↓ 1小时观察
阶段 2: 批次1 10%(扩大验证)
    ↓ 30分钟观察
阶段 3: 批次2 30%
    ↓ 30分钟观察
阶段 4: 批次3 60%
    ↓ 30分钟观察
阶段 5: 批次4 100%
# Kruise Rollouts 组合策略
apiVersion: rollouts.kruise.io/v1beta1
kind: Rollout
metadata:
  name: my-app-rollout
spec:
  workloadRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  strategy:
    canary:
      steps:
      # 金丝雀阶段:5% 流量,观察 1 小时
      - replicas: 5%
        pause:
          duration: 3600
      
      # 多批次阶段
      - replicas: 10%
        pause:
          duration: 1800
      - replicas: 30%
        pause:
          duration: 1800
      - replicas: 60%
        pause:
          duration: 1800
      - replicas: 100%
      
      # 配合流量路由
      trafficRoutings:
      - service: my-app
        ingress:
          classType: nginx
          name: my-app-ingress

最佳实践
#

1. 发布前检查清单
#

□ 代码审查完成
□ 单元测试通过
□ 集成测试通过
□ 变更说明文档准备
□ 回滚方案准备
□ 监控告警配置
□ 值班人员确认
□ 发布窗口确认

2. 健康检查配置
#

# 完善的探针配置
spec:
  containers:
  - name: app
    readinessProbe:
      httpGet:
        path: /healthz/ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
    livenessProbe:
      httpGet:
        path: /healthz/live
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 10
      failureThreshold: 3
    startupProbe:
      httpGet:
        path: /healthz/startup
        port: 8080
      initialDelaySeconds: 0
      periodSeconds: 5
      failureThreshold: 30  # 最多等待 150 秒启动

3. 优雅终止
#

spec:
  terminationGracePeriodSeconds: 60
  containers:
  - name: app
    lifecycle:
      preStop:
        exec:
          command:
          - /bin/sh
          - -c
          - |
            # 通知停止接收新请求
            curl -X POST localhost:8080/admin/drain
            # 等待存量请求处理完成
            sleep 30

4. 发布指标监控
#

# Prometheus 告警规则
groups:
- name: deployment
  rules:
  - alert: HighErrorRateDuringDeployment
    expr: |
      sum(rate(http_requests_total{status=~"5.."}[5m])) /
      sum(rate(http_requests_total[5m])) > 0.01
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "Error rate > 1% during deployment"
  
  - alert: HighLatencyDuringDeployment
    expr: |
      histogram_quantile(0.99, 
        sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
      ) > 1
    for: 2m
    labels:
      severity: warning
    annotations:
      summary: "P99 latency > 1s during deployment"

总结
#

策略核心特点推荐场景
滚动发布简单、资源少日常更新、资源有限
蓝绿发布快速切换、快速回滚关键服务、重大升级
金丝雀发布精确控制、风险可控高风险变更、新功能验证
多批次发布分批观察、大规模适用大集群、多区域

选择发布策略时,需要综合考虑:

  1. 业务重要性:越重要越需要精细控制
  2. 变更风险:高风险用金丝雀
  3. 集群规模:大规模用多批次
  4. 资源限制:资源少用滚动发布
  5. 回滚要求:快速回滚用蓝绿

最终目标是在发布速度系统稳定性之间找到平衡。

发布平台实战 - 这篇文章属于一个选集。
§ 2: 本文

相关文章