
# 多维多级网络拓扑调度
#### 背景信息
在大规模训练作业中，通常会将一个大作业切分成多个分片，例如模型并行的各分片、数据并行的副本组。相较于分片与分片之间，每个分片内部具有更强的网络通信性能诉求。
在分布式推理任务中，也可能存在不同角色的子任务，例如常见的Prefill角色和Decode角色。这些角色内部的任务之间存在频繁通信需求。
在大模型训练或分布式推理场景下，整个训练/推理任务需要消耗巨大的资源，这些资源通常无法在一个网络性能域（HyperNode）内满足。虽然整体任务的网络拓扑约束调度可以保障任务部署在指定的多个网络性能域内，但无法保证各个子任务能部署在同一网络性能域内，导致子任务可能跨网络性能域部署，显著影响通信效率。
为此，Volcano 在网络拓扑感知调度（Network Topology Aware Scheduling）策略基础上，提供了多维多级网络拓扑亲和调度能力。在调度时，Volcano会感知集群的网络拓扑结构，优先将定义的子任务整体调度至同一网络性能域内，在满足任务整体资源需求的同时，尽可能减少子任务内部的通信开销，有效解决大规模训练与分布式推理作业中的网络通信性能问题。
#### 功能介绍
Volcano提供了任务分组定义机制，并在任务网络拓扑约束的基础上，支持对不同分组配置独立的网络拓扑约束。
在开启网络拓扑感知调度后，调度器将遵循各个子任务的网络拓扑约束以及任务整体的网络拓扑约束，从而在满足整体作业网络通信性能需求的前提下，实现对各子任务的精细化拓扑亲和调度。
Volcano通过PodGroup资源对象提供了对任务内部Pod的分组定义能力。通过配置subGroupPolicy字段，可将一个PodGroup内的Pod划分为多个SubGroup。在subGroupPolicy中，每个SubGroup均可独立配置网络拓扑约束。在调度过程中，每个SubGroup将遵循其自身的网络拓扑约束。
任务负载可通过设置关联PodGroup的subGroupPolicy，利用Volcano实现多维多级网络拓扑亲和调度。Volcano Job和Kthena ModelServing等工作负载在定义中已内置对应的分组定义与网络拓扑约束配置，可自动创建和管理PodGroup，并在调度时遵循网络拓扑约束。
```
apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
metadata:
  name: pg-test1
  namespace: default
spec:
  networkTopology:                           # 配置podGroup网络拓扑约束
      mode: hard
      highestTierAllowed: 2
  subGroupPolicy:                          
  - name: subgroup-test              
    subGroupSize: 2                          # subGroup Pod数量 
    networkTopology:                         # 配置subGroup网络拓扑约束
      mode: hard
      highestTierAllowed: 1
    labelSelector:                           # 分组的Pod需要匹配的标签
       matchLabels:
          task-type: test  
    matchLabelKeys:                          # Pod的分组依据，value值相同的Pod分到同一个SubGroup中
    - group
```
#### 网络拓扑约束配置
在Volcano Job中，可通过配置networkTopology字段描述Job部署时的网络拓扑约束，确保Job实例被调度至满足条件的最优性能域内，显著提升计算效率与通信性能。具体约束配置如下。
| 字段                 | 说明                                                                                                                                                                                                                                                                                                                                                                  |
|:---|:---|
| mode               | 支持hard和soft两种模式： - hard：硬约束，Job内所有实例必须部署在同一个指定层级的HyperNode内。  - soft：软约束，Job内所有实例部署在同一个尽可能低层级的HyperNode内。   |
| highestTierAllowed | 与hard模式配合使用，表示Job最高允许部署到哪一层HyperNode（即最大tier值）。soft模式下无需配置此字段。 例如，配置参数值为2，则Job只能部署在tier ≤ 2的HyperNode内（如tier=1或tier=2），禁止跨tier=3或更高层级的HyperNode。 ``` spec: networkTopology: mode: hard highestTierAllowed: 2 ```                                                                |
| highestTierName    | 与hard模式配合使用，表示Job最高允许部署的HyperNode的名称，soft模式下无需配置该字段。                                                                                                                                                                                                                                                                                                                |
   
