当前位置: 首页 > news >正文

Volcano 进阶实战 (二) - (网络拓扑/负载感知)调度

承接前文继续开始进阶调度策略:

Volcano 实战快速入门 (一)-CSDN博客文章浏览阅读868次,点赞18次,收藏18次。本文介绍了当前 Kubernetes 在大语言模型应用场景中的资源调度和管理面临的现状和挑战。简单介绍了 Volcano 的核心概念和组件功能。并提供了一些基础的任务示例 https://blog.csdn.net/weixin_39403185/article/details/147494858?spm=1011.2124.3001.6209

四、Volcano 进阶功能实战

        在AI大模型训练场景中,模型并行(Model Parallelism)将模型分割到多个节点上,训练过程中这些节点需要频繁进行大量数据交互。此时,节点间的网络传输性能往往成为训练的瓶颈,显著影响训练效率。数据中心的网络类型多样(如IB、RoCE、NVSwitch等),且网络拓扑复杂,通常包含多层交换机。两个节点间跨的交换机越少,通信延迟越低,吞吐量越高。因此,用户希望将工作负载调度到具有最高吞吐量和最低延迟的最佳性能域,尽可能减少跨交换机的通信,以加速数据交换,提升训练效率。

为此,Volcano提出了网络拓扑感知调度(Network Topology Aware Scheduling)策略,通过统一的网络拓扑API和智能调度策略,解决大规模数据中心AI训练任务的网络通信性能问题

4.1 网络拓扑感知调度

我绘制了一个简易的 IDC 网络拓扑示意图。可以看到实例计算通信速度

  • 本地是最快 -->

  • 次之 在同刀片机上 -->

  • 次之 在同机架上 -->

  • 次之 在同汇聚交换机 -->

  • 次之 在同 IDC 机房 -->

  • 次之 在同城不同IDC 机房 -->

  • 次之 在同国不同城不同IDC 机房 -->

  • 次之 跨国不同IDC 机房 (网络联通情况下最慢的网络拓扑)

在大模型训练中海量数据交换通信场景下,是非常需要能优化计算资源,计算任务的网络拓扑优化。

a) 资源准备

k8s / 1 master + 7worker

b) 构建HyperNode 拓扑

打标签标记 节点拓扑 模拟网络拓扑(标签在生产环境根据实际情况标记即可)

kubectl label node te1 volcano.sh/rack=s0-s1-rack-1 --overwrite
kubectl label node te2 volcano.sh/rack=s0-s1-rack-1 --overwrite
kubectl label node te3 volcano.sh/rack=s0-s1-rack-2 --overwrite
kubectl label node te4 volcano.sh/rack=s0-s1-rack-2 --overwrite
kubectl label node te5 volcano.sh/rack=s0-s2-rack-3 --overwrite
kubectl label node te6 volcano.sh/rack=s0-s2-rack-3 --overwrite
kubectl label node te7 volcano.sh/rack=s0-s2-rack-4 --overwrite 
kubectl label node te8 volcano.sh/rack=s0-s2-rack-4 --overwrite

构建 valcano 网络拓扑

cat <<EOF | kubectl apply -f -
apiVersion: topology.volcano.sh/v1alpha1
kind: HyperNode
metadata:name: s0-s1-rack-1
spec:tier: 1 members:- type: Nodeselector:exactMatch:name: "te1"- type: Nodeselector:exactMatch:name: "te2"
---
apiVersion: topology.volcano.sh/v1alpha1
kind: HyperNode
metadata:name: s0-s1-rack-2
spec:tier: 1 members:- type: Nodeselector:exactMatch:name: "te3"- type: Nodeselector:exactMatch:name: "te4"
---
apiVersion: topology.volcano.sh/v1alpha1
kind: HyperNode
metadata:name: s0-s2-rack-3
spec:tier: 1 members:- type: Nodeselector:exactMatch:name: "te5"- type: Nodeselector:exactMatch:name: "te6"
---
apiVersion: topology.volcano.sh/v1alpha1
kind: HyperNode
metadata:name: s0-s2-rack-4
spec:tier: 1members:- type: Nodeselector:exactMatch:name: "te7"- type: Nodeselector:exactMatch:name: "te8"
EOF
cat <<EOF | kubectl apply -f -
apiVersion: topology.volcano.sh/v1alpha1
kind: HyperNode
metadata:name: s0-s1
spec:tier: 2members:- type: HyperNodeselector:exactMatch:name: "s0-s1-rack-1"- type: HyperNodeselector:exactMatch:name: "s0-s1-rack-2"
---
apiVersion: topology.volcano.sh/v1alpha1
kind: HyperNode
metadata:name: s0-s2
spec:tier: 2members:- type: HyperNodeselector:exactMatch:name: "s0-s2-rack-3"- type: HyperNodeselector:exactMatch:name: "s0-s2-rack-4"
---
apiVersion: topology.volcano.sh/v1alpha1
kind: HyperNode
metadata:name: s0
spec:tier: 3members:- type: HyperNodeselector:exactMatch:name: "s0-s1"- type: HyperNodeselector:exactMatch:name: "s0-s2"
EOF

