分组Pod故障迁移
功能介绍
在数据中心分布式AI训练/推理场景下,作业实例具有强协同依赖性、长时间运行性和资源独占性(如NPU、GPU)等特点,而数据中心很有可能出现节点宕机、网络分区等故障。当集群出现故障并直接影响某些Pod运行时,重启整个作业是代价高昂的,有可能导致整个作业一直处于运行、失败、重启的循环中,永远无法顺利完成;而只迁移这些受直接影响的Pod,虽然代价较小,但却有可能导致这些Pod与同组内的其他Pod割裂,出现运行信息过时、拓扑约束失效等情况,致使整个分组处于占用资源、但未正常运行的状态,造成集群资源浪费。
为此,Volcano进一步提出了故障场景下支持分组Pod迁移的能力,即当检测到集群出现故障导致某些Pod被驱逐或失活时,主动迁移整个分组的Pod到别的适合的节点上,以加快作业恢复速度,避免浪费集群资源。
以下图场景为例,在由8个空闲节点、4个一层HyperNode、2个二层HyperNode和1个三层HyperNode组成的集群中,运行着一个Volcano Job。该Job包含两个分组,每个分组都被约束调度到同一个一层HyperNode下,其中分组1由Pod0和Pod1组成,运行在节点node0和node1上;分组2有Pod2和Pod3组成,运行在节点node2和node3上。此时,node3节点失效,导致其上的Pod3失活。
- 若不支持分组Pod迁移能力,则新建的Pod3将因为不存在满足网络拓扑约束的节点而一直处于Pending状态,导致Pod2占用node2节点资源,但却不能正常运行,造成集群资源浪费。或者,用户需重启整个Job,导致Pod0和Pod1也需要重新运行,作业恢复成本较大。
- 若支持分组Pod迁移能力,则可主动中止同一分组内的Pod2,并将新创建的Pod2和Pod3统一调度到HyperNode3下,即节点node6和node7上,从而使整个作业高效恢复运行。
为此,Volcano Job在作业生命周期管理策略中提供了RestartPartition动作,允许在发生特定事件时重启或迁移整个分组。例如,在Job中添加如下配置,表示在发生Pod驱逐、Pod失败时重启、迁移该Pod所在的整个分组。
spec:
policies:
- action: RestartPartition
event: PodEvicted
- action: RestartPartition
event: PodFailed 前提条件
集群中已安装Volcano调度器插件,且插件版本在1.21.1及以上。
约束与限制
- 网络拓扑感知调度暂不支持抢占。当资源紧张时,调度器不会主动抢占已分配给Pod的资源。
- 若配置了分组亲和策略,则不支持soft模式的网络拓扑约束。
- HyperJob工作负载不支持网络拓扑感知调度。即使在HyperJob的JobTemplate中配置了networkTopology或分组亲和策略,这些配置将被忽略且不会生效。
- HyperNode自动发现功能不支持多种网络拓扑结构混部的场景(例如,A2与A3拓扑类型共存于同一集群)。
- 应尽量避免在运行中变更网络拓扑配置项,因为这可能导致集群内HyperNode结构重建,进而引发Volcano调度器进程的负载波动或调度异常。
- 若在调度过程中,集群网络拓扑结构或配置项发生变更,Volcano无法保证调度结果的正确性。
使用示例
- 登录CCE控制台,单击集群名称进入集群。
- 单击左侧导航栏的“配置中心”,切换至“调度配置”页面,选择Volcano调度器找到对应的“专家模式”,单击“开始使用”。

