
# 分发策略 PropagationPolicy
#### 概述
PropagationPolicy 是UCS集群联邦的核心 API 之一，用于定义多集群环境中的资源分发策略。该 API 支持将 Kubernetes 资源分发到一个或多个成员集群，并提供灵活的调度、资源管理功能。与Karmada的PropagationPolicy接口兼容。
分发策略 PropagationPolicy具有以下主要特征：
- **多集群资源分发**: 支持将资源分发到多个 Kubernetes 集群
- **灵活的调度策略**: 提供静态权重、复制分发和分散部署等多种调度方式
- **资源依赖管理**: 自动分发相关依赖资源
分发策略 PropagationPolicy相关类型如下：
- **PropagationPolicy:** 用于命名空间作用域的资源分发，只能分发其所在命名空间的资源。详情可参见[什么是命名空间作用域的资源?](https://kubernetes.io/zh-cn/docs/reference/using-api/api-concepts/)
- **ClusterPropagationPolicy:** 支持集群作用域的资源分发，包括PersistentVolume、StorageClass、CustomResourceDefinition，也支持任意命名空间（不包括系统命名空间）的资源分发。详情可参见[什么集群作用域的资源?](https://kubernetes.io/zh-cn/docs/reference/using-api/api-concepts/)
 
#### API规范
基本信息：
```
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
```
作用范围：
- **PropagationPolicy**: 命名空间级别，只能分发所在命名空间的资源
- **ClusterPropagationPolicy**: 集群级别，可分发集群级别资源和任意命名空间的资源
 
#### 资源格式
**PropagationPolicy YAML 模板：**
```
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: <policy-name>
  namespace: <namespace-name>  # 仅 PropagationPolicy 需要
spec:
  resourceSelectors: []        # 必需，选择要分发的资源  
  conflictResolution: <string> # Abort/Overwrite
  dependentOverrides: []       # 依赖的 OverridePolicy
  placement:                   # 必需，集群选择规则
    clusterAffinity:
      clusterNames: []
    clusterTolerations: []
    replicaScheduling:
      replicaSchedulingType: "Divided"     # Duplicated/Divided
      replicaDivisionPreference: "Weighted"  # Aggregated/Weighted
      weightPreference:
        dynamicWeight: ""
        staticWeightList: []
    spreadConstraints: []
  propagateDeps: false         # 自动分发依赖
```
**ClusterPropagationPolicy YAML 模板**
```
apiVersion: policy.karmada.io/v1alpha1
kind: ClusterPropagationPolicy
metadata:
  name: <policy-name>
spec:
  # 与 PropagationPolicy 的 spec 结构相同
  resourceSelectors: []
  placement: {}
  # ... 其他字段
```
#### 参数详细说明
1. **resourceSelectors（必需）** ：选择要分发的 Kubernetes 资源。包含以下字段：
   - apiVersion (string, 必需): 目标资源的 API 版本
   
   - kind (string, 必需): 目标资源的类型（Deployment, Service, ConfigMap 等）
   
   - name (string): 目标资源的名称，空字符串表示匹配所有
   
   - namespace (string): 目标资源的命名空间
   
   - labelSelector (LabelSelector): 标签选择器
   
   
   **使用示例：**
   ```
   resourceSelectors:
     # 精确匹配
     - apiVersion: apps/v1
       kind: Deployment
       name: web-app
       namespace: default
     # 标签选择
     - apiVersion: v1
       kind: ConfigMap
       labelSelector:
         matchLabels:
           app: web-app
         matchExpressions:
           - key: tier
             operator: In
             values: ["frontend", "backend"]
   ```
   
2. **placement** ：定义资源分发到哪些集群的规则。
   - **clusterAffinity**
     ```
     placement:
       clusterAffinity:
         clusterNames: ["cluster-1", "cluster-2"]  # 指定集群列表
     ```
     
   
   - **replicaScheduling（副本调度）**
   
   
   ```
   placement:
     replicaScheduling:
       replicaSchedulingType: "Divided"         # 调度类型
       replicaDivisionPreference: "Weighted"    # 分配偏好
       weightPreference:
         dynamicWeight: "AvailableReplicas"     # 动态权重
         staticWeightList:                      # 静态权重
           - targetCluster:
               clusterNames: ["cluster-1"]
             weight: 2
           - targetCluster:
               clusterNames: ["cluster-2"]
             weight: 1
   ```
   **调度类型说明**:
   - Duplicated: 将相同的副本数复制到每个候选集群
   
   - Divided: 根据候选集群数量分配副本数 **分配偏好说明**:
     
   
   - Weighted: 按权重分配副本
   
   - Aggregated: 尽量分配到资源充足的集群
    
3. **spreadConstraints（分散约束）** ：用于控制资源在多个集群间的分布策略，确保高可用性和资源分散。
   ```
   placement:
     spreadConstraints:
       - spreadByField: "cluster"        # 按集群维度分散：仅支持`cluster`维度
         minGroups: 3                         # 最少分布在 3 个不同的集群中
         maxGroups: 5                        # 最多分布在 5 个不同的集群中
   ```
   **字段说明**：
   - spreadByField: 按集群维度分散约束，仅支持cluster维度
   
   - minGroups : 最少集群数
   
   - maxGroups: 最多集群数
   
   
   ![](https://support.huaweicloud.com/api-ucs/public_sys-resources/caution_3.0-zh-cn.png)
   在静态权重模式下，spreadConstraints 约束不会生效。
   在以下情况，系统将根据权重规则或默认行为进行调度，而不考虑 spreadConstraints 的分散约束：   
   - 使用拆分模式（replicaSchedulingType: Divided）+ 权重分配（replicaDivisionPreference: Weighted）+ 配置静态权重列表（weightPreference: staticWeightList）/ 未配置权重偏好（weightPreference为空）。
     
4. 其他重要参数
   - **conflictResolution**
     ```
     conflictResolution: "Abort"  # Abort: 停止分发 | Overwrite: 覆盖现有资源
     ```
     
   
   - **propagateDeps**
     ```
     propagateDeps: true  # 自动分发依赖的 ConfigMap、Secret 等资源
     ```
     
   
   - **clusterTolerations**
     ```
     clusterTolerations:  # 自动添加的集群容忍策略，避免因为集群状态异常导致pod重调度
     - key: cluster.karmada.io/not-ready
       operator: Exists
     - key: cluster.karmada.io/unreachable
       operator: Exists
     ```
     
    
 
#### 提升工作负载部署的稳定性与可预测性
为了确保您的工作负载在 Karmada 环境中运行更加稳定、可预测，并有效规避潜在的生产风险，我们对集群和副本调度相关的配置逻辑进行了优化和加强。这些改进旨在引导用户采用更符合最佳实践的配置模式，从而获得更可靠的部署体验。
**集群亲和性配置优化**
在定义工作负载的集群亲和性（ClusterAffinity）时，我们引入了更明确和直接的配置要求。现在，为了确保集群选择的清晰性和精确性，建议您：
- **明确指定目标集群：** 请直接通过 clusterNames 字段来指定您希望部署的集群。这种方式能够提供最直观、最无歧义的集群定位，从而避免因动态匹配可能带来的不确定性。
我们鼓励采用这种直接指定的方式，以确保您的工作负载能够准确无误地部署到预期的集群上，从而提升部署的可靠性。
**扩散约束配置指引**
为了更有效地管理工作负载在集群间的均匀分布，我们对扩散约束（SpreadConstraints）的配置进行了简化和规范。现在，当您配置扩散约束时：
- **与集群亲和性协同：** 扩散约束现在需要与 ClusterAffinity 字段协同使用，以确保扩散操作是在一个明确定义的集群范围内进行。
- **聚焦集群维度扩散：** 扩散维度（SpreadByField）将主要支持以"cluster"作为其唯一的扩散依据。这有助于实现更一致和可控的跨集群工作负载分布。
- **单一约束原则：** 为了避免复杂的、可能相互冲突的扩散规则，我们鼓励在一个数组元素中定义单一、清晰的扩散约束。
这些调整旨在确保工作负载的扩散逻辑更加直观、易于理解和管理，从而实现更均衡、高效的资源利用。
**副本调度策略增强**
当您使用 ReplicaSchedulingTypeDivided 策略进行副本调度时，我们对集群权重的配置提出了更严格的要求，以确保副本分配的精确性和可预测性：
- **权重配置的完整性：** 任何通过 ClusterAffinity 指定的候选集群，都必须在 WeightPreference.StaticWeightList 中明确配置其权重。
这一策略旨在保证所有被考虑用于副本调度的集群都拥有明确的权重定义，从而确保副本能够按照您预设的比例准确地分布，避免因缺少权重配置而导致的不平衡或意外行为。
我们相信这些优化将使您的部署管理更加高效、稳定，并降低潜在的运营风险。如果您在配置过程中遇到任何疑问，或需要进一步的帮助，请随时联系我们的支持团队。
#### 使用示例
**示例 1: 基础静态权重分发**
**场景**: 将 Web资源分发到 3 个集群，按 2:1:1 的比例分配副本
```
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: web-app-static-weight
  namespace: default
spec:
  resourceSelectors:
    - apiVersion: apps/v1
      kind: Deployment
      name: web-app
    - apiVersion: v1
      kind: Service
      name: web-app-service
    - apiVersion: v1
      kind: ConfigMap
      name: app-config
  placement:
    clusterAffinity:
      clusterNames: 
        - member1
        - member2
        - member3
    replicaScheduling:
      replicaSchedulingType: "Divided"
      replicaDivisionPreference: "Weighted"
      weightPreference:
        staticWeightList:
          - targetCluster:
              clusterNames: ["member1"]
            weight: 2  # 50% 副本
          - targetCluster:
              clusterNames: ["member2"]
            weight: 1  # 25% 副本
          - targetCluster:
              clusterNames: ["member3"]
            weight: 1  # 25% 副本
  propagateDeps: true                # 自动分发依赖资源
  conflictResolution: "Abort"        # 冲突时停止分发
```
**示例 2: 复制模式 (Duplicated) 部署**
**场景**: 需要在每个集群中都部署完整副本的资源
```
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: cache-cluster-duplicated
  namespace: production
spec:
  resourceSelectors:
    - apiVersion: apps/v1
      kind: Deployment
      name: redis-cluster
    - apiVersion: v1
      kind: ConfigMap
      name: redis-config
    - apiVersion: v1
      kind: Service
      name: redis-cluster-service
  placement:
    clusterAffinity:
      clusterNames:
        - cache-west-1
        - cache-east-1
        - cache-eu-1
    replicaScheduling:
      replicaSchedulingType: "Duplicated"  # 复制模式：每个集群获得完整副本    
  propagateDeps: true                      # 自动分发配置和依赖
  # 关键：复制模式下，所有集群都会获得完整的副本数量
  # 如果Deployment指定replicas: 3，那么每个集群都会运行3个副本
```
**示例 3: 复制模式 + DaemonSet 自动扩展集群**
**场景**: 部署 DaemonSet 到所有集群，当新增集群时自动部署，无需手动修改策略
```
# PropagationPolicy：选择所有集群的复制模式
apiVersion: policy.karmada.io/v1alpha1
kind: ClusterPropagationPolicy
metadata:
  name: file-sync-agent-auto-spread
spec:
  resourceSelectors:
    - apiVersion: apps/v1
      kind: DaemonSet
      name: file-sync-agent
    - apiVersion: v1
      kind: ConfigMap
      name: agent-config
    - apiVersion: v1
      kind: ServiceAccount
      name: file-sync-agent
  placement:
    # 关键：clusterAffinity 为空，自动选择所有可用的集群
    # 当新集群加入 Karmada 控制平面时，自动纳入部署范围
    # 复制模式：每个集群都会部署完整的 DaemonSet
    replicaScheduling:
      replicaSchedulingType: "Duplicated"
      # DaemonSet 本身就会在每个节点上运行，所以这里是复制模式确保每个集群都部署
  # 自动处理依赖资源
  propagateDeps: true
  # 冲突解决策略
  conflictResolution: "Overwrite"
```
