跨集群联邦:让 Kubernetes 区域故障真正做到无停机切换

2026-07-27 24 预计阅读时间: 1 分钟
来源: cncf.io AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

多区域部署最容易制造一种危险的安全感:服务已经在两个 Kubernetes 集群中运行,但其中一个集群消失时,用户流量仍然固执地发往故障区域。副本存在,不等于故障转移已经成立。要让备用集群真正接管请求,必须把工作负载、流量入口、健康判断和数据状态一起纳入设计。

联邦解决的不是“多复制一份”

跨集群联邦的核心目标,是把多个独立集群视为同一个服务的运行位置,同时保留故障隔离边界。每个集群应当能够独立调度 Pod、暴露入口并报告健康状态;集群之间则需要共享或同步服务定义、发布版本和流量策略。

一条完整的请求链路通常包含四层:

  1. 工作负载层:同一版本的 Deployment、ConfigMap 和 Secret 被部署到多个区域。
  2. 集群入口层:每个集群拥有独立的负载均衡器或 Gateway 地址。
  3. 全局流量层:全局负载均衡器、Anycast 网络或支持健康检查的 DNS 服务在区域之间分配请求。
  4. 状态层:数据库、消息系统和对象存储具有明确的跨区域复制与故障恢复策略。

缺少第三层时,备用集群只是闲置副本;缺少第四层时,流量即使成功切换,也可能遇到旧数据、写入冲突或不可用的下游依赖。

健康检查必须越过 Pod 边界

仅检查某个 Pod 是否返回 200 不足以判断一个区域能否接管生产流量。全局流量系统至少应该检查集群入口,并让探针覆盖服务的关键依赖。与此同时,探针不能把短暂的数据库抖动直接放大成整个区域切换,否则会造成流量在两个区域之间来回摆动。

可以把健康状态拆成两类:

  • /livez 只回答进程是否存活,供 Kubernetes 重启异常容器。
  • /readyz 判断实例是否可以接收请求,供 Service 和全局健康检查使用。

区域摘除还应设置连续失败阈值,恢复时设置连续成功阈值。DNS 方案需要特别关注 TTL 和客户端缓存,因为声明的 TTL 并不保证所有递归解析器和应用都按时刷新记录。需要秒级恢复时,具备主动探测和连接级转发能力的全局负载均衡通常更合适。

可以这样实践:同一服务部署到两个集群

下面的示例假设本机已有两个 kubeconfig context:region-aregion-b。镜像需要替换为你自己的应用镜像,并确保它在 8080 端口提供 /readyz

# app.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: federated-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: federated-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: api
      containers:
        - name: api
          image: ghcr.io/your-org/api:1.0.0
          ports:
            - name: http
              containerPort: 8080
          readinessProbe:
            httpGet:
              path: /readyz
              port: http
            periodSeconds: 5
            failureThreshold: 3
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: api
  namespace: federated-demo
spec:
  type: LoadBalancer
  selector:
    app: api
  ports:
    - name: http
      port: 80
      targetPort: http
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api
  namespace: federated-demo
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: api

将清单应用到两个集群,并读取各自的入口地址:

set -eu

for context in region-a region-b; do
  kubectl --context "$context" apply -f app.yaml
  kubectl --context "$context" -n federated-demo rollout status deployment/api
  kubectl --context "$context" -n federated-demo get service api
 done

接下来把两个 LoadBalancer 地址注册到支持主动健康检查的全局流量系统中,健康检查路径设为 /readyz。具体配置取决于云厂商或 DNS 提供商,因此不能仅靠上述 Kubernetes 清单自动完成。

发布时也不要同时更新所有区域。可以先更新备用区域,验证指标和业务请求,再逐步迁移流量:

kubectl --context region-b -n federated-demo \
  set image deployment/api api=ghcr.io/your-org/api:1.1.0
kubectl --context region-b -n federated-demo \
  rollout status deployment/api

# 验证 region-b 后,再更新 region-a
kubectl --context region-a -n federated-demo \
  set image deployment/api api=ghcr.io/your-org/api:1.1.0
kubectl --context region-a -n federated-demo \
  rollout status deployment/api

这种顺序把区域故障转移能力同时用于发布控制:只要旧区域仍能服务,就可以在新版本异常时停止迁移,而不必回滚两个集群。

真正困难的是状态和容量

无状态 API 最容易跨区域接管,但大多数生产服务并不真正无状态。数据库可能采用单主跨区域复制,也可能允许多区域写入;两种模式的故障边界完全不同。

单主模式需要回答:主区域失联后,谁提升副本,如何避免旧主恢复后继续写入?多主模式则必须处理冲突、时钟偏差和一致性要求。消息队列、定时任务和后台消费者也需要防止两个区域重复处理同一任务。

容量同样不能忽略。两个区域各承担 50% 流量时,任一区域都必须留出接管另外 50% 的余量。若正常状态已经接近资源上限,故障转移只会把集群故障变成过载故障。除了 CPU 和内存,还要核对负载均衡配额、数据库连接数、NAT 端口及第三方 API 限流。

上线前用故障演练验证承诺

“零停机”应该由指标证明,而不是由架构图宣布。上线前至少检查以下项目:

  • 两个集群能否从同一受控版本来源独立部署。
  • 全局入口能否在预期时间内发现区域故障并停止转发。
  • 单一区域是否有足够容量承接全部生产流量。
  • 会话、缓存、数据库和消息系统在切换后是否保持正确行为。
  • 区域恢复时是否逐步引流,避免瞬间压垮刚恢复的服务。
  • 故障演练期间是否持续记录错误率、延迟、恢复时间和数据恢复点。

跨集群联邦并不会自动带来零停机。它提供的是多个独立故障域,而全局流量控制、可靠健康检查、状态复制和定期演练,才会把这些故障域连接成真正可用的多区域系统。


相关推荐