
# 多级网络拓扑调度
#### 功能介绍
目前，分布式AI训练/推理任务正逐渐成为算力基础设施的核心工作负载，但由于高度依赖各子任务间的数据交换，面临着网络传输性能的瓶颈，导致计算效率难以显著提升。这一问题的主要原因在于数据中心网络拓扑的复杂性，通常由多层交换机构成的层级架构组成，且类型多样，包括IB、RoCE、NVSwitch等。跨层级交换机的通信路径越长，延迟越高，吞吐量越低，效率随之下降；反之，通信性能更优。因此，将高度相关的工作负载调度至同一高性能域，可以有效减少跨交换机的通信成本，加快节点间的数据交换，从而显著提高分布式训练/推理任务的整体效率。
为此，Volcano首先定义了一种新的CRD，即HyperNode，用于统一描述集群的多层级网络拓扑结构，屏蔽网络类型差异。如下图所示，每个HyperNode代表一个网络拓扑性能域，通常可以映射到一个交换机或ToR；多个HyperNode可以通过层级连接，形成多级树状结构，从而精准表达真实数据中心的复杂网络拓扑结构。
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002563376171.png "点击放大")
在这种结构中，节点间的通信效率取决于它们之间的HyperNode层级跨度。例如：
- node0和node1属于HyperNode0（tier 1），通信效率最高。
- node0和node2属于HyperNode4（tier 2），通信效率较低。
- node0和node4属于HyperNode6（tier 3），通信效率最差。
与传统的通过节点标签（label）表示网络拓扑的方式相比，HyperNode具有以下优势：
- 语义统一：通过标准化的结构化定义，消除了手动标签方式中可能存在的语义不一致问题。
- 层级结构：支持树状层级结构，能够精确映射物理网络拓扑关系，适应多层交换结构。
- 易于管理：支持手动创建或通过自动拓扑发现机制动态维护，实现资源状态的自动化同步与管理。
为了进一步减轻网络拓扑信息的管理负担，Volcano提供了HyperNode自动发现功能。该功能能够自动检测集群内部的网络拓扑结构，并根据检测结果自动创建、更新或删除相应的HyperNode自定义资源（CRs），从而减少网络拓扑信息的管理负担。自动发现功能具备以下核心优势：
- 自动化管理：自动从节点网络拓扑信息标签（labels）中发现和维护HyperNode信息，无需手动操作。
- 实时同步：实时同步网络拓扑的变化（如节点网络拓扑信息标签的更改），确保HyperNode信息与实际网络状态的一致性。
通过这一自动化发现机制，您可以专注于作业调度的配置，无需担忧HyperNode的创建和维护复杂性，显著简化了网络拓扑感知调度的部署和管理。
#### 网络拓扑约束配置
在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配置文件中，修改default_controller_conf配置为如下内容，以启用HyperNode自动发现功能。其中配置参数，请根据实际需求调整。 
   ```
   ...
   default_controller_conf:
     networkTopologyDiscovery:
       - source: label # HyperNode 自动发现插件名称，不可修改
         enabled: true # 开关：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 名匹配，不支持修改
   ...
   ```
   同时，在default_scheduler_conf配置中添加名为network-topology-aware的插件，如下所示。其配置参数，请根据实际需求调整。
   ```
   ...
   default_scheduler_conf:
     actions: allocate, backfill, preempt
     configurations: ''
     metrics:
       interval: 30s
       type: ''
     tiers:
       - plugins:
           - name: priority
           - enableJobStarving: false
             enablePreemptable: false
             enableReclaimable: false
             name: gang
           - name: conformance
           - enableHierarchy: true
             name: capacity
       - plugins:
           - enablePreemptable: false
             enableReclaimable: false
             name: drf
           - name: predicates
           - name: nodeorder
       - plugins:
           - name: cce-gpu-topology-predicate
           - name: cce-gpu-topology-priority
           - name: xgpu
           - name: network-topology-aware # 添加本行内容，以启用网络拓扑感知调度
             arguments:
               weight: 10                       # 本插件整体策略权重，可不填，默认为1
               hypernode.binpack.cpu: 5         # CPU资源HyperNode级装箱权重，可不填，默认为1
               hypernode.binpack.memory: 5      # 内存资源HyperNode级装箱权重，可不填，默认为1
               hypernode.binpack.resources: nvidia.com/gpu, huawei.com/ascend-1980      # 装箱策略需要考虑的自定义资源名，可不填，默认为无
               hypernode.binpack.resources.nvidia.com/gpu: 10                           # 自定义资源“nvidia.com/gpu”的HyperNode级装箱权重，可不填，默认为1
               hypernode.binpack.resources.huawei.com/ascend-1980: 10                   # 自定义资源“huawei.com/ascend-1980”的HyperNode级装箱权重，可不填，默认为1
               hypernode.binpack.normal-pod.enable: true      # 针对无网络拓扑约束Pod的多层级HyperNode装箱调度能力开关，可不填，默认为true
               hypernode.binpack.normal-pod.fading: 0.8       # 无网络拓扑约束Pod在计算各层级HyperNode装箱分数时，第tier层的权重为math.Pow(fading, tier-1)，可不填，默认为0.8
       - plugins:
           - name: nodelocalvolume
           - name: nodeemptydirvolume
           - name: nodeCSIscheduling
           - name: networkresource
   ...
   ```
   
   
