概述

当你的业务规模增长到单集群无法承载时,多集群就成为必然选择。可能的原因包括:单集群节点上限(5000 节点)、多地域部署、混合云策略、故障隔离、合规要求。但多集群带来的管理复杂度是指数级增长——应用如何跨集群部署、服务如何跨集群发现、配置如何同步、故障如何切换。

本文逐步梳理多集群的架构模式、主流管理工具对比,以及跨集群服务发现、CI/CD、容灾切换的实践方案。

本文基于 Kubernetes v1.30。多集群管理领域仍在快速演进,部分工具的成熟度需持续关注。

为什么需要多集群

单集群的瓶颈

瓶颈说明
规模上限K8s 单集群推荐上限 5000 节点、15 万 Pod、30 万容器
故障域单集群 etcd 故障影响所有业务
升级风险集群升级可能影响所有业务
多租户隔离软隔离不如硬隔离
地域延迟跨地域不能用一个集群
合规要求数据不能跨地域/跨境

多集群的典型场景

场景架构目标
多地域容灾每地域一个集群,DNS 全局负载均衡RTO < 5min
混合云云上 + 自建机房弹性 + 合规
开发/测试/生产隔离每环境一个集群安全隔离
多租户硬隔离每租户独立集群安全合规
边缘计算中心集群 + 边缘集群低延迟

多集群架构模式

模式一:Hub-Spoke(中心辐射)

        ┌─────────┐
        │  Hub    │  ← 管理集群
        │ Cluster │
        └────┬────┘
    ┌────────┼────────┐
    ▼        ▼        ▼
┌──────┐ ┌──────┐ ┌──────┐
│Spoke1│ │Spoke2│ │Spoke3│  ← 工作集群
└──────┘ └──────┘ └──────┘

中心集群负责管理配置、分发应用、收集状态。工作集群只运行业务负载。这是最常见的多集群管理模式。

优势:管理集中、配置一致、操作简便。 劣势:Hub 是单点;Hub 故障不影响已有工作负载,但影响新部署。

模式二:联邦(Federation)

┌─────────────────────────────────────┐
│         Federation Control Plane     │
│  (统一 API,跨集群资源调度)          │
└───┬──────────┬──────────┬──────────┘
    ▼          ▼          ▼
┌──────┐  ┌──────┐  ┌──────┐
│Clstr1│  │Clstr2│  │Clstr3│
└──────┘  └──────┘  └──────┘

联邦控制平面提供统一 API,用户在联邦层创建资源,自动分发到各集群。

优势:统一 API、自动调度、跨集群服务发现。 劣势:架构复杂、控制平面自身需要高可用。

模式三:网格(Mesh)

  ┌──────┐         ┌──────┐
  │Clstr1│◄───────►│Clstr2│
  └──┬───┘         └───┬──┘
     │                  │
     ▼                  ▼
  ┌──────┐         ┌──────┐
  │Clstr3│◄───────►│Clstr4│
  └──────┘         └──────┘

各集群对等,通过服务网格互联。适合对等的多地域部署。

优势:无中心节点、故障隔离好。 劣势:管理复杂、一致性难保证。

主流多集群管理工具对比

工具总览

工具项目状态核心能力成熟度CNCF 状态
KubeFed已停止维护联邦 API停滞已归档
Cluster API活跃集群生命周期孵化
Karmada活跃多集群编排孵化
OCM (Open Cluster Management)活跃集群管理孵化
Argo CD + ApplicationSet活跃GitOps 多集群部署毕业
Submariner活跃跨集群网络孵化

KubeFed(已停止维护)

KubeFed 是最早的 K8s 多集群联邦项目,但已于 2023 年正式归档停止维护。

不推荐新项目使用 KubeFed。参考 KubeFed 归档公告

Cluster API

Cluster API(CAPI)专注于集群生命周期管理——创建、升级、销毁集群,不涉及跨集群应用部署。

核心概念

概念说明
Cluster一个 K8s 集群的声明式定义
Machine一个节点(Control Plane 或 Worker)
MachineDeployment类似 Deployment,管理一组 Machine
MachineSet类似 ReplicaSet
MachineHealthCheck节点健康检查和自动修复
InfrastructureProvider基础设施提供者(AWS/GCP/Azure/vSphere)

示例:声明式创建集群

# cluster.yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: my-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks: ["10.244.0.0/16"]
    services:
      cidrBlocks: ["10.96.0.0/12"]
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: KubeadmControlPlane
    name: my-cluster-control-plane
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
    kind: AWSCluster
    name: my-cluster

