分发策略
Karmada 提供了 PropagationPolicy 和 ClusterPropagationPolicy 两种 API 用于资源分发。关于这两种 API 的区别,可参考 此处。
本指南通过解释 API 规范中的每个字段来描述 PropagationPolicy 的配置选项。ClusterPropagationPolicy 与其共享相同的 spec 结构,因此示例对两者均适用。
ResourceSelectors(资源选择器)
resourceSelectors 字段指定应分发哪些资源。必须至少定义一个选择器。
ResourceSelector 通过 API 版本和 Kind 匹配资源,并可选择性地通过名称、标签和命名空间进一步筛选。如果未设置 name 或 labelSelector,它将匹配有效命名空间中(默认为策略的命名空间)给定 APIVersion/Kind 的所有资源。
匹配策略命名空间中的所有资源
如果省略 name 和 labelSelector,选择器将匹配有效命名空间(默认为策略命名空间)中指定 APIVersion/Kind 的所有资源:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: all-deployments
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinity:
clusterNames:
- member1
- member2
这将匹配策略命名空间中的所有 Deployment。
对于 ClusterPropagationPolicy,相同的选择器将匹配所有命名空间中的 Deployment。
按名称匹配
按名称匹配特定资源:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: nginx
placement:
clusterAffinity:
clusterNames:
- member1
这仅匹配策略命名空间中名为 nginx 的 Deployment。
按标签匹配
通过标签选择器匹配资源:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: app-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
labelSelector:
matchLabels:
app: nginx
placement:
clusterAffinity:
clusterNames:
- member1
这将匹配策略命名空间中带有标签 app=nginx 的 Deployment。
PropagateDeps(分发依赖)
propagateDeps 字段控制是否应自动分发依赖资源。
启用时,被分发工作负载引用的资源(例如,Deployment 引用的 ConfigMap 和 Secret)将自动分发,无需在 resourceSelectors 中列出它们。
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
namespace: default
name: nginx
propagateDeps: true
placement:
clusterAffinity:
clusterNames:
- member1
这会将 nginx Deployment 及其引用的依赖项分发到 member1。
Placement(分发位置)
placement 字段指定资源应如何分发到各个集群。它包括集群亲和性、扩散约束和副本调度策略。
Cluster Affinity(集群亲和性)
.spec.placement.clusterAffinity 字段 表示调度限制,用于限制可选择哪些集群。如果未指定,任何集群都可以成为调度候选集群。
ClusterAffinity 支持四种过滤机制:
- LabelSelector(标签选择器):按标签过滤集群
- FieldSelector(字段选择器):按字段(provider、region、zone)过滤集群
- ClusterNames(集群名称):显式列出集群名称
- ExcludeClusters(排除集群):显式排除集群名称
当指定多个过滤机制时,它们以逻辑 AND 组合,这意味着集群必须匹配所有指定条件才能被选中。
clusterAffinity 定义了集群的候选集——它指定哪些集群有资格被选择,但不保证它们都会被选中。调度器会根据各种因素(如调度策略、集群健康状况和资源可用性)从此候选集中进行选择。要严格控制选择多少个集群,请将 spreadConstraints 与 clusterAffinity 结合使用。
例如,如果在 clusterNames 中指定了 10 个集群,但希望确保仅选择 2 个,可将其与 spreadConstraints 结合,使用 spreadByField: cluster 并设置 maxGroups: 2, minGroups: 2。
LabelSelector(标签选择器)
LabelSelector 是按标签选择成员集群的过滤器。它使用 *metav1.LabelSelector 类型。如果它非 nil 且非空,它将过滤候选集以仅包含匹配此过滤器的集群。
PropagationPolicy 可按如下方式配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinity:
labelSelector:
matchLabels:
location: us
这将创建标记为 location=us 的集群候选集。
PropagationPolicy 也可按如下方式配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinity:
labelSelector:
matchExpressions:
- key: location
operator: In
values:
- us
这使用基于集合的选择器过滤候选集,仅包含其 location 标签在 us 中的集群。
有关 matchLabels 和 matchExpressions 的描述,您可以参考支持基于集合的需求的资源。
FieldSelector(字段选择器)
FieldSelector 是按字段选择成员集群的过滤器。如果它非 nil 且非空,它将过滤候选集以仅包含匹配此过滤器的集群。
PropagationPolicy 可按如下方式配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinity:
fieldSelector:
matchExpressions:
- key: provider
operator: In
values:
- aws
- key: region
operator: NotIn
values:
- us-west-1
这定义了来自 provider aws 的集群候选集,同时排除 region us-west-1 中的集群。
如果在 fieldSelector 中指定了多个 matchExpressions,集群必须匹配所有 matchExpressions。
matchExpressions 中的 key 现在支持三个值:provider、region 和 zone,它们分别对应 Cluster 对象的 .spec.provider、.spec.region 和 .spec.zone 字段。
matchExpressions 中的 operator 现在支持 In 和 NotIn。
ClusterNames(集群名称)
用户可以设置 ClusterNames 字段来指定选定的集群。
PropagationPolicy 可按如下方式配置:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinity:
clusterNames:
- member1
- member2
这将候选集限制为 member1 和 member2。
ExcludeClusters(排除集群)
显式排除集群被选中:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinity:
exclude:
- member1
- member3
这将从候选集中排除 member1 和 member3。
ClusterAffinities(多个集群组)
clusterAffinities 字段允许定义多个具有回退行为的集群组。clusterAffinity 定义一组选择条件,这些条件一起应用以产生单个候选集群集。clusterAffinities 定义多个有序的条件集(组),这些条件集按顺序评估:调度器尝试第一组,仅当前一组无法满足调度时才回退到下一组。
clusterAffinities 不能与 clusterAffinity 共存。
工作原理
调度器按顺序评估亲和性组:
- 尝试使用第一组进行调度
- 如果第一组不满足调度限制,尝试下一组
- 一个集群可以属于多个组
- 如果没有组满足限制,调度失败
ClusterAffinityTerm
clusterAffinities 中的每个组由一个 ClusterAffinityTerm 定义,包含以下内容:
affinityName:集群组的可读名称- 内联
ClusterAffinity字段,如labelSelector、fieldSelector、clusterNames和exclude:定义该 term 的主集群组 overflowAffinities(可选):附加的有序集群组,仅在同一 term 中的主集群组无法容纳调度时才会被使用
通过 overflowAffinities,可以实现溢出调度场景,例如优先调度到 IDC 集群,当 IDC 资源不足时溢出到云端集群。
由于溢出调度需要感知成员集群的可用资源,目前不支持副本复制模式和静态权重分配与溢出调度组合使用。
overflowAffinities 工作原理