#### 前提条件
集群中已安装Volcano调度器插件，且插件版本在1.21.1及以上。
#### 约束与限制
- 网络拓扑感知调度暂不支持抢占。当资源紧张时，调度器不会主动抢占已分配给Pod的资源。
- HyperJob工作负载不支持网络拓扑感知调度。即使在HyperJob的JobTemplate中配置了networkTopology或分组亲和策略，这些配置将被忽略且不会生效。
- HyperNode自动发现功能不支持多种网络拓扑结构混部的场景（例如，A2与A3拓扑类型共存于同一集群）。
- 应尽量避免在运行中变更网络拓扑配置项，因为这可能导致集群内HyperNode结构重建，进而引发Volcano调度器进程的负载波动或调度异常。
- 若在调度过程中，集群网络拓扑结构或配置项发生变更，Volcano无法保证调度结果的正确性。
 
#### 开启网络拓扑
1. 登录[CCE控制台](https://console.huaweicloud.com/cce2.0/?#/cce/cluster/list)，单击集群名称进入集群。
2. 单击左侧导航栏的"配置中心"，切换至"调度配置"页面，选择Volcano调度器找到对应的"专家模式"，单击"开始使用"。 
   ![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002519785283.png "点击放大")
   
   
   
   
   
3. 进入CCE专家模式配置页面，在YAML配置文件中，开启network-topology-aware插件，以实现网络拓扑感知调度。 
   ```
   ...
   default_scheduler_conf:
     actions: allocate, backfill, preempt
     tiers:
     - plugins:
       - name: priority
       - enableJobStarving: false
         enablePreemptable: false
         name: gang
       - name: conformance
     - plugins:
       - enablePreemptable: false
         name: drf
       - name: predicates
       - name: nodeorder
     - plugins:
       - name: cce-gpu-topology-predicate
       - name: cce-gpu-topology-priority
       - name: xgpu
       - name: network-topology-aware # 开启网络拓扑感知调度插件
     - plugins:
       - name: nodelocalvolume
       - name: nodeemptydirvolume
       - name: nodeCSIscheduling
       - name: networkresource
   ...
   ```
   同时修改default_controller_conf配置，启用HyperNode自动发现功能。其配置参数，请根据实际需求调整。
   ```
   ...
   default_controller_conf:
     networkTopologyDiscovery:
       - source: label # HyperNode自动发现插件的名称，不可修改
         enabled: true # HyperNode自动发现插件开关，true表示开启，false表示关闭（原有的HyperNode实例不会删除）
         config:
           networkTopologyTypes:
             testtopology:                         # 网络拓扑层级关系的名称，最大限制20字符；当前仅支持配置一组
               - nodeLabel: test-tier-3            # 第3层网络拓扑对应的节点标签名，对应HyperNode tier=3
               - nodeLabel: test-tier-2            # 第2层网络拓扑对应的节点标签名，对应HyperNode tier=2
               - nodeLabel: test-tier-1            # 第1层网络拓扑对应的节点标签名，对应HyperNode tier=1
               - nodeLabel: kubernetes.io/hostname # 第0层网络拓扑对应的节点标签名，即节点层级，仅支持根据Node名匹配，不支持修改
   ```
   参数填写完成后，单击"保存"。
   
   
4. 完成上述配置后，单击右下角"确认配置"。在"确认配置"弹窗中，确认修改信息，无误后单击"保存"。
 
#### 部署负载实现多维多级网络拓扑亲和调度
使用多维多级网络拓扑亲和调度，需根据集群网络环境定义HyperNode用于描述网络拓扑。HyperNode的定义与生成请参见[网络拓扑感知调度概述](https://support.huaweicloud.com/usermanual-cce/cce_10_1126.html)。
以下示例采用两层网络拓扑结构。
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002532590774.png "点击放大")
#### 创建Volcano Job示例
Volcano Job通过partitionPolicy支持Job分组定义与partition层级的网络拓扑约束配置。可将Job内的Pod按照Pod标签划分为不同的Partition（如训练任务中的并行分片），并为每个Partition指定独立的网络拓扑约束。调度时，将确保属于同一Partition的Pod被调度至满足拓扑约束的同一网络性能域内。
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002532595066.png "点击放大")
例如，Job内task1有8个副本，通过partitionPolicy将其划分为两个Partition（分片），每个Partition包含4个Pod。
- 同一Partition内的Pod调度时只能部署在第1层HyperNode内。
- 同一Job内的Pod只能部署在第2层及以下的HyperNode内。
当1层HyperNode无法满足Job调度资源时，调度器可将不同Partition调度至同一个2层HyperNode下的不同的1层HyperNode，但同一Partition内的Pod必须部署在同一个1层HyperNode内。
```
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: sample
spec:
  schedulerName: volcano
  networkTopology:                # 可选字段，描述job级别的网络拓扑约束
    mode: hard                    # 可选字段，配置约束模式
    highestTierAllowed: 2         # 可选字段，表示Job最高允许部署到哪一层HyperNode
  tasks:
    - name: "task"
      replicas: 8                 # 必选字段，表示一个task内有多少pod
      partitionPolicy:            # 可选字段，表示对当前task内的所有pod进行分组
        totalPartitions: 2        # 必选字段，对task内的一组pod分为多少组
        partitionSize: 4          # 必选字段，每组中包含的pod数量（Gang调度条件），totalPartitions和partitionSize相乘的结果应与replicas相等， 
        networkTopology:          # 可选字段，描述每个分组的网络拓扑约束
          mode: hard              # 可选字段，配置分组亲和策略时
          highestTierAllowed: 1   # 可选字段，表示Partition最高允许部署到哪一层HyperNode
      template:
        spec:
          containers:
            - image: busybox
              command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
              imagePullPolicy: IfNotPresent
              name: sample-task
              resources:
                requests:
                  cpu: "1"
          restartPolicy: OnFailure
```
#### 创建Kthena ModelServing示例
在分布式推理负载中，存在Prefill与Decode两种角色。每个角色实例内的多个Pod存在频繁通信。为提升通信效率，应确保相同角色实例内的Pod部署在同一网络性能域内。Kthena提供的模型服务编排（ModelServing）支持定义推理负载在不同维度上的网络拓扑调度要求。系统会基于ModelServing自动创建并管理PodGroup，通过Volcano实现负载的多维多级网络拓扑亲和调度。
创建ModelServing时，仅需在rolePolicy和groupPolicy中指定networkTopology约束即可。ModelServing控制器会根据rolePolicy和groupPolicy中定义的networkTopology自动创建并管理PodGroup的网络拓扑约束配置。
![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/caution_3.0-zh-cn.png)
rolePolicy的HyperNode层级要求应不高于groupPolicy，否则会造成无法调度的情况。
```
apiVersion: workload.serving.volcano.sh/v1alpha1
kind: ModelServing
metadata:
  name: sample
  namespace: default
spec:
  schedulerName: volcano
  replicas: 1
  template:
    restartGracePeriodSeconds: 60
    networkTopology:
      rolePolicy:
        mode: hard              # 可选字段，配置Role网络拓扑约束模式
        highestTierAllowed: 1   # 可选字段，表示Role内Pods最高允许部署到哪一层HyperNode
      groupPolicy:
        mode: hard              # 可选字段，配置ServingGroup网络拓扑约束模式
        highestTierAllowed: 2   # 可选字段，表示ServingGroup内Pods最高允许部署到哪一层HyperNode
    roles:
      - name: prefill
        replicas: 1 
        entryTemplate:
          spec:
            containers:
              - name: leader
                image: busybox
                resources:
                  limits:
                    cpu: "0.5"
                  requests:
                    cpu: "0.5"
        workerReplicas: 3
        workerTemplate:
          spec:
            containers:
              - name: worker
                image: busybox
                resources:
                  limits:
                    cpu: "0.5"
                  requests:
                    cpu: "0.5"
      - name: decode
        replicas: 1  
        entryTemplate:
          spec:
            containers:
              - name: leader
                image: busybox
                resources:
                  limits:
                    cpu: "0.5"
                  requests:
                    cpu: "0.5"
        workerReplicas: 3
        workerTemplate:
          spec:
            containers:
              - name: worker
                image: busybox
                resources:
                  limits:
                    cpu: "0.5"
                  requests:
                    cpu: "0.5"
```
上述示例中，推理负载由1个Prefill实例和1个Decode实例组成一个ServingGroup。每个实例包含4个Pod（1个entry Pod + 3个worker Pod）。调度时Prefill/Decode实例内的Pod只能调度到同一个1层HyperNode的节点上，整个ServingGroup实例内的Pods可以部署在同一个2层HyperNode下的节点上。
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002563515641.png "点击放大")