---
# control-plane.yaml
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
  name: my-cluster-control-plane
spec:
  replicas: 3
  version: v1.30.0
  machineTemplate:
    infrastructureRef:
      apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
      kind: AWSMachineTemplate
      name: my-cluster-control-plane
  kubeadmConfigSpec:
    initConfiguration:
      nodeRegistration:
        kubeletExtraArgs:
          cloud-provider: aws
    clusterConfiguration:
      apiServer:
        extraArgs:
          cloud-provider: aws

---
# worker-nodes.yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
  name: my-cluster-md-0
spec:
  clusterName: my-cluster
  replicas: 3
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: my-cluster
  template:
    spec:
      clusterName: my-cluster
      version: v1.30.0
      bootstrap:
        configRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
          kind: KubeadmConfigTemplate
          name: my-cluster-md-0
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
        kind: AWSMachineTemplate
        name: my-cluster-md-0

优势:声明式集群生命周期管理、支持多基础设施、自动节点修复。 劣势:只管集群创建不管应用部署、学习曲线陡峭。

Karmada

Karmada(Kubernetes Management Daemon)是华为开源的多集群编排引擎,CNCF 孵化项目。

核心能力

  • 跨集群应用分发(PropagationPolicy)
  • 跨集群服务发现
  • 故障转移
  • 资源重调度

架构

Karmada Control Plane
├── karmada-apiserver     (统一 API 入口)
├── karmada-controller-manager
├── karmada-scheduler      (跨集群调度)
└── karmada-webhook

Member Clusters
├── cluster-1 (push mode)
├── cluster-2 (push mode)
└── cluster-3 (pull mode)

应用分发示例

# 定义应用
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 10
  selector:
    matchLabels:
      app: myapp
  template:
    spec:
      containers:
      - name: app
        image: myapp:v1

---
# 定义分发策略
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: myapp-propagation
spec:
  resourceSelectors:
  - apiVersion: apps/v1
    kind: Deployment
    name: myapp
  placement:
    clusterAffinity:
      clusterNames:
      - cluster-beijing
      - cluster-shanghai
    replicaScheduling:
      replicaSchedulingType: Divided
      replicaDivisionPreference: Weighted
      weightPreference:
        staticWeightList:
        - targetCluster:
            clusterNames: [cluster-beijing]
          weight: 7
        - targetCluster:
            clusterNames: [cluster-shanghai]
          weight: 3

故障转移

apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: myapp-failover
spec:
  resourceSelectors:
  - apiVersion: apps/v1
    kind: Deployment
    name: myapp
  placement:
    clusterAffinity:
      clusterNames:
      - cluster-beijing
      - cluster-shanghai
    spreadConstraints:
    - spreadByLabel: failure-domain.beta.kubernetes.io/region
      maxGroups: 2
      minGroups: 1
  failover:
    application:
      decisionConditions:
        maxUnavailable: 50%
      gracePeriodSeconds: 300
      purgeMode: Graceful

优势:功能完善、支持故障转移、中文文档好。 劣势:社区相对较小、控制平面自身需高可用。

OCM(Open Cluster Management)

OCM 是红帽开源的多集群管理框架。

核心概念

概念说明
ManagedCluster被管理的集群
ManagedClusterSet集群集合
Placement集群选择策略
ManifestWork分发到集群的工作负载
SubscriptionGitOps 订阅
Channel订阅源

优势:与 OpenShift 集成好、模块化设计。 劣势:社区较小、文档以英文为主。

Argo CD ApplicationSet

Argo CD 本身是 GitOps 工具,通过 ApplicationSet 实现多集群部署:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapp-multi-cluster
spec:
  generators:
  - list:
      elements:
      - cluster: cluster-beijing
        url: https://cluster-beijing-api:6443
      - cluster: cluster-shanghai
        url: https://cluster-shanghai-api:6443
  template:
    metadata:
      name: '{{cluster}}-myapp'
    spec:
      project: default
      source:
        repoURL: https://github.com/myorg/myapp-deploy
        targetRevision: HEAD
        path: overlays/{{cluster}}
      destination:
        server: '{{url}}'
        namespace: production
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

优势:与 Argo CD 无缝集成、GitOps 模式、成熟稳定。 劣势:只管应用部署不管集群生命周期、无跨集群服务发现。

工具选型建议

需求推荐工具
集群创建/升级/销毁Cluster API
跨集群应用分发 + 故障转移Karmada
GitOps 多集群部署Argo CD + ApplicationSet
跨集群网络连通Submariner
红帽/OpenShift 生态OCM
简单多集群部署(<10集群)Argo CD + ApplicationSet
复杂多集群编排(>10集群)Karmada + Cluster API

