上一篇【第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/v1beta1kind:FederatedDeploymentmetadata:name:order-servicenamespace:shopspec:template:# 这就是普通的Deployment specmetadata:labels:{app:order-service}spec:replicas:6template:spec:containers:-name:order-serviceimage:registry.example.com/order-service:1.5.0placement:clusters:-name:cluster-east# 发到华东-name:cluster-north# 发到华北overrides:-clusterName:cluster-eastclusterOverrides:-path:/spec/replicasvalue:4# 华东放4副本-clusterName:cluster-northclusterOverrides:-path:/spec/replicasvalue:2# 华北放2副本(用户少)要点:KubeFed的优雅之处在于**“声明一次,多集群落地”**——你只写一份FederatedDeployment,联邦控制器帮你把真正的Deployment同步到每个成员集群,还能按集群差异化覆盖副本数、镜像等。
三、副本怎么分:ReplicaSchedulingPreference
光指定"发到哪"不够,副本怎么切也讲究。RSP(ReplicaSchedulingPreference)支持按权重、按集群容量动态分配:
apiVersion:scheduling.kubefed.io/v1alpha1kind:ReplicaSchedulingPreferencemetadata:name:order-servicenamespace:shopspec:targetKind:FederatedDeploymenttotalReplicas:10clusters:cluster-east:weight:3# 华东权重3cluster-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/v1alpha1kind:PropagationPolicymetadata:name:order-propnamespace:shopspec:resourceSelectors:-apiVersion:apps/v1kind:Deploymentname:order-serviceplacement:clusterAffinity:clusterNames:[cluster-east,cluster-north]spreadConstraints:-spreadByField:clustermaxGroups: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上运行机器学习工作负载