3. 蓝绿发布实战:基于 Kubernetes Service 与 Ingress 实现蓝绿环境切换

蓝绿发布是一种零停机部署策略,通过维护两套完全独立的生产环境(蓝环境与绿环境),实现流量瞬间切换与快速回滚。本章将基于 Kubernetes 原生 Service 与 Ingress 资源,手把手构建完整的蓝绿发布流程,涵盖环境准备、流量切换、验证与回滚。

3.1 蓝绿发布核心概念与架构

蓝绿发布的核心思想是:在同一集群中同时运行两个版本的应用实例,通过控制前端流量入口(Service/Ingress)的标签选择器,将用户流量瞬间从旧版本切换到新版本。

关键术语:
  • 蓝环境(Blue):当前稳定运行的生产版本(v1)。
  • 绿环境(Green):待发布的新版本(v2),部署完成后进行验证。
  • 流量切换点:Service 的 selector 或 Ingress 的 backend 指向目标环境。
  • 回滚操作:将流量切回蓝环境,保留绿环境用于问题排查。
蓝绿发布架构图 用户 / DNS Ingress Controller Service (app-svc) 蓝环境 (Blue) v1 Pod: app-v1-xxx 标签: version: v1 绿环境 (Green) v2 Pod: app-v2-xxx 标签: version: v2 当前流量指向蓝环境(实线),绿环境待验证后切换(虚线)

3.2 环境准备:部署蓝绿两套 Deployment

首先创建两个 Deployment,分别代表蓝环境(v1)和绿环境(v2)。关键区别在于 labels 和容器镜像版本。

3.2.1 蓝环境 Deployment(v1)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-blue
  labels:
    app: myapp
    version: v1
    environment: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: v1
  template:
    metadata:
      labels:
        app: myapp
        version: v1
        environment: blue
    spec:
      containers:
      - name: app
        image: myapp:1.0.0
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

3.2.2 绿环境 Deployment(v2)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-green
  labels:
    app: myapp
    version: v2
    environment: green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: v2
  template:
    metadata:
      labels:
        app: myapp
        version: v2
        environment: green
    spec:
      containers:
      - name: app
        image: myapp:2.0.0
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
最佳实践:两个 Deployment 的 replicas 应保持一致,避免切换后流量压力不均。建议使用 readinessProbe 确保 Pod 真正就绪后再接收流量。

3.3 创建共享 Service 实现流量切换

蓝绿发布的核心是 一个 Service 对应两个环境,通过修改 selector 中的 version 标签值来切换流量。

3.3.1 初始 Service(指向蓝环境 v1)

apiVersion: v1
kind: Service
metadata:
  name: app-svc
spec:
  selector:
    app: myapp
    version: v1    # 初始指向蓝环境
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

3.3.2 流量切换操作(指向绿环境 v2)

执行以下命令,将 Service 的 selector 从 version: v1 改为 version: v2:

kubectl patch svc app-svc -p '{"spec":{"selector":{"version":"v2"}}}'

验证切换是否成功:

# 查看 Service 端点是否已切换到 v2 Pod
kubectl get endpoints app-svc

# 通过 Service IP 访问测试
kubectl run test-pod --image=busybox -it --rm -- wget -qO- http://app-svc

3.4 使用 Ingress 实现精细化流量路由

当需要更复杂的路由规则(如按 Header、权重比例)时,使用 Ingress 资源替代 Service 直接暴露。通过修改 Ingress 的 backend 指向不同版本的 Service,实现流量切换。

3.4.1 创建两个版本独立的 Service

# 蓝环境 Service
apiVersion: v1
kind: Service
metadata:
  name: app-svc-blue
spec:
  selector:
    app: myapp
    version: v1
  ports:
  - port: 80
    targetPort: 8080

---
# 绿环境 Service
apiVersion: v1
kind: Service
metadata:
  name: app-svc-green
spec:
  selector:
    app: myapp
    version: v2
  ports:
  - port: 80
    targetPort: 8080

3.4.2 Ingress 配置(初始指向蓝环境)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-svc-blue    # 初始指向蓝环境
            port:
              number: 80