c) 调度测试部署 

## hard / soft
cat <<EOF | kubectl apply -f -
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:name: hello-volcano-job
spec:schedulerName: volcanominAvailable: 6queue: defaultnetworkTopology:mode: hard highestTierAllowed: 2tasks:- name: mytaskreplicas: 10template:spec:containers:- name: hello-containerimage: busyboxcommand: ["sh", "-c", "echo 'Hello Volcano!' && sleep 30"]imagePullPolicy: IfNotPresentresources:requests:cpu: "100m"memory: "256Mi"restartPolicy: Never
EOF

hard模式

highestTierAllowed: 2 严格在同一个网络拓扑节点上

soft模式

允许调度的就比较多了。看起来是比较零散的。可能还需要更多的精细调整。

4.2 负载感知调度

        集群中的调度是将pending状态的Pod分配到节点运行的过程,Pod的调度依赖于集群中的调度器。调度器是通过一系列算法计算出Pod运行的最佳节点,但是Kubernetes集群环境是存在动态变化的,例如某一个节点需要维护,这个节点上的所有Pod会被驱逐到其他节点,但是当维护完成后,之前被驱逐的Pod并不会自动回到该节点上来,因为Pod一旦被绑定了节点是不会触发重新调度的。由于这些变化,集群在一段时间之后就可能会出现不均衡的状态。

 a) 基础环境配置

## 安装 metrics-server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
#需要在环境变量中添加如下 配置去掉校验
#- --kubelet-insecure-tls## 安装 prometheus 相关组件
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo updatehelm upgrade --install prometheus prometheus-community/prometheus -n kube-system \
--set server.persistentVolume.enabled=false \
--set server.alertmanager.enabled=falsehelm install prometheus-adapter prometheus-community/prometheus-adapter -n kube-system##安装 valcano
kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml##安装 valcano-descheduler
kubectl apply -f https://raw.githubusercontent.com/volcano-sh/descheduler/refs/heads/main/installer/volcano-descheduler-development.yaml

metrics-server 安装成功后会看到如下:

安装 valcano和valcano-descheduler的运行情况

b) descheduler 调度配置

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:name: volcano-deschedulernamespace: volcano-system
data:policy.yaml: |apiVersion: "descheduler/v1alpha2"kind: "DeschedulerPolicy"profiles:- name: kube-systempluginConfig:- args:ignorePvcPods: truenodeFit: truepriorityThreshold:value: 10000name: DefaultEvictor- args:evictableNamespaces:exclude:- defaultmetrics:address: "http://prometheus-server.kube-system.svc.cluster.local:80"type: PrometheustargetThresholds:cpu: 80memory: 85thresholds:cpu: 30memory: 30name: LoadAwareplugins:balance:enabled:- LoadAware
EOF

priorityThreshol注意测试的 Job 的 Pod 优先级需要符合这个配置才能观测到重新调度现象,要不然直接就略过了

metrics我填的是 prometheus 的 service 的标准地址

          metrics:address: "http://prometheus-server.kube-system.svc.cluster.local:80"type: Prometheus

c) descheduler 源码修改适配

        查询语句 不兼容 需要 将 3s 修改成 3m 改大一些。这个没办法语句硬编码到源代码里面了。无法通过配置修改

