上一篇【第87篇】微服务应用K8s化改造实战——从传统部署到云原生 下一篇【第89篇】K8s + AI/ML——在K8s上运行机器学习工作负载
摘要
单集群玩得再溜,也架不住业务真上规模——一个集群挂了全公司停摆、一个地域延迟高用户骂街、被一家云厂商锁死不敢动。这时候就得"多集群"。
但多集群不是"再装一个K8s"那么简单:应用怎么同时发到几个集群?一个集群挂了流量怎么切走?配置怎么保持一致?这篇把多集群的核心动机、KubeFed v2的联邦模型、以及Karmada等现代方案一次讲清,顺便聊聊跨集群服务发现和流量调度这些真正难的活。
一、为什么需要多集群:单集群的三道天花板
先说清楚,不是炫技才上多集群,是单集群真有物理天花板:
【单集群的天花板】
1. 故障域单一
一个控制平面挂 → 整个集群失联(哪怕节点都活着)
一次etcd脑裂 → 全集群写入瘫痪
2. 地域延迟
集群在华东, 华南用户访问绕半圈
合规要求数据不出境(数据主权)
3. 厂商锁定
全在A云, 想迁B云? 重来一遍
某云region故障 → 业务全断
由此引出多集群的三大驱动力:
要点:多集群通常不是"为了技术",而是为了隔离故障域、贴近用户、不绑定单一厂商。先把动机想清楚,再选方案,不然容易为联邦而联邦。
| 高可用/灾备 | 主集群挂了切备用 | 同城双活 / 异地灾备 |
| 低延迟 | 用户分散多地域 | 多地域就近接入 |
| 混合云/多云 | 不绑定厂商、用便宜资源 | 自有IDC + 公有云 |
二、KubeFed v2:联邦控制面长啥样
KubeFed(Kubernetes Federation v2)是社区早期的联邦方案,思路很清晰:再起一个"联邦控制面",它去管你底下的一堆成员集群。
【KubeFed 架构】
┌─────────────────────────────┐
│ 联邦控制面 (Federation) │
│ ┌───────────────────────┐ │
│ │ federated-apiserver │ │
│ │ federated-controller │ │
│ └───────────────────────┘ │
└───────┬───────────┬─────────┘
│ │
┌─────▼───┐ ┌────▼─────┐
│ 集群A │ │ 集群B │ ← 普通K8s集群, 各自独立
│(华东) │ │(华北) │
└─────────┘ └──────────┘
核心概念三个:
- FederatedTypeConfig:告诉联邦"我要管哪些资源类型"(Deployment/Service/ConfigMap…)。不配置的就不联邦。
- FederatedResource(如 FederatedDeployment):在普通Deployment外面套一层,描述"这个Deployment要发到哪些集群、各发几份"。
- Placement / ReplicaSchedulingPreference:决定分发策略——发到哪几个集群、副本怎么分配。
一个 FederatedDeployment 长这样:
apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
name: order–service
namespace: shop
spec:
template: # 这就是普通的Deployment spec
metadata:
labels: { app: order–service }
spec:
replicas: 6
template:
spec:
containers:
– name: order–service
image: registry.example.com/order–service:1.5.0
placement:
clusters:
– name: cluster–east # 发到华东
– name: cluster–north # 发到华北
overrides:
– clusterName: cluster–east
clusterOverrides:
– path: /spec/replicas
value: 4 # 华东放4副本
– clusterName: cluster–north
clusterOverrides:
– path: /spec/replicas
value: 2 # 华北放2副本(用户少)
要点:KubeFed的优雅之处在于**“声明一次,多集群落地”**——你只写一份FederatedDeployment,联邦控制器帮你把真正的Deployment同步到每个成员集群,还能按集群差异化覆盖副本数、镜像等。
三、副本怎么分:ReplicaSchedulingPreference
光指定"发到哪"不够,副本怎么切也讲究。RSP(ReplicaSchedulingPreference)支持按权重、按集群容量动态分配:
apiVersion: scheduling.kubefed.io/v1alpha1
kind: ReplicaSchedulingPreference
metadata:
name: order–service
namespace: shop
spec:
targetKind: FederatedDeployment
totalReplicas: 10
clusters:
cluster-east:
weight: 3 # 华东权重3
cluster-north:
weight: 1 # 华北权重1
# 结果: 华东 7.5→8, 华北 2.5→2 (按权重近似)
这比手工写固定副本数灵活:集群扩缩容后权重自动再平衡。
四、KubeFed的尴尬与现代替代:Karmada
说实话,KubeFed v2到后来社区基本停滞了——它侵入式地要求你改YAML(写FederatedXxx),而且跨集群服务发现、流量治理这种硬骨头它没解决好。于是出现了更现代的方案,代表是Karmada。
【Karmada 思路: 更接近"多集群的K8s"】
Karmada 控制面
├── karmada-apiserver (兼容K8s API!)
├── karmada-scheduler (把资源调度到成员集群)
└── karmada-controller
关键差别: 你写的还是原生 Deployment/Service YAML!
只是通过 "PropagationPolicy" 决定发到哪些集群
→ 不用学一套新API, 迁移成本低
# 原生Deployment照写, 另外配一个分发策略
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: order–prop
namespace: shop
spec:
resourceSelectors:
– apiVersion: apps/v1
kind: Deployment
name: order–service
placement:
clusterAffinity:
clusterNames: [cluster–east, cluster–north]
spreadConstraints:
– spreadByField: cluster
maxGroups: 2 # 至少分到2个集群
要点:Karmada相比KubeFed最大的进步是**“API兼容”**——你继续写原生K8s YAML,用一份PropagationPolicy描述分发意图,不用把每个资源都改写成Federated类型。这也是它现在更受欢迎的原因。
五、真正难的活:跨集群服务发现与流量
联邦把"资源分发"解决了,但用户访问时的问题是:我该打到哪个集群?集群A挂了怎么切到B?
【跨集群流量调度】
用户
│
▼
全局负载均衡(GSLB / DNS 按地域)
│
├── 华东用户 → 集群A Ingress
└── 华北用户 → 集群B Ingress
集群间:
– 服务发现: 各集群独立Service, 靠外部GSLB分流
– 数据同步: 数据库主从/多活(不在K8s职责内)
– 故障切换: 健康检查失败 → DNS/Anycast切走
主流做法分两层:
- 南北向(用户→集群):靠云厂商GSLB、DNS按地域解析、或Cloudflare/Alb等做全局流量管理。集群挂了就把解析切走。
- 东西向(集群↔集群):如果集群间要互相调用,用Cilium Cluster Mesh或Submariner(第050篇讲过的多集群网络)打通Pod网络,让A集群的Pod能直接访问B集群的Service。
要点:多集群的"难"不在分发,在状态与流量。无状态服务好办(分发+GSLB),有状态服务(数据库)的多活/主从才是噩梦——这部分通常不在K8s层解决,而靠数据库自身的主从复制。
六、多集群可观测性
多个集群,监控也不能各看各的。常见两种思路:
| 全局Prometheus | 各集群remote-write到中心Prometheus | 集群数不多、网络稳 |
| Thanos / Cortex | 各集群Prometheus本地存,全局查询层聚合 | 大规模、长期存储 |
| 多集群Grafana | 一个Grafana配多个数据源 | 轻量统一看板 |
# 各成员集群的Prometheus加remoteWrite(示例)
global:
remote_write:
– url: http://thanos–receiver.federation.svc:19291/api/v1/receive
七、选型建议
| 只是灾备用,平时一个主一个备 | 主备 + Velero定期备份(第082篇),别上联邦 |
| 多地域低延迟,无状态服务多 | GSLB分流 + Karmada分发 |
| 混合云不想绑定厂商 | Karmada + 各云原生CSI/CNI |
| 集群间要Pod直连调用 | Cilium Cluster Mesh / Submariner(第050篇) |
| 只是想统一管理kubectl | kubectl context 切换 + 轻量面板即可 |
要点:很多团队一上来就上联邦,结果90%的集群从来不会切换,纯增加复杂度。先问"真有多集群故障切换需求吗",没有就主备+备份够了,别为联邦而联邦。
本篇小结
多集群是单集群撞上故障域、地域延迟、厂商锁定三道天花板后的必然选择。KubeFed v2用"联邦控制面+一套Federated资源"实现了声明一次多集群落地,但侵入式API和跨集群服务治理短板让它逐渐边缘化;Karmada用"原生YAML + PropagationPolicy"的兼容思路成了更主流的现代方案。
但要记住:分发容易,流量和状态难。无状态服务靠GSLB分流+联邦分发即可,有状态服务多活才是硬骨头。别为了联邦而联邦——没真实切换需求,主备+Velero备份往往更省心。下篇换个"重"话题:在K8s上跑AI/ML工作负载。
上一篇【第87篇】微服务应用K8s化改造实战——从传统部署到云原生 下一篇【第89篇】K8s + AI/ML——在K8s上运行机器学习工作负载

