资源分发
Karmada 提供了 PropagationPolicy 和 ClusterPropagationPolicy 两种 API 用于资源分发。关于这两种 API 的区别,可参考 此处。
本文将以 PropagationPolicy 为例,介绍资源分发的具体操作方法。
前提条件
请先 安装 Karmada,并准备好 karmadactl 命令行工具。
注意:在此之前,我们需要将 kubectl 指向
<karmada-apiserver.config>,而不是成员集群。
部署最简单的多集群 Deployment
创建 PropagationPolicy 对象
可通过创建 YAML 文件定义的 PropagationPolicy 对象来分发 Deployment 资源。例如,以下 YAML 文件描述了:需将 default 命名空间下名为 nginx 的 Deployment 对象分发到 member1 集群:
# propagationpolicy.yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: example-policy # The default namespace is `default`.
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: nginx # If no namespace is specified, the namespace is inherited from the parent object scope.
placement:
clusterAffinity:
clusterNames:
- member1
- 基于上述 YAML 文件创建分发策略:
kubectl apply -f propagationpolicy.yaml
- 创建名为 nginx 的 Deployment:
kubectl create deployment nginx --image nginx
注意:该资源在 Karmada 中仅作为模板存在;分发到成员集群后,其行为与单 Kubernetes 集群中的资源行为一致。
注意:资源与分发策略的创建无先后顺序要求。
- 查看 Deployment 的分发状态:
karmadactl get deployment
输出结果示例如下:
NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION
nginx member1 1/1 1 1 52s Y
- 查看该 Deployment 在成员集群中创建的 Pod:
karmadactl get pod -l app=nginx
输出结果示例如下:
NAME CLUSTER READY STATUS RESTARTS AGE
nginx-6799fc88d8-s7vv9 member1 1/1 Running 0 52s
更新分发策略
可通过应用新的 YAML 文件来更新分发策略。例如,以下 YAML 文件将 nginx Deployment 的分发目标修改为 member2 集群:
# propagationpolicy-update.yaml
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: example-policy
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: nginx
placement:
clusterAffinity:
clusterNames: # Modify the selected cluster to propagate the Deployment.
- member2
- 应用更新后的 YAML 文件:
kubectl apply -f propagationpolicy-update.yaml
- 更新后,查看 Deployment 信息(输出示例如下):
NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION
nginx member2 1/1 1 1 5s Y
- 查看更新后 Deployment 对应的 Pod(输出示例如下):
NAME CLUSTER READY STATUS RESTARTS AGE
nginx-6799fc88d8-8t8cc member2 1/1 Running 0 17s
更新 Deployment
可直接更新 Karmada 中的 Deployment 模板,修改会自动同步到所有成员集群。
- 将 Deployment 的副本数(replicas)更新为 2
- 更新后查看 Deployment 信息(输出示例如下):
NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION
nginx member2 2/2 2 2 7m59s Y
- 查看更新副本数后对应的 Pod(输出示例如下):
NAME CLUSTER READY STATUS RESTARTS AGE
nginx-6799fc88d8-8t8cc member2 1/1 Running 0 8m12s
nginx-6799fc88d8-zpl4j member2 1/1 Running 0 17s
删除分发策略
通过名称删除分发策略:
kubectl delete propagationpolicy example-policy
删除分发策略不会删除已分发到成员集群的 Deployment,需单独在 Karmada 控制平面中删除 Deployment。
在 Karmada 控制平面中删除 nginx Deployment:
kubectl delete deployment nginx
将 Deployment 部署到指定的目标集群集合
PropagationPolicy 的 .spec.placement.clusterAffinity 字段用于定义集群调度约束;若不配置该字段,所有集群均会成为调度候选。
该字段支持以下 4 种配置方式:
- LabelSelector(标签选择器)
- FieldSelector(字段选择器)
- ClusterNames(集群名称列表)
- ExcludeClusters(排除集群列表)
LabelSelector(标签选择器)
通过集群标签筛选目标成员集群,使用 *metav1.LabelSelector 类型。若配置非空的标签选择器,仅匹配标签的集群会被选中。
配置方式 1:精确匹配标签:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
spec:
#...
placement:
clusterAffinity:
labelSelector:
matchLabels:
location: us
#...
配置方式 2:表达式匹配标签:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
spec:
#...
placement:
clusterAffinity:
labelSelector:
matchExpressions:
- key: location
operator: In
values:
- us
#...
关于 matchLabels 和 matchExpressions 的详细说明,可参考支持集合型需求的资源文档。
FieldSelector(字段选择器)
通过集群字段筛选目标成员集群。若配置非空的字段选择器,仅匹配字段的集群会被选中。
配置示例
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
#...
placement:
clusterAffinity:
fieldSelector:
matchExpressions:
- key: provider
operator: In
values:
- huaweicloud
- key: region
operator: NotIn
values:
- cn-south-1
#...
字段选择器规则
- 若
fieldSelector中指定多个matchExpressions,集群需满足所有表达式才能被选中。 matchExpressions中的key目前支持 3 个值:provider(对应 Cluster 对象的.spec.provider字段)、region(对应.spec.region)、zone(对应.spec.zone)。matchExpressions中的operator目前支持In(在列表内)和NotIn(不在列表内)。
ClusterNames(集群名称列表)
用户可以直接指定目标集群的名称。
配置示例如下:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
#...
placement:
clusterAffinity:
clusterNames:
- member1
- member2
#...
ExcludeClusters(排除集群列表)
用户可以通过设置 ExcludeClusters 字段来指定需要忽略的集群。
分发策略(PropagationPolicy)可按如下方式配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
#...
placement:
clusterAffinity:
exclude:
- member1
- member3
#...
多集群亲和性组
用户可通过设置 ClusterAffinities 字段,在分发策略(PropagationPolicy)中声明多个集群组。调度器会按照配置在 spec 中的顺序,逐一评估这些集群组:
- 不满足调度约束的集群组会被忽略(即该组内所有集群均不会被选中,除非集群同时属于下一个集群组 —— 一个集群可归属多个组)。
- 若所有集群组均不满足调度约束,调度会失败(无任何集群被选中)。
注意事项
ClusterAffinities(多集群亲和性组)与ClusterAffinity(单集群亲和性)不可同时配置。- 若未配置 ClusterAffinity 和 ClusterAffinities,则所有集群均会成为调度候选集群。
潜在应用场景1: 可将本地数据中心的私有集群设为主集群组,将云服务商提供的托管集群设为副集群组。这样,Karmada 调度器会优先将工作负载调度到主集群组;仅当主集群组不满足约束(如资源不足)时,才会考虑副集群组。
分发策略可按如下配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
spec:
#...
placement:
clusterAffinities:
- affinityName: local-clusters
clusterNames:
- local-member1
- local-member2
- affinityName: cloud-clusters
clusterNames:
- public-cloud-member1
- public-cloud-member2
#...
潜在应用场景2: 可将集群划分为主集群组和备集群组,工作负载会优先调度到主集群;当主集群发生故障(如数据中心断电)时,Karmada 调度器可将工作负载迁移到备集群。
分发策略可按如下配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
spec:
#...
placement:
clusterAffinities:
- affinityName: primary-clusters
clusterNames:
- member1
- affinityName: backup-clusters
clusterNames:
- member1
- member2
#...
如需了解更详细的设计信息,可参考 多调度组 文档。
基于污点和容忍的调度
分发策略(PropagationPolicy)的 .spec.placement.clusterTolerations 字段用于定义集群容忍规则。与 Kubernetes 类似,容忍规则需与集群上设置的 “污点” 配合使用:
- 若为集群设置了一个或多个污点,默认情况下工作负载无法调度或运行在这些集群上。
- 仅当分发策略明确声明 “容忍” 这些污点时,工作负载才能被调度到对应集群。
目前 Karmada 支持的污点效应(effect)包括 NoSchedule(不调度,仅影响新工作负载)和 NoExecute(不执行,既影响已运行工作负载,也影响新工作负载)。
你可以通过 karmadactl taint 命令为集群添加污点:
# Update cluster 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'
# If a taint with that key and effect already exists, its value is replaced as specified
karmadactl taint clusters foo dedicated=special-user:NoSchedule
若需将工作负载调度到上述带污点的集群(如 foo 集群),需在分发策略中声明对应的容忍规则,示例如下:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
#...
placement:
clusterTolerations:
- key: dedicated
value: special-user
Effect: NoSchedule
NoExecute 类型 的污点还可用于 “多集群故障转移” 场景,详情可参考 此处。
多区域高可用支持
通过 “按区域扩散约束”(spread-by-region constraint),用户可将工作负载部署到多个区域。例如,为实现高可用(HA),用户可能希望工作负载始终在不同区域运行。
要实现多区域部署,需先通过以下命令自定义集群的区域配置:
$ kubectl --kubeconfig ~/.kube/karmada.config --context karmada-apiserver edit cluster/member1
...
spec:
apiEndpoint: https://172.18.0.4:6443
id: 257b5c81-dfae-4ae5-bc7c-6eaed9ed6a39
impersonatorSecretRef:
name: member1-impersonator
namespace: karmada-cluster
region: test
...
之后,需限制待选中的集群组数量(最大值和最小值)。假设存在两个区域,且希望在每个区域各选择一个集群部署工作负载,可参考以下配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
#...
placement:
replicaScheduling:
replicaSchedulingType: Duplicated
spreadConstraints:
- spreadByField: region
maxGroups: 2
minGroups: 2
- spreadByField: cluster
maxGroups: 1
minGroups: 1
若副本分割偏好(ReplicaDivisionPreference)设为 StaticWeightList(静态权重列表),则扩散约束的声明会被忽略。
若扩散约束中使用了 SpreadByField(按字段扩散),则必须包含 SpreadByFieldCluster(按集群扩散)。
例如,当使用 SpreadByFieldRegion(按区域扩散)指定区域组时,需同时通过 SpreadByFieldCluster 指定每个区域应选中的集群数量。
副本调度的多种策略
当分发 “spec 字段中包含副本数配置的资源”(如 Deployment、StatefulSet,或可通过自定义资源解释器解析的 CRD)到成员集群时,.spec.placement.replicaScheduling 字段用于定义副本数的调度策略。
该字段包含两种 “副本调度类型”(replicaSchedulingType