Skip to content

蓝绿与金丝雀发布

Deployment 原生滚动更新适合常规发布——换镜像、逐批替换、readinessProbe 控制节奏。但它的回滚是逐批重建旧 Pod,不是瞬间切换。发布涉及接口改动、依赖变更、核心链路时,蓝绿或金丝雀更安全。

方式核心动作回退速度适合场景
滚动更新新旧 Pod 分批替换慢——逐批回滚旧版本常规无状态服务
蓝绿部署两套完整版本并存,入口一次切换快——改 selector 或路由即切回需要秒级回退的服务
金丝雀发布小比例流量进新版本,观察后逐步放大快——调回权重即切回风险较高、需要灰度验证的发布

Service selector 蓝绿

蓝绿部署的核心是两套 Deployment 同时存在,Service 通过 label 控制指向哪套。

部署蓝绿两套:

yaml
# blue Deployment——当前稳定版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-blue
  namespace: demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      color: blue
  template:
    metadata:
      labels:
        app: web
        color: blue
    spec:
      containers:
        - name: web
          image: harbor.example.com/demo/web:v1.0.0
---
# green Deployment——新版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-green
  namespace: demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      color: green
  template:
    metadata:
      labels:
        app: web
        color: green
    spec:
      containers:
        - name: web
          image: harbor.example.com/demo/web:v1.1.0

部署 green 之后,两个版本的 Pod 都在运行,但 Service 还指向 blue——此时 green Pod 在跑但不接流量。先确认 green Pod Ready,再切流:

yaml
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: demo
spec:
  selector:
    app: web
    color: blue       # 切流时改成 green
  ports:
    - port: 80
      targetPort: 8080

切流和回滚就是改 Service selector:

bash
# 切到 green
kubectl -n demo patch svc web \
  -p '{"spec":{"selector":{"app":"web","color":"green"}}}'

# 回滚到 blue
kubectl -n demo patch svc web \
  -p '{"spec":{"selector":{"app":"web","color":"blue"}}}'

切流是瞬间的——Service 的 EndpointSlice 立即更新为 green Pod 的 IP。但已建立的 TCP 连接不受影响,长连接可能还会在旧 Pod 上持续一段时间。切换前要确认新版本容量足够、缓存已预热、数据库 schema 兼容。

Gateway API 权重金丝雀

Gateway API 的 HTTPRoute 支持权重分流,不需要改 Service selector:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web
  namespace: demo
spec:
  parentRefs:
    - name: main-gateway
      namespace: gateway-system
  hostnames:
    - web.example.com
  rules:
    - backendRefs:
        - name: web-v1
          port: 80
          weight: 90
        - name: web-v2
          port: 80
          weight: 10

权重随机分配,不保证同一用户的连续请求落在同一版本。需要会话亲和时配合 Header 匹配或 Cookie 机制。

逐步放量:weight: 10 → 观察指标 → weight: 50 → 观察 → weight: 100。观察窗口里至少看:5xx 比例、P95/P99 延迟、业务错误日志、下游数据库和缓存连接数。

Argo Rollouts

手动改 HTTPRoute 权重或 Service selector 时,发布节奏完全靠操作者控制。Argo Rollouts 把蓝绿、金丝雀、暂停、自动分析声明成控制器——发布过程受控制器约束,每一步有超时和自动回滚:

yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: web
  namespace: demo
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: harbor.example.com/demo/web:v1.1.0
  strategy:
    canary:
      steps:
        - setWeight: 10
        - pause: {duration: 5m}
        - setWeight: 50
        - pause: {duration: 10m}
        - setWeight: 100
bash
kubectl argo rollouts get rollout web -n demo -w
kubectl argo rollouts promote web -n demo    # 手动推进到下一步
kubectl argo rollouts abort web -n demo      # 中止发布

核心服务做灰度时,Argo Rollouts 比手工改权重更稳——发布过程受控制器约束,每步有固定观察窗口,异常时自动回滚。

Ingress 注解灰度

Ingress 控制器的金丝雀靠注解实现。这套方式依赖控制器私有实现:

yaml
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"

社区维护的 ingress-nginx 已于 2026 年 3 月退役。旧集群如果依赖大量 Nginx 注解,迁移前先列出注解清单,再找 Gateway API 或目标控制器的对应能力。

金丝雀发布观察指标

指标看什么
5xx 比例新版本是否产生服务端错误
4xx 异常变化路由、鉴权、参数兼容问题
P95/P99 延迟性能回退
Pod 重启和 OOM运行时稳定性
应用错误日志业务异常
下游连接数MySQL、Redis、MQ 是否被新版本打满

发布复盘里写清楚镜像 tag、流量比例、观察时间、指标变化、是否回滚。"灰度正常"四个字没有排查价值。