4. K8s原生蓝绿发布实现:使用Service Selector进行流量切换的YAML示例
Kubernetes 原生蓝绿发布的核心思想是同时维护两套完全独立的生产环境(蓝环境与绿环境),通过 Service 的 selector 字段在瞬间完成流量切换。本节将提供完整的 YAML 示例,并解析流量切换的原子操作原理。
4.1 蓝绿发布资源拓扑
下图展示了蓝绿发布在 K8s 中的资源关系:Service 作为流量入口,通过修改 selector 指向不同版本的 Deployment,实现零中断切换。
4.2 完整 YAML 资源清单
以下是一套完整的蓝绿发布 YAML 示例,包含 Service、蓝环境 Deployment、绿环境 Deployment 三个资源对象。
4.2.1 Service 定义(流量入口)
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
namespace: production
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: my-app
version: v1 # 初始指向蓝环境
关键点:Service 的
selector 是流量切换的唯一控制点。切换时只需修改 version 标签值,无需重建 Service 或修改其他字段。
4.2.2 蓝环境 Deployment(v1 - 当前生产)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v1
namespace: production
labels:
app: my-app
version: v1
spec:
replicas: 5
selector:
matchLabels:
app: my-app
version: v1
template:
metadata:
labels:
app: my-app
version: v1
spec:
containers:
- name: app
image: myregistry/my-app:1.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
4.2.3 绿环境 Deployment(v2 - 新版本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v2
namespace: production
labels:
app: my-app
version: v2
spec:
replicas: 5
selector:
matchLabels:
app: my-app
version: v2
template:
metadata:
labels:
app: my-app
version: v2
spec:
containers:
- name: app
image: myregistry/my-app:2.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
4.3 流量切换操作步骤
蓝绿发布的流量切换仅需一步操作:修改 Service 的 selector 字段。以下是两种常用方式:
| 方式 | 命令 | 说明 |
|---|---|---|
| kubectl patch | kubectl patch svc my-app-svc -p '{"spec":{"selector":{"app":"my-app","version":"v2"}}}' |
直接修改 selector,立即生效 |
| kubectl apply | 修改 YAML 中 selector 后执行 kubectl apply -f service.yaml |
声明式更新,适合 CI/CD 流程 |
切换验证命令:
# 查看 Service 当前 selector
kubectl get svc my-app-svc -o jsonpath='{.spec.selector}'
# 验证后端 Endpoint 是否已切换
kubectl get endpoints my-app-svc
# 确认 Pod 标签匹配
kubectl get pods -l app=my-app,version=v2
4.4 切换前后对比
下表展示了切换前后 Service 与后端 Pod 的对应关系变化:
| 状态 | Service selector | 匹配的 Pod 标签 | 流量去向 |
|---|---|---|---|
| 切换前 | app=my-app, version=v1 |
app=my-app, version=v1 |
全部流向蓝环境 v1 |
| 切换中 | 更新瞬间 | Endpoint Controller 异步更新 | 毫秒级完成,无中断 |
| 切换后 | app=my-app, version=v2 |
app=my-app, version=v2 |
全部流向绿环境 v2 |
4.5 切换流程时序
下图展示了从修改 selector 到流量完全切换的时序过程:
4.6 最佳实践与注意事项
- Readiness Probe 必须配置:确保新版本 Pod 就绪后才接收流量,避免切换后立即出现 502。
- 保留旧版本资源:切换后不要立即删除蓝环境,保留用于快速回滚。
- 标签设计规范化:统一使用
app和version标签,避免 selector 匹配歧义。 - Endpoint 缓存影响:客户端 DNS 缓存或 kube-proxy 同步延迟可能导致少量流量短暂流向旧版本,建议在切换前预热新版本 Pod。
常见陷阱:如果 Service 的
selector 同时匹配了蓝绿两个版本的 Pod(例如只写了 app=my-app 而未指定 version),流量会按轮询方式分发到两个版本,导致蓝绿发布失效。务必在 selector 中明确指定版本标签。