4. 以下图中的多级网络拓扑结构为例，创建8个节点，并执行如下命令，为它们添加如下网络拓扑标签。 
   ![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000002532537810.png "点击放大")
   表1节点、IP与多级HyperNode归属映射表 
   | 节点名   | IP地址          | 标签（Labels）                                     |
   |:---|:---|:---|
   | node0 | 192.168.5.17  | test-tier-2=HyperNode2, test-tier-1=HyperNode0 |
   | node1 | 192.168.5.224 | test-tier-2=HyperNode2, test-tier-1=HyperNode0 |
   | node2 | 192.168.5.235 | test-tier-2=HyperNode2, test-tier-1=HyperNode0 |
   | node3 | 192.168.5.239 | test-tier-2=HyperNode2, test-tier-1=HyperNode0 |
   | node4 | 192.168.5.240 | test-tier-2=HyperNode2, test-tier-1=HyperNode1 |
   | node5 | 192.168.5.251 | test-tier-2=HyperNode2, test-tier-1=HyperNode1 |
   | node6 | 192.168.5.83  | test-tier-2=HyperNode2, test-tier-1=HyperNode1 |
   | node7 | 192.168.5.95  | test-tier-2=HyperNode2, test-tier-1=HyperNode1 |
      
   本示例仅用于演示，实际创建的HyperNode应依据集群的真实拓扑。此外，对于没有网络拓扑关系的普通节点，不应添加与网络拓扑相关的节点标签，否则可能导致创建的HyperNode不符合预期。
   ```
   kubectl label node 192.168.5.17  test-tier-2=HyperNode2 test-tier-1=HyperNode0 # node0
   kubectl label node 192.168.5.224 test-tier-2=HyperNode2 test-tier-1=HyperNode0 # node1
   kubectl label node 192.168.5.235 test-tier-2=HyperNode2 test-tier-1=HyperNode0 # node2
   kubectl label node 192.168.5.239 test-tier-2=HyperNode2 test-tier-1=HyperNode0 # node3
   kubectl label node 192.168.5.240 test-tier-2=HyperNode2 test-tier-1=HyperNode1 # node4
   kubectl label node 192.168.5.251 test-tier-2=HyperNode2 test-tier-1=HyperNode1 # node5
   kubectl label node 192.168.5.83  test-tier-2=HyperNode2 test-tier-1=HyperNode1 # node6
   kubectl label node 192.168.5.95  test-tier-2=HyperNode2 test-tier-1=HyperNode1 # node7
   ```
   
   
5. 执行以下命令，查询Volcano自动发现的HyperNode。 
   ```
   kubectl get hypernodes
   ```
   返回信息如下所示。
   ```
   NAME                                      TIER   TIERNAME      NODECOUNT   AGE
   hypernode-testtopology-tier1-8****   1      test-tier-1   4           6s
   hypernode-testtopology-tier1-l****   1      test-tier-1   4           6s
   hypernode-testtopology-tier2-v****   2      test-tier-2   2           6s
   ```
   
   
6. 创建一个Volcano Job工作负载，包含8个Pod，每个Pod独占一个节点的NPU资源，要求至少调度4个Pod，并且这些Pod必须位于同一个一层HyperNode下。示例如下所示。 
   ```
   apiVersion: batch.volcano.sh/v1alpha1
   kind: Job
   metadata:
     name: network-topology-job
     namespace: default
   spec:
     schedulerName: volcano
     minAvailable: 4         # Gang调度条件，需要满足至少4个Pod可调度成功
     networkTopology:        # 配置网络拓扑约束
       mode: hard
       highestTierAllowed: 1 # 最高亲和到tier=1的HyperNode
     tasks:
       - replicas: 8 # 一共8个实例
         name: t0
         template:
           spec:
             containers:
               - name: container1
                 image: nginx:latest
                 resources:
                   requests:
                     huawei.com/ascend-1980: 16 # 每个实例独占一个节点的NPU资源
                   limits:
                     huawei.com/ascend-1980: 16
   ```
   
   
7. 检查调度结果。在本例中，4个Pod被调度至HyperNode1上，状态为Running；另外4个Pod因无法找到满足网络拓扑约束的节点，状态为Pending。 
   ```
   kubectl get pod -o wide
   ```
   返回信息如下所示。
   ```
   NAME                        READY   STATUS    RESTARTS   AGE   IP             NODE            NOMINATED NODE   READINESS GATES
   network-topology-job-t0-0   1/1     Running   0          6s    172.19.3.3     192.168.5.239   <none>           <none>
   network-topology-job-t0-1   1/1     Running   0          6s    172.19.2.131   192.168.5.224   <none>           <none>
   network-topology-job-t0-2   1/1     Running   0          6s    172.19.1.142   192.168.5.235   <none>           <none>
   network-topology-job-t0-3   1/1     Running   0          6s    172.19.1.24    192.168.5.17    <none>           <none>
   network-topology-job-t0-4   0/1     Pending   0          6s    <none>         <none>          <none>           <none>
   network-topology-job-t0-5   0/1     Pending   0          6s    <none>         <none>          <none>           <none>
   network-topology-job-t0-6   0/1     Pending   0          6s    <none>         <none>          <none>           <none>
   network-topology-job-t0-7   0/1     Pending   0          6s    <none>         <none>          <none>           <none>
   ```
   
   
 
