第 7 篇|Volcano Gang 调度:成组分配与绑定

第 7 篇|Volcano Gang 调度:成组分配与绑定

💡 原文中文,约6800字,阅读约需17分钟。
📝

内容提要

本文解析 Volcano 调度器如何满足 Gang 约束:调度从缓存快照开启 Session,依次执行 enqueue、allocate 等阶段。enqueue 判断作业能否进入调度,allocate 用 Statement 试分配资源,若成员未达最低数则 Discard 撤销。满足门槛后 Commit 并异步绑定,但绑定可能部分失败,Gang 不保证全部 Pod 同时启动。

🔎

延伸解读

Gang 约束的边界:最低成员数而非全部 Pod

文章指出,Gang 检查的范围由最低成员数决定。如果最低成员数小于总副本数,达到门槛后可以先提交满足要求的部分,剩余成员继续参与后续分配。因此不能将 Gang 约束理解为“整个作业的全部 Pod 必须一次性同时运行”。这一设计允许作业在部分成员就绪时启动,但读者需注意,未达到最低成员数时,已试分配的资源会被撤销。

试分配与提交:内存状态与 API 绑定的分离

allocate 阶段通过 Statement 在 Session 内试分配资源,此时仅调整内存状态和节点账目,并未绑定到 Kubernetes。只有满足 JobReady 后才会 Commit,将分配送入缓存并异步绑定。这种分离意味着调度器可以在不实际占用资源的情况下评估可行性,但提交后的绑定仍可能失败,因为节点状态可能已变化。

绑定异步执行:部分成功与失败处理

Commit 后,绑定通过 BindFlowChannel 异步执行,每个成员的绑定结果独立记录。文章强调,绑定可能部分成功、部分失败,且没有事务保证全部回滚。失败成员会触发 resyncTask 重新同步,而成功绑定的成员不会自动回退。因此,Gang 约束只能避免提交前明显不足的分配,不能保证所有 Pod 同时启动或全部绑定成功。

排查调度问题:分阶段观察状态

文章建议排查时分别观察 PodGroup 是否准入、成员是否找到节点、绑定有无错误、容器是否启动以及 RayCluster 是否就绪。仅看到 PodGroup 阶段变化不足以说明程序已开始执行。这种分阶段视角有助于定位问题发生在调度、绑定还是容器启动阶段,避免将调度成功等同于应用就绪。

Q&A

Volcano 调度器的一轮调度是如何开始的?

调度器通过 informer 维护长期 SchedulerCache,周期性 runOnce 打开一轮 Session。Session 从 cache.Snapshot() 获取缓存快照作为工作视图,在锁保护下复制节点等对象,避免直接改动长期状态。随后依次执行配置中的 action,如 enqueue、allocate、backfill。

Volcano 默认配置包含哪些 action 和插件?

默认配置在 pkg/scheduler/util.go 的 DefaultSchedulerConf 中定义,actions 为 enqueue、allocate、backfill。插件按 tiers 组织,第一层包括 priority、gang、conformance,第二层包括 overcommit、drf、predicates、proportion、nodeorder。该配置没有 preempt 和 reclaim。

enqueue 阶段如何判断作业能否进入调度?

enqueue 检查作业的 PodGroup.Spec.MinResources。如果为 nil,则直接通过;否则调用 JobEnqueueable,由 overcommit 和 proportion 等插件根据集群资源、已准入需求和 Queue 状态判断是否准入。通过后 PodGroup 阶段变为 Inqueue,作业加入 Session。

allocate 阶段如何通过 Statement 试分配资源并满足 Gang 约束?

allocate 使用 Statement 记录试分配操作,调整 Session 中成员状态和节点资源账目。如果所有成员都能找到合法节点,则 JobReady 为 true,执行 stmt.Commit() 提交;如果某个成员找不到位置,则执行 stmt.Discard() 撤销所有试分配,恢复内存状态。

Volcano 的 Gang 约束能保证所有 Pod 同时启动吗?

不能。Gang 约束在提交前避免明显不足的分配,但 Commit 后绑定是异步的,可能部分成功部分失败。失败成员会记录错误并重新同步,已成功的成员不会自动回滚。因此 Gang 不保证所有 Pod 同时启动,也不保证绑定全部成功。

Volcano 中 JobReady 的判断标准是什么?

JobReady 由 gang 插件注册的回调判断,要求 CheckTaskReady、CheckSubJobReady 和 IsReady 均为 true。IsReady 会统计 Allocated、Binding、Bound、Running、Succeeded 等内部状态的成员数,并考虑 Pending 的 BestEffort 成员。它不等于 Kubernetes Pod 的 Ready 条件。

🏷️

标签

➡️

继续阅读