4. K8s原生蓝绿发布实现:使用Service Selector进行流量切换的YAML示例

Kubernetes 原生蓝绿发布的核心思想是同时维护两套完全独立的生产环境(蓝环境与绿环境),通过 Service 的 selector 字段在瞬间完成流量切换。本节将提供完整的 YAML 示例,并解析流量切换的原子操作原理。

4.1 蓝绿发布资源拓扑

下图展示了蓝绿发布在 K8s 中的资源关系:Service 作为流量入口,通过修改 selector 指向不同版本的 Deployment,实现零中断切换。

K8s 原生蓝绿发布流量切换拓扑 用户流量 Service (my-app-svc) selector: app=my-app, version=v1 蓝环境 (v1 - 当前生产) Deployment: my-app-v1 replicas: 5 labels: app=my-app, version=v1 绿环境 (v2 - 待发布) Deployment: my-app-v2 replicas: 5 labels: app=my-app, version=v2 切换 selector: version=v1 → v2

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 到流量完全切换的时序过程:

Service Selector 切换时序 T0 T1 T2 T3 修改 selector kubectl patch Endpoint 更新 异步同步 kube-proxy 同步 iptables/IPVS 流量切换完成 零中断 切换关键指标 • T0→T1:API Server 写入 etcd,耗时 < 100ms • T1→T2:Endpoint Controller 检测并更新 Endpoints,耗时 1-3s • T2→T3:kube-proxy 更新节点转发规则,耗时 < 1s

4.6 最佳实践与注意事项

  • Readiness Probe 必须配置:确保新版本 Pod 就绪后才接收流量,避免切换后立即出现 502。
  • 保留旧版本资源:切换后不要立即删除蓝环境,保留用于快速回滚。
  • 标签设计规范化:统一使用 app 和 version 标签,避免 selector 匹配歧义。
  • Endpoint 缓存影响:客户端 DNS 缓存或 kube-proxy 同步延迟可能导致少量流量短暂流向旧版本,建议在切换前预热新版本 Pod。
常见陷阱:如果 Service 的 selector 同时匹配了蓝绿两个版本的 Pod(例如只写了 app=my-app 而未指定 version),流量会按轮询方式分发到两个版本,导致蓝绿发布失效。务必在 selector 中明确指定版本标签。