## 查询语句 不兼容 需要 将 3s 修改成 3m 改大一些
avg_over_time((1 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle",instance="$replace_with_your_node_name"}[30s])) * 1))[2m:30s])

开始改代码重新打包:

 

## 制作镜像
cd descheduler
make image

## 重新标记 然后推到阿里云个人仓库
docker tag volcanosh/vc-descheduler:393a2d822ce3946642e76a0e1b27539012280e32 \
registry.ap-southeast-5.aliyuncs.com/xxxx/vc-descheduler:v1.0.0 
docker push registry.ap-southeast-5.aliyuncs.com/xxxx/vc-descheduler:v1.0.0 
## 然后需要将个人仓库公开

修改descheduler的 deployment 的镜像到阿里云私有仓库地址重启就完事了

查看日志可以观察到确实生效了 修改的代码

d) 开始测试

注意先修改一下descheduler deployment 的 --descheduling-interval=10m。

方便观测默认值是 10 分钟重新调度一次。可以改成 1 分钟检测一次。

创建自定义优先级资源对象。千万注意要和前文priorityThreshol这个相符合。满足条件才会触发重新调度

cat <<EOF | kubectl apply -f -
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:name: low-priority
value: 1000
globalDefault: false
description: "Low priority tasks"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:name: high-priority
value: 1000000
globalDefault: false
description: "High priority tasks, can preempt low priority"
EOF

创建低优先级Pod

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:name: low-priority-workloadannotations:volcano.sh/preemptable: "true"
spec:replicas: 3selector:matchLabels:app: low-priority-apptemplate:metadata:labels:app: low-priority-appspec:schedulerName: volcanopriorityClassName: low-prioritycontainers:- name: workload-containerimage: polinux/stresscommand: ["stress"]args:- "--cpu"- "1" - "--timeout"- "3600s"resources:requests:cpu: "300m"memory: "256Mi"limits:cpu: "500m"memory: "512Mi"
EOF

创建压测 Pod

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:name: stress-pod-on-te3
spec:nodeSelector:kubernetes.io/hostname: te3containers:- name: stress-containerimage: polinux/stresscommand: ["stress"]args: ["--cpu", "2", "--vm", "1", "--vm-bytes", "1G", "--timeout", "600s"]resources:requests: { cpu: "1500m", memory: "1Gi" }limits: { cpu: "2000m", memory: "1.5Gi" }
EOF

可以观察到压力 Pod 和普通 Pod 都在 te3 上了 

可以观察到压力 Pod开始发力,促使 te3 的负载非常高

e) 观测结果

valcano-descheduler的日志显示 已经触发驱逐了 平衡了。

观察 te3 上的普通 Pod 被重新调度到 te5 了

4.3 多集群调度

篇幅有限放到第三篇

4.4 离线混部调度

篇幅有限放到第三篇

4.5 MPI分布式训练

篇幅有限放到第三篇

参考:

网络拓扑感知调度 | Volcano背景 在AI大模型训练场景中,模型并行(Model Parallelism)将模型分割到多个节点上,训练过程中这些节点需要频繁进行大量数据交互。https://volcano.sh/zh/docs/network_topology_aware_scheduling/负载感知重调度 | Volcano背景 集群中的调度是将pending状态的Pod分配到节点运行的过程,Pod的调度依赖于集群中的调度器。调度器是通过一系列算法计算出Pod运行https://volcano.sh/zh/docs/descheduler/云原生混部 | Volcano背景 随着云原生技术的快速发展,越来越多的业务已逐渐迁移到Kubernetes,使用云原生化的方式进行开发维护,极大地简化了应用程序的部署、编https://volcano.sh/zh/docs/colocation/队列资源管理 | Volcano功能概述 队列是Volcano的核心概念之一,用于支持多租户场景下的资源分配与任务调度。通过队列,用户可以实现多租资源分配、任务优先级控制、资https://volcano.sh/zh/docs/queue_resource_management/多集群AI作业调度 | Volcano背景 随着企业业务的快速增长,单一Kubernetes集群往往无法满足大规模AI训练和推理任务的需求。用户通常需要管理多个Kuberneteshttps://volcano.sh/zh/docs/multi_cluster_scheduling/

相关文章:

  • 反爬加密字体替换机制解析
  • 人形机器人:开启AI与物理世界交互新时代
  • springboot应用使用shell脚本打包成部署压缩包(支持xjar)
  • spring响应式编程系列:异步生产数据
  • 计算机网络的五层结构(物理层、数据链路层、网络层、传输层、应用层)到底是什么?
  • 如何保证线程安全(含典型手段与应用场景)
  • 什么是智能导诊知识库?
  • 平面连杆机构(上)
  • H.264/AVC标准主流开源编解码器编译说明
  • 在分类任务中,显著性分析
  • 【课题推荐】基于场景的改进IMM算法
  • 在线录屏工具(压箱底)-免费高清
  • 为什么vllm能够加快大模型推理速度?
  • SM30 权限检查
  • 实验四 进程调度实验
  • 英语中的介词(preposition)
  • OSPF中DR/BDR的选举
  • 黑马Java基础笔记-4
  • Linux渗透测试
  • 7.Geometric Intersection: Interval
  • 人民日报:应对外贸行业风险挑战,稳企业就是稳就业
  • 2025年“畅游江淮 合肥等侬”文旅推介会在沪成功举办
  • 出国留学、来华留学呈现双增新趋势,“00后留学生个性鲜明”
  • 剪纸纹样“流动”在水乡,谁不忆江南
  • 一年吸引30多万人次打卡,江苏这个渔村是怎么做到的?
  • 乌克兰基辅遭大规模袭击,已致12人死亡