调度器按顺序评估主集群组和溢出集群组:
- 尽可能将副本分配到主集群组。
- 如果主集群组无法容纳所有副本,则尝试将剩余副本分配到溢出集群组。
- 对于每个溢出组,分配的副本数为剩余未分配副本数与该组总可用容量中的较小值。
- 在每个组内,副本根据
placement.replicaScheduling策略分配到各集群。 - 一旦所有副本都能被分配,调度成功。如果评估完所有组后仍有副本未分配, 则此 ClusterAffinityTerm 调度失败,调度器将继续评估 clusterAffinities 中的下一个 ClusterAffinityTerm(如有)。
用例 1:本地集群作为主集群,云集群作为备份
本地数据中心的私有集群可以作为主组,集群提供商提供的托管集群可以作为次要组。调度器会优先调度到主组,仅当主组缺乏资源时 才考虑第二组。
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinities:
- affinityName: local-clusters
clusterNames:
- local-member1
- local-member2
- affinityName: cloud-clusters
clusterNames:
- public-cloud-member1
- public-cloud-member2
这优先选择本地集群,如果它们无法满足调度,则回退到云组。
用例 2:灾难恢复(主集群和备份集群)
集群被组织为主组和备份组。工作负载首先调度到主集群,如果主集群失败则迁移到备份集群。
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: test-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinities:
- affinityName: primary-clusters
clusterNames:
- member1
- member2
- affinityName: backup-clusters
clusterNames:
- member3
- member4
这首先尝试主集群,如果主集群失败,则将工作负载移动到备份组。
用例 3:从 IDC GPU 集群溢出到云端 GPU 集群
IDC GPU 集群可以作为运行 GPU 推理工作负载的主集群组,而云端 GPU 集群可以作为处理额外峰值流量的溢出集群组。调度器会优先将副本填充到 IDC 集群中,仅当 IDC 集群无法容纳所有副本时,才会将剩余副本溢出到云端集群。
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: gpu-inference-overflow
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterAffinities:
- affinityName: idc-gpu
clusterNames:
- idc-gpu-cluster1
overflowAffinities:
- affinityName: cloud-gpu
clusterNames:
- cloud-gpu-cluster1
- cloud-gpu-cluster2
replicaScheduling:
replicaSchedulingType: Divided
replicaDivisionPreference: Weighted
weightPreference:
dynamicWeight: AvailableReplicas
这会优先使用 IDC GPU 集群;仅当 IDC 集群无法容纳所有副本时,才会溢出到云端 GPU 集群。当流量下降时,副本会优先从云端 GPU 集群回收,从而保持 GPU 使用的成本效益。
ClusterTolerations(集群容忍)
.spec.placement.clusterTolerations 字段表示集群容忍。与 Kubernetes 类似,容忍与集群上的污点配合使用。
在集群上设置一个或多个污点后,除非策略明确容忍这些污点,否则工作负载无法调度到该集群。Karmada 目前支持具有 NoSchedule 和 NoExecute 效果的污点。
设置集群污点
使用 karmadactl taint 为集群添加污点:
# 使用键 'dedicated'、值 'special-user' 和效果 'NoSchedule' 更新集群 'foo' 的污点
# 如果具有该键和效果的污点已存在,则其值将被替换为指定的值
karmadactl taint clusters foo dedicated=special-user:NoSchedule
容忍集群污点
要调度到被污染的集群,在策略中声明容忍:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
clusterTolerations:
- key: dedicated
value: special-user
effect: NoSchedule
这允许调度到被污染为 dedicated=special-user:NoSchedule 的集群。
NoExecute 效果也用于多集群故障转移。
SpreadConstraints(扩散约束)
.spec.placement.spreadConstraints 字段控制如何根据拓扑域(集 群、区域、地带或提供商)将资源分散到集群。
扩散约束的工作原理
扩散约束根据指定字段将集群划分为组,并对选择多少个组施加约束:
- SpreadByField:按内置字段对集群分组
cluster(已支持)region(已支持)zone(尚未实现)provider(尚未实现)
- SpreadByLabel:按自定义标签对集群分组
- MaxGroups:要选择的最大组数
- MinGroups:要选择的最小组数(默认为 1)
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
placement:
replicaScheduling:
replicaSchedulingType: Duplicated
spreadConstraints:
- spreadByField: region
maxGroups: 2
minGroups: 2
- spreadByField: cluster
maxGroups: 2
minGroups: 2
这将工作负载分散到恰好两个区域,每个区域一个集群(总共两个集群)。
如果副本分割偏好是 StaticWeightList,则不应用扩散约束。
如果使用 SpreadByField,您还必须指定集群级别的扩散约束。例如,当使用 SpreadByFieldRegion 指定区域组时,您还必须使用 SpreadByFieldCluster 指定要选择多少个集群。
ReplicaScheduling(副本调度)
.spec.placement.replicaScheduling 字段定义在分发具有副本规范的资源(例如 Deployment、StatefulSet 或自定义 CRD)时应如何分配副本。
有两种副本调度类型:
- Duplicated(复制):每个集群接收来自资源规范的完整副本数
- Divided(分割):总副本根据
ReplicaDivisionPreference在选定的集群之间分割
Duplicated 模式
所有选定的集群接收相同数量的副本:
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:
replicaSchedulingType: Duplicated
这创建了 member1 和 member2 的候选集,并将完整的副本数发送到选定的集群。要确切确保选择多少个集群,请使用 spreadConstraints(参见 SpreadConstraints 部分)。
Divided 模式
总副本在选定的集群之间分割。分割策略由 ReplicaDivisionPreference 确定:
Aggregated(聚合)分割
将副本分割到尽可能少的集群中,同时尊重它们的可用资源。注意:该分割方法不会响应 spreadConstraints 配置因为它旨在最小化所使用的集群数量。
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:
replicaSchedulingType: Divided
replicaDivisionPreference: Aggregated
这将副本分割到来自候选集(member1 和 member2)的尽可能少的集群中。
Weighted(加权)分割
按权重分割副本。支持两种权重方法:
StaticWeightList(静态权重列表):显式为集群分配权重
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: nginx
placement:
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
staticWeightList:
- targetCluster:
clusterNames:
- member1
weight: 1
- targetCluster:
clusterNames:
- member2
weight: 2
这按静态权重的比例分配副本。对于 3 个副本:member1 获得 1 个副本(权重 1),member2 获得 2 个副本(权重 2)。
如果您需要精确控制为加权分配选择多少个集群,请将 spreadConstraints 与权重偏好结合:
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
spreadConstraints:
- spreadByField: cluster
maxGroups: 2
minGroups: 2
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
staticWeightList:
- targetCluster:
clusterNames:
- member1
weight: 1
- targetCluster:
clusterNames:
- member2
weight: 2
这通过 spreadConstraints 确保恰好选择 2 个集群,并按指定的权重(1:2 比例)在它们之间分配副本。
DynamicWeight(动态权重):根据可用资源生成权重
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: nginx-propagation
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: nginx
placement:
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
dynamicWeight: AvailableReplicas
这根据可用容量计算权重,因此副本按每个集群可以容纳的数量成比例地分割。
使用 AvailableReplicas,权重基于每个集群可以容纳多少副本来计算:
- 如果集群 A 可以容纳 6 个副本,B 可以容纳 12 个,C 可以容纳 18 个
- 权重变为 A:B:C = 6:12:18 (1:2:3)
- 对于 12 个总副本,分配为 A:2, B:4, C:6
如果 ReplicaDivisionPreference 设置为 Weighted 而没有 WeightPreference,则所有集群权重相等。