3. 蓝绿发布实战:基于 Kubernetes Service 与 Ingress 实现蓝绿环境切换
蓝绿发布是一种零停机部署策略,通过维护两套完全独立的生产环境(蓝环境与绿环境),实现流量瞬间切换与快速回滚。本章将基于 Kubernetes 原生 Service 与 Ingress 资源,手把手构建完整的蓝绿发布流程,涵盖环境准备、流量切换、验证与回滚。
3.1 蓝绿发布核心概念与架构
蓝绿发布的核心思想是:在同一集群中同时运行两个版本的应用实例,通过控制前端流量入口(Service/Ingress)的标签选择器,将用户流量瞬间从旧版本切换到新版本。
关键术语:
- 蓝环境(Blue):当前稳定运行的生产版本(v1)。
- 绿环境(Green):待发布的新版本(v2),部署完成后进行验证。
- 流量切换点:Service 的
selector或 Ingress 的backend指向目标环境。 - 回滚操作:将流量切回蓝环境,保留绿环境用于问题排查。
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"}]'
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 分钟,确保监控系统确认无异常后再回收资源。