跨集群服务发现

方案一:全局 DNS

最简单的跨集群服务发现方式,利用 CoreDNS 的多集群插件:

# 集群 A 中的服务
svc-a.namespace-a.svc.cluster-beijing.cluster.local

# 集群 B 中的服务
svc-b.namespace-b.svc.cluster-shanghai.cluster.local

通过全局 DNS 解析,各集群可以互相访问 Service。

方案二:Service Mesh 多集群

Istio 支持多集群 Service Mesh,提供跨集群的负载均衡和故障转移:

# ServiceExport:导出 Service 到网格
apiVersion: networking.istio.io/v1beta1
kind: ServiceExport
metadata:
  name: myapp
  namespace: production
spec:
  hosts:
  - "myapp.production.svc.cluster.local"
  ports:
  - number: 8080
    name: http
    protocol: HTTP
# ServiceEntry:在其他集群导入
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: remote-myapp
spec:
  hosts:
  - "myapp.production.svc.cluster.local"
  location: MESH_INTERNAL
  ports:
  - number: 8080
    name: http
    protocol: HTTP
  resolution: DNS
  endpoints:
  - address: cluster-beijing-api.internal
    ports:
      http: 15443

方案三:Submariner

Submariner 通过 IP 隧道连接各集群 Pod 网络:

# 安装 Submariner
subctl deploy-broker --kubeconfig cluster-a.kubeconfig

# 加入集群
subctl join broker-info.subm --clusterid cluster-a --kubeconfig cluster-a.kubeconfig
subctl join broker-info.subm --clusterid cluster-b --kubeconfig cluster-b.kubeconfig

# 验证连通性
subctl show all --kubeconfig cluster-a.kubeconfig

方案对比

方案复杂度功能延迟适用场景
全局 DNS服务发现高(跨集群)简单场景
Service Mesh发现 + 负载均衡 + 策略高级流量管理
SubmarinerPod 网络直连需要 Pod 直连

统一 CI/CD

GitOps 多集群部署

