CNCF毕业的多集群编排项目,统一调度与故障迁移
Karmada(Kubernetes Armada)是华为开源、现已从 CNCF 毕业的多集群管理项目(2026 年 9 月正式毕业,与 v1.19 版本同期发布)。它解决的是这样一个问题:当你有多个 Kubernetes 集群时,如何用一套 API 把应用分发到多个集群,并支持副本拆分、差异化配置、故障自动迁移。
Karmada 与 Cluster API 的定位经常被混淆,其实完全不同:
对比项 Karmada Cluster API
解决的问题 多集群上的「应用怎么跑」 集群本身的「创建与生命周期」
关注对象 Deployment / Service 等业务 Cluster / Machine 等基础设施
集群来源 已有集群,纳管进来 由 CAPI 创建出来
调度能力 跨集群副本拆分、故障迁移 无(集群级)
简单说:Cluster API 管「有哪几个集群」,Karmada 管「应用怎么分布到这些集群上」。两者可以叠加使用。
Karmada 的核心价值在于不改造应用:你的 Deployment、Service、ConfigMap 写法与单集群完全一致,只是多写一份 PropagationPolicy 说明「要发到哪些集群、副本怎么分」。
Karmada 的控制平面自己就是一套完整的 Kubernetes API Server,而不是一个普通的 CRD 控制器:
karmada-apiserver 独立的 API Server,承载多集群相关 CRD
karmada-controller-manager 核心控制器,负责资源分发与状态收集
karmada-scheduler 多集群调度器,决定资源落到哪些集群
karmada-webhook 准入校验
karmada-aggregated-apiserver 聚合 API,提供集群访问代理
kube-controller-manager 复用上游控制器
etcd 以 StatefulSet 形式运行
默认都装在 karmada-system 命名空间下。此外每个被纳管的成员集群上会有一个 karmada-agent(拉模式)或不需要 agent(推模式)。
两种接入模式:
Push 模式 Karmada 直接持有成员集群的 kubeconfig,主动下发资源
Pull 模式 成员集群上部署 karmada-agent,由 agent 反向拉取指令
适合成员集群在防火墙后、或跨云跨边的场景
# 方式一:karmadactl(kubectl 插件形式等价,kubectl karmada init)
kubectl karmada init
# 指定数据与 PKI 目录(默认会写 /etc/karmada,需要提权)
kubectl karmada init --karmada-data=/opt/karmada --karmada-pki=/opt/karmada/pki
# 控制平面高可用
kubectl karmada init --karmada-apiserver-replicas 3 --etcd-replicas 3
# 离线环境:指定 CRD 包与镜像
kubectl karmada init --crds=<crds.tar.gz 路径> \
--karmada-controller-manager-image=<私有仓库地址>
# 指定宿主集群的 kubeconfig
kubectl karmada init --kubeconfig=$HOME/.kube/host.config
安装脚本会输出 karmada-apiserver 的 kubeconfig 路径,通常可以直接用:
export KUBECONFIG=/etc/karmada/karmada-apiserver.config
kubectl get clusters
kubectl get pods -n karmada-system
本地开发环境(用 kind 拉起,自动创建成员集群):
git clone https://github.com/karmada-io/karmada
cd karmada
hack/local-up-karmada.sh
export KUBECONFIG="$HOME/.kube/karmada.config" # Karmada 控制平面
export KUBECONFIG="$HOME/.kube/members.config" # 成员集群(member1/2/3)
# 推模式:注册已有集群
karmadactl join member1 \
--cluster-kubeconfig=$HOME/.kube/member1.config \
--cluster-context=member1
# 拉模式:在成员集群侧执行 register
karmadactl register <karmada-apiserver-address> \
--token=<token> --discovery-token-ca-cert-hash=sha256:<hash>
# 查看成员集群
kubectl get clusters
karmadactl get clusters
# 摘除集群
karmadactl unjoin member1
应用本身不需要任何改动,照常用 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 4
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
再写一份 PropagationPolicy 说明分发策略:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: nginx
placement:
clusterAffinity:
clusterNames:
- member1
- member2
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
staticWeightList:
- targetCluster:
clusterNames:
- member1
weight: 3
- targetCluster:
clusterNames:
- member2
weight: 1
关键字段的含义:
replicaSchedulingType: Duplicated 每个集群都跑完整副本数(默认)
replicaSchedulingType: Divided 总副本数按权重拆分到各集群
replicaDivisionPreference: Weighted / Aggregated
clusterAffinity 指定集群名单或标签选择器
spreadConstraints 约束副本在故障域上的分布
同一个应用分发到不同集群时,镜像地址、副本数、资源配额往往不同,用 OverridePolicy 表达:
apiVersion: policy.karmada.io/v1alpha1
kind: OverridePolicy
metadata:
name: nginx-override
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: nginx
overrideRules:
- targetCluster:
clusterNames:
- member2
overriders:
plaintext:
- path: /spec/template/spec/containers/0/image
operator: replace
value: registry.cn-hangzhou.aliyuncs.com/library/nginx:1.27
Karmada 会检测成员集群的健康状态,当集群变为 NotReady 时自动把工作负载迁移到其他可用集群:
# 查看集群状态
kubectl get clusters -o wide
# 模拟成员集群失联
kubectl --kubeconfig=$HOME/.kube/members.config \
--context=member1 scale deploy -n kube-system coredns --replicas=0
# 观察工作负载被重新调度
kubectl --kubeconfig=$HOME/.kube/karmada.config get work -A
污点与容忍度可以控制哪些应用允许被迁移:
spec:
placement:
clusterTolerations:
- key: cluster.karmada.io/not-ready
operator: Exists
effect: NoExecute
tolerationSeconds: 300
# Karmada 把每个资源的分发状态记录在 ResourceBinding 与 Work 中
kubectl get resourcebindings -A
kubectl get works -A
kubectl describe work nginx-propagation-default
# 查看某成员集群上实际生效的清单
kubectl get work <work-name> -n <namespace> -o yaml
# 启用官方 addon(需 karmadactl)
karmadactl addons enable karmada-search # 多集群资源检索
karmadactl addons enable karmada-metrics-adapter # 多集群指标
karmadactl addons enable karmada-scheduler-estimator
karmadactl addons list
karmada-search 提供跨集群的资源查询,karmada-metrics-adapter 让 kubectl top 能跨集群工作,多集群 HPA 则依赖它们。
kubectl karmada init 默认要写 /etc/karmada,需要提权。容器化或受限环境里应显式用 --karmada-data 与 --karmada-pki 指定可写目录。karmadactl register。模式选错会表现为集群一直处于 NotReady。PropagationPolicy 的默认行为是「每集群全量副本」。不写 replicaScheduling 时,replicas: 4 会变成每个集群 4 个副本,总副本数被放大。要做总量控制必须显式写 replicaSchedulingType: Divided,这是新手最容易踩的坑。PropagationPolicy 与 ClusterPropagationPolicy 作用域不同。前者是命名空间级的,后者是集群级的;分发 Namespace、ClusterRole 这类集群级资源只能用后者。kubectl get propagationpolicy -A 有没有覆盖到。work.karmada.io/...)用于冲突检测;如果成员集群上已经手工创建了同名资源,Karmada 默认不会覆盖,会报冲突。clusterTolerations 里的 tolerationSeconds;没有配置容忍度的应用在集群失联时会停在原地。指望「秒级切换」的团队需要先确认这套参数。ServiceImport/ServiceExport),但底层网络连通性仍然要靠 Cilium ClusterMesh、Submariner 这类方案解决,Karmada 不负责跨集群的数据面。kube-controller-manager、kube-apiserver 用的是上游镜像(例如 v1.30.x 系列)。升级前先查兼容矩阵,不要直接替换镜像。kubectl — Kubernetes集群管理工具cluster-api — 负责集群生命周期的上游项目kubeadm — Kubernetes集群安装工具argocd — 另一种应用分发方案istio — 跨集群服务网格