- 进入CCE专家模式配置页面,在YAML配置文件中,修改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名匹配,不支持修改 ... - 以下图中的多级网络拓扑结构为例,创建8个节点,并执行如下命令,为它们添加如下网络拓扑标签。
本示例仅用于演示,实际创建的HyperNode应依据集群的真实拓扑。此外,对于没有网络拓扑关系的普通节点,不应添加与网络拓扑相关的节点标签,否则可能导致创建的HyperNode不符合预期。
kubectl label node 192.168.5.17 test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode0 # node0 kubectl label node 192.168.5.224 test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode0 # node1 kubectl label node 192.168.5.235 test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode1 # node2 kubectl label node 192.168.5.239 test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode1 # node3 kubectl label node 192.168.5.240 test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode2 # node4 kubectl label node 192.168.5.251 test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode2 # node5 kubectl label node 192.168.5.83 test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode3 # node6 kubectl label node 192.168.5.95 test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode3 # node7
表1 节点、IP与多级HyperNode归属映射表 节点名
IP地址
标签(Labels)
node0
192.168.5.17
test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode0
node1
192.168.5.224
test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode0
node2
192.168.5.235
test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode1
node3
192.168.5.239
test-tier-3=HyperNode6 test-tier-2=HyperNode4 test-tier-1=HyperNode1
node4
192.168.5.240
test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode2
node5
192.168.5.251
test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode2
node6
192.168.5.83
test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode3
node7
192.168.5.95
test-tier-3=HyperNode6 test-tier-2=HyperNode5 test-tier-1=HyperNode3
- 执行以下命令,查询Volcano自动发现的HyperNode。
kubectl get hypernodes
返回信息如下所示。
NAME TIER TIERNAME NODECOUNT AGE hypernode-testtopology-tier1-2**** 1 test-tier-1 2 8s hypernode-testtopology-tier1-4**** 1 test-tier-1 2 8s hypernode-testtopology-tier1-j**** 1 test-tier-1 2 8s hypernode-testtopology-tier1-l**** 1 test-tier-1 2 8s hypernode-testtopology-tier2-m**** 2 test-tier-2 2 8s hypernode-testtopology-tier2-n**** 2 test-tier-2 2 8s hypernode-testtopology-tier3-c**** 3 test-tier-3 2 8s
- 创建一个Volcano Job工作负载,包含4个Pod,每个Pod独占一个节点的所有NPU资源,并配置分组策略将这4个Pod均分为2组,每个分组最高亲和到tier=1的HyperNode上。此外,配置事件为PodEvicted、动作为RestartPartition的生命周期管理策略,已启用分组Pod故障迁移能力。示例如下所示。
apiVersion: batch.volcano.sh/v1alpha1 kind: Job metadata: name: network-topology-job namespace: default spec: schedulerName: volcano policies: - action: RestartPartition # 发生PodEvicted事件时,重启该pod所在的整个分组pod event: PodEvicted minAvailable: 4 # gang调度条件,需要满足至少4个pod可调度成功 tasks: - replicas: 4 # 一共4个实例 name: t0 partitionPolicy: # 配置分组亲和调度策略 totalPartitions: 2 # 将当前task内的pod分为2组 partitionSize: 2 # 每个分组包含2个pod networkTopology: # 配置分组级网络拓扑约束 mode: hard # 该网络拓扑约束为硬约束,必须满足 highestTierAllowed: 1 # 最高亲和到tier=1的HyperNode template: spec: containers: - name: container1 image: nginx:latest resources: requests: huawei.com/ascend-1980: 16 # 每个pod独占一个节点的NPU资源 limits: huawei.com/ascend-1980: 16 - 执行以下命令,查看调度结果。此时,第一组Pod已被调度至HyperNode0的node0和node1上,第二组Pod已被调度至HyperNode1的node2和node3上。
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.1.36 192.168.5.17 <none> <none> network-topology-job-t0-1 1/1 Running 0 6s 172.19.2.143 192.168.5.224 <none> <none> network-topology-job-t0-2 1/1 Running 0 6s 172.19.3.19 192.168.5.239 <none> <none> network-topology-job-t0-3 1/1 Running 0 6s 172.19.1.162 192.168.5.235 <none> <none>
- 执行以下命令,驱逐node3节点上的Pod,模拟节点故障场景。
kubectl drain 192.168.5.239 --ignore-daemonsets
- 重新检查调度结果。此时,第二个分组的两个Pod已被调度到HyperNode3的node6和node7上,保持了与分组内其他Pod的网络拓扑一致性。
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 2m51s 172.19.1.29 192.168.5.17 <none> <none> network-topology-job-t0-1 1/1 Running 0 2m51s 172.19.2.136 192.168.5.224 <none> <none> network-topology-job-t0-2 1/1 Running 0 80s 172.19.3.143 192.168.5.95 <none> <none> network-topology-job-t0-3 1/1 Running 0 82s 172.19.4.12 192.168.5.83 <none> <none>
- 执行以下命令,恢复node3节点。
kubectl uncordon 192.168.5.239