
Volcano 多调度器部署实战用 scheduler-name 与 node-selector 将集群切分为独立调度域【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano在单一大规模集群中训练、推理、系统服务等不同工作负载往往需要互不干扰地运行。本文围绕 Volcano 的多调度器Multi Volcano Schedulers设计讲解如何通过--scheduler-name与--node-selector两个启动参数把同一个集群切分为多个相互隔离、又各自具备完整调度能力的调度域。读完本文你将能够部署多套 vc-scheduler 实例、让 controller-manager 同时管理多个调度器、并让 Job 与普通 Deployment 精确落到指定的调度器与节点分组上。一、背景与动机为什么要拆出多个调度器当集群服务于多种用途时常希望把集群划分成多个区段section分别承载不同性质的负载。Volcano 的多调度器方案正是为这一场景设计的部署多套 vc-scheduler 实例每套实例通过node-selector只看见一部分节点从而实现按节点分组的隔离调度。原始设计文档 multi-volcano-schedulers.md 列出了该方案的四个核心优势分区隔离Each section can keep isolated不同区段的调度器只处理各自节点范围内的资源负载之间互不感知、互不抢占完整调度能力Each section include full scheduling capability每个调度器实例都是完整的 vc-scheduler拥有队列、Job 全量调度、插件等能力而不是一个调度器 一个过滤器支持用户独占节点Support user monopolizing some nodes将某批节点划给某个调度器后该调度器负责的负载只会在这些节点上运行天然形成节点独占系统服务定点部署System services can be scheduled in specific nodes系统组件类负载Deployment 等也可以指定到特定调度器被固定调度到指定节点分组。二、部署步骤一为每个调度器指定名字与节点选择器多调度器部署的第一步是给每个 vc-scheduler 实例起一个唯一名字并通过selector过滤它负责的节点。selector是一个 label query值中支持冒号写法例如--node-selector key1:value1,key2:value2。对调度器的 Deployment 做如下修改diff 形式# Scheduler deployment ... spec: containers: - args: - --logtostderr - --scheduler-conf/volcano.scheduler/volcano-scheduler.conf - --scheduler-namegpu - --node-selectorzone:gpu - -v3 - 21这两个参数在 scheduler 选项定义 中均有明确说明--scheduler-name字符串数组参数默认值为volcano见 defaultSchedulerName 常量。其帮助文本写得很直白vc-scheduler will handle pods whose .spec.SchedulerName is same as scheduler-name即调度器只会接管spec.schedulerName与自身名字匹配的 Pod--node-selector字符串切片参数帮助文本给出了与文档一致的用法示例volcano only work with the labeled node, like: --node-selectorvolcano.sh/role:train --node-selectorvolcano.sh/role:serving。可以看到它支持重复传参或逗号分隔的key:value形式。三、部署步骤二controller-manager 声明多个 scheduler-nameVolcano 的 controller-manager 负责维护 Job/PodGroup 等对象它必须知道自己管辖哪些调度器因此需要把集群中所有 vc-scheduler 的名字都声明出来# Controller deployment ... spec: containers: - args: - --logtostderr - --scheduler-namevolcano - --scheduler-namegpu - -v4 - 21对应实现在 controller-manager 选项定义--scheduler-name同样是字符串数组StringArrayVar默认值为volcano帮助文本为 Volcano will handle pods whose .spec.SchedulerName is same as scheduler-name。由于 controller 与调度器使用的是同一个参数名但语义分别是我管理的调度器名单与我是谁两边必须保持名字一致否则 Job 的 PodGroup 状态将无法被正确维护。四、部署步骤三为 Job 指定调度器Job 要落到哪个调度域取决于spec.schedulerName字段。以原始文档中的 GPU 作业示例为准apiVersion: batch.volcano.sh/v1alpha1 kind: Job metadata: name: run-gpu spec: minAvailable: 3 schedulerName: gpu # need to specify scheduler name tasks: - replicas: 3 name: worker template: metadata: name: worker spec: containers: - image: tensorflow/tensorflow:latest-gpu name: tensorflow resources: requests: cpu: 1 memory: 10Gi nvidia.com/gpu: 2指定schedulerName: gpu后controller 会为其创建同名的 PodGroupvc-scheduler名字为 gpu 的那套在缓存中识别到这些 Pod 的spec.schedulerName与自身匹配后才会接管调度且只会把 Pod 安排进通过node-selectorzone:gpu过滤后的节点集合。五、部署步骤四把系统服务Deployment也交给指定调度器除 Volcano Job 外普通 Kubernetes 工作负载同样可以指定调度器。文档给出了一份用 Deployment 部署系统服务的示例把schedulerName改为目标调度器即可apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: schedulerName: volcano containers: - name: nginx image: nginx这就是文档所述System services can be scheduled in specific nodes的落地方式为系统服务单独命名一套调度器并用node-selector锁定节点分组再把系统服务的schedulerName指向它即可实现系统负载定点部署、与业务负载隔离。六、源码级原理解析调度器如何按名字与标签过滤上面四个配置为什么能生效可以从调度器缓存的两个关键路径印证。Pod 侧按 schedulerName 过滤。在 事件处理器 中getOrCreateJob会在 Pod 尚无 Job 归属时检查if !slices.Contains(sc.schedulerNames, pi.Pod.Spec.SchedulerName) { klog.V(4).Infof(Pod %s/%s is not scheduled by %s, skip creating PodGroup and Job for it in cache., ...) } return nil即 Pod 的spec.schedulerName不在本实例--scheduler-name声明的名字列表中时直接被跳过、不进入调度缓存。这意味着两套调度器即使同时 watch 全集群的 Pod也只会各自处理自己署名的那部分互不干扰。节点侧按 node-selector 标签过滤。在 nodeCanAddCache 中func (sc *SchedulerCache) nodeCanAddCache(node *v1.Node) bool { if !responsibleForNode(node.Name, sc.schedulerPodName, sc.c) { return false } if len(sc.nodeSelectorLabels) 0 { return true } for labelName, labelValue : range node.Labels { key : labelName : labelValue if _, ok : sc.nodeSelectorLabels[key]; ok { return true } } klog.Infof(node %s ignore add/update/delete into schedulerCache, node.Name) return false }从源码结构看node-selector被解析成key:value形式的标签集合nodeSelectorLabels节点只有携带其中任一key:value标签才会被加入缓存没有配置node-selector时集合为空所有节点都可见。这与文档中selector(label query) supports :的说明完全对应也解释了为什么文档示例用zone:gpu这种带冒号的写法。两个过滤叠加起来就构成了完整的隔离模型schedulerName 决定哪些负载归我node-selector 决定哪些节点归我。每个实例都在各自节点子集上拥有完整调度能力分区之间天然隔离。七、配置要点小结与适用前提组件关键参数默认值说明vc-scheduler--scheduler-namevolcano本实例接管spec.schedulerName与该名一致的 Pod多实例部署时各实例必须使用不同名字vc-scheduler--node-selector无全部节点可见key:value形式的标签过滤支持逗号分隔或重复传参如zone:gpuvolcano-controllers--scheduler-namevolcano字符串数组需列出集群中全部调度器名字Job / Deploymentspec.schedulerNamedefault-scheduler工作负载的署名字段决定其被哪套调度器接管使用多调度器方案时的适用前提与注意点集群中每个 vc-scheduler 实例的--scheduler-name必须互不相同且这些名字都要出现在 controller-manager 的--scheduler-name列表中否则对应调度域内的 Job 无法被正确维护节点需要预先打上node-selector使用的标签如zonegpu否则该调度器实例的缓存中不会有任何节点从源码结构看未配置node-selector的调度器实例会看到全部节点因此独占语义依赖显式的标签划分划分节点时建议各分区标签互斥避免两个调度器同时看见同一批节点该方案与 Volcano 自身的 sharding 模式--scheduler-sharding-mode是两套不同的节点划分机制前者面向多实例多用途分区选型时应先明确目标是逻辑分片还是物理分区。更多 Job 写法可参考仓库中的示例定义 example/job.yaml此外设计文档目录中还有 docs/design/deploy-multi-volcano-schedulers-without-using-selector.md从文件名推断其讨论的是不使用 node-selector 的多调度器部署方式可与本文方案对照阅读。【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考