# 目录结构
# ├── base/                 # 基础配置
# │   ├── deployment.yaml
# │   ├── service.yaml
# │   └── kustomization.yaml
# ├── overlays/             # 各集群覆盖配置
# │   ├── cluster-beijing/
# │   │   ├── deployment-patch.yaml
# │   │   └── kustomization.yaml
# │   └── cluster-shanghai/
# │       ├── deployment-patch.yaml
# │       └── kustomization.yaml
# └── argocd-apps/         # Argo CD Application
#     └── appset.yaml
# Argo CD ApplicationSet
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapp
spec:
  generators:
  - git:
      repoURL: https://github.com/myorg/myapp-deploy
      revision: HEAD
      directories:
      - path: overlays/*
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: production
      source:
        repoURL: https://github.com/myorg/myapp-deploy
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: '{{cluster.url}}'
        namespace: production
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true

配置差异管理

各集群的配置差异通过 Kustomize patches 管理:

# overlays/cluster-beijing/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../../base

patches:
- path: deployment-patch.yaml

configMapGenerator:
- name: app-config
  behavior: merge
  literals:
  - REGION=beijing
  - DB_HOST=pg-beijing.internal
# overlays/cluster-beijing/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 5                   # 北京集群5副本
  template:
    spec:
      nodeSelector:
        topology.kubernetes.io/region: cn-north-1

容灾切换

多地域容灾架构

            ┌─────────────────────┐
            │   Global DNS / GSLB  │
            │   (Route53 / CloudDNS)│
            └──────┬────────┬──────┘
                   │        │
         ┌─────────┘        └─────────┐
         ▼                            ▼
  ┌──────────────┐            ┌──────────────┐
  │  北京集群     │            │  上海集群     │
  │  (Active)    │            │  (Standby)   │
  │  权重: 100   │            │  权重: 0     │
  └──────────────┘            └──────────────┘
         │                            │
         ▼                            ▼
  ┌──────────────┐            ┌──────────────┐
  │  北京 DB     │ ──同步──→  │  上海 DB     │
  │  (Primary)   │            │  (Replica)   │
  └──────────────┘            └──────────────┘

RTO/RPO 设计

指标含义目标
RTORecovery Time Objective,恢复时间目标< 5min
RPORecovery Point Objective,数据丢失目标< 1min

故障切换流程

# 1. 检测故障(Prometheus/Blackbox Exporter)
# 北京集群连续3次健康检查失败

# 2. DNS 切换(Route53 Health Check 自动切换)
aws route53 change-resource-record-sets \
  --hosted-zone-id Z123ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.example.com",
        "Type": "CNAME",
        "TTL": 60,
        "ResourceRecords": [{"Value": "shanghai-lb.example.com"}]
      }
    }]
  }'

# 3. 提升备集群数据库为主
# 在上海集群执行 DB failover

# 4. 在备集群扩容
kubectl scale deployment myapp -n production --replicas=10 --kubeconfig=shanghai.kubeconfig

# 5. 验证服务
curl -f https://api.example.com/health || echo "FAIL"

自动故障切换

使用 Karmada 的故障转移功能实现自动切换:

apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: myapp-failover-policy
spec:
  resourceSelectors:
  - apiVersion: apps/v1
    kind: Deployment
    name: myapp
  placement:
    clusterAffinity:
      clusterNames:
      - cluster-beijing
      - cluster-shanghai
  failover:
    application:
      decisionConditions:
        maxUnavailable: 50%
      gracePeriodSeconds: 180
      purgeMode: Graceful

数据同步策略

数据类型同步方案RPO
数据库主从复制 / CDC秒级
对象存储跨区域复制秒级
配置GitOps 同步分钟级
缓存各集群独立不同步(可丢失)

恢复演练

演练流程

1. 在非生产环境模拟主集群故障
2. 验证 DNS 切换时间
3. 验证备集群数据库提升时间
4. 验证应用启动时间
5. 验证服务恢复时间
6. 验证数据一致性
7. 验证回切流程

混沌工程

# 使用 Chaos Mesh 模拟集群故障
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
  name: kill-api-pods
  namespace: production
spec:
  action: pod-kill
  mode: all
  selector:
    namespaces:
    - production
    labelSelectors:
      app: api-server
  scheduler:
    cron: "@every 1h"

演练检查清单

  • DNS 切换在 60 秒内完成
  • 备集群应用在 3 分钟内启动
  • 数据库故障转移在 1 分钟内完成
  • RTO < 5 分钟
  • RPO < 1 分钟
  • 无数据丢失
  • 回切流程正常
  • 监控告警正常触发

多集群可观测性

统一监控架构

各集群 Prometheus → Thanos / VictoriaMetrics → Grafana
# Thanos Receive 配置
apiVersion: monitoring.thanos.io/v1alpha1
kind: ThanosReceive
metadata:
  name: thanos-receive
spec:
  replicas: 3
  tsdbVolume:
    storageClass: fast-ssd
    size: 100Gi
  tsdbRetention: 15d
  configReloader:
    enabled: true

跨集群日志

各集群 Fluentbit → 中央 Loki / Elasticsearch

多集群监控面板

# Grafana 数据源配置
apiVersion: 1
datasources:
- name: Thanos
  type: prometheus
  url: http://thanos-query.monitoring:9090
  isDefault: true
  jsonData:
    timeInterval: "30s"

关键多集群监控指标:

指标含义
各集群 Pod 总数集群规模
各集群节点资源利用率容量规划
跨集群服务延迟容灾切换判断
各集群 Pending Pod扩容信号
Argo CD 同步状态部署健康度

总结

多集群管理是 K8s 生态中最复杂的领域之一,核心要点:

  1. 不要过早引入多集群:单集群能承载就别上多集群。多集群的管理成本是单集群的 3-5 倍。
  2. 选型看需求:需要集群生命周期管理用 Cluster API,需要跨集群编排用 Karmada,需要 GitOps 部商用 Argo CD。
  3. GitOps 是部署标配:多集群环境下,手动部署不可持续。Argo CD + Kustomize 是经过验证的组合。
  4. 容灾需要演练:没有演练过的容灾方案等于没有容灾。每季度至少做一次完整的故障切换演练。
  5. 统一可观测性:多集群监控数据必须汇聚到一个平面,否则排障时在各集群间切换会浪费大量时间。
  6. 数据同步是关键:应用切换容易,数据同步难。数据库主从复制、对象存储跨区域复制需要提前规划。
  7. DNS 是第一道防线:全局 DNS 负载均衡是最简单的流量切换手段,TTL 设短一点(60 秒),切换更快。

多集群不是银弹,它用更高的复杂度换取更好的故障隔离和扩展性。在决定上多集群之前,先确认单集群真的已经不够用了。

参考资料与致谢

本文在撰写过程中参考了以下资料,感谢原作者的贡献:

  1. KubeFed 归档公告 — GitHub 开源社区,参考了KubeFed 归档公告相关内容