3.4.3 切换 Ingress 到绿环境

kubectl patch ingress app-ingress --type='json' \
  -p='[{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/service/name", "value": "app-svc-green"}]'
Ingress 流量切换流程 阶段 1:部署绿环境 kubectl apply -f app-green.yaml 阶段 2:验证绿环境 Ingress 指向 app-svc-green 阶段 3:切换流量 patch Ingress backend Ingress 切换详细步骤 1. 部署绿环境 Deployment 和 Service(app-svc-green) 2. 通过内部 ClusterIP 或临时 Ingress 规则验证绿环境健康 3. 执行 patch 命令将 Ingress backend 切换到 app-svc-green 4. 验证生产域名 myapp.example.com 是否返回 v2 响应 5. 保留蓝环境 30 分钟,确认无问题后回收

3.5 回滚策略:快速切回蓝环境

当绿环境出现问题时,回滚操作只需将流量切回蓝环境。回滚速度取决于 DNS 传播和 Ingress 控制器生效时间,通常在秒级完成。

回滚场景 操作命令 生效时间
Service 模式回滚 kubectl patch svc app-svc -p '{"spec":{"selector":{"version":"v1"}}}' < 1s
Ingress 模式回滚 kubectl patch ingress app-ingress --type='json' -p='[{"op":"replace","path":"/spec/rules/0/http/paths/0/backend/service/name","value":"app-svc-blue"}]' < 5s
保留绿环境 不删除绿环境 Deployment,仅切流量 用于问题排查
回滚注意事项:
  • 回滚前确认蓝环境 Pod 仍处于 Running 状态且 readinessProbe 通过。
  • 如果蓝环境已被回收,需先扩容蓝环境 Deployment 再切流量。
  • 建议在回滚后保留绿环境至少 15 分钟,便于日志和监控对比。

3.6 完整发布与回滚脚本示例

以下是一个自动化蓝绿发布脚本的核心逻辑,包含部署、验证、切换和回滚:

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

NAMESPACE="production"
APP="myapp"
VERSION="v2"

echo "=== 步骤 1: 部署绿环境 ==="
kubectl apply -f app-green.yaml -n $NAMESPACE

echo "=== 步骤 2: 等待绿环境就绪 ==="
kubectl rollout status deployment/app-green -n $NAMESPACE --timeout=120s

echo "=== 步骤 3: 验证绿环境健康 ==="
GREEN_POD=$(kubectl get pod -l version=v2 -n $NAMESPACE -o jsonpath='{.items[0].metadata.name}')
kubectl exec $GREEN_POD -n $NAMESPACE -- curl -s http://localhost:8080/health
if [ $? -ne 0 ]; then
  echo "绿环境健康检查失败,触发回滚"
  exit 1
fi

echo "=== 步骤 4: 切换流量到绿环境 ==="
kubectl patch svc app-svc -n $NAMESPACE -p '{"spec":{"selector":{"version":"v2"}}}'

echo "=== 步骤 5: 验证生产流量 ==="
sleep 5
kubectl run test-$VERSION --image=busybox -it --rm -- wget -qO- http://app-svc.$NAMESPACE.svc.cluster.local

echo "=== 发布成功,保留蓝环境用于回滚 ==="

3.7 蓝绿发布 vs 滚动更新对比

特性 蓝绿发布 滚动更新
资源占用 双倍资源(两套环境同时运行) 仅需额外 25% 资源(maxSurge)
切换速度 秒级(标签切换) 分钟级(逐步替换 Pod)
回滚速度 秒级(切回旧标签) 分钟级(回滚 Deployment)
验证能力 全量验证后再切换 逐步验证,部分流量可能受影响
适用场景 重大版本变更、数据库迁移 日常小版本迭代
生产建议:对于关键业务服务,推荐使用蓝绿发布 + Ingress 模式。蓝绿发布提供瞬间切换和回滚能力,配合 readinessProbe 和自动化脚本,可将发布风险降至最低。每次发布后保留旧环境至少 30 分钟,确保监控系统确认无异常后再回收资源。