尧图精选

Volcano 队列资源预留设计详解:Guarantee 字段、预留节点评分算法与 Capacity 插件落地

🕒 发布时间:2026/9/17 21:10:35 📁 来源:尧图网络
Volcano 队列资源预留设计详解Guarantee 字段、预留节点评分算法与 Capacity 插件落地【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano本篇围绕 Volcano 的设计文档 queue-resource-reservation-design.md 展开讲解为指定队列预留集群资源这一特性从动机、API 字段设计、预留节点选择算法含完整评分公式到控制器与调度插件实现的完整脉络。读完后你将掌握如何在 Queue CR 中通过guarantee字段声明队列的保底资源、预留节点选择算法的四个加权维度及其归一化公式、预留状态锁定节点与空闲资源如何写回status.reservation以及当前仓库中 Capacity 插件是如何消费 guarantee 资源并在回收reclaim时提供保护的具体源码依据。1. 背景与动机为什么需要队列级资源预留该设计源于 Volcano 上游 issue 1101 提出的诉求Volcano 应当支持为指定队列预留资源resource reservation for specified queue。设计文档 docs/design/queue-resource-reservation-design.md 明确了四条初始需求支持为指定队列预留指定资源只考虑非抢占式non-preemption预留——预留过程不驱逐正在运行的工作负载支持在不重启 Volcano的前提下对指定队列动态开启和关闭资源预留即通过更新 Queue CR 的 spec 即可生效同时支持两种声明方式固定资源量hard reservation如cpu: 2、memory: 4G与集群资源百分比percentage。这类需求在多租户共享集群中非常典型某个租户/队列希望保证自己的作业随时有资源可用而不是与其他队列完全按公平共享的比例竞争。2. 设计考量预留请求的约束条件设计文档的 Consideration 章节对预留请求给出了明确的合法性约束这些约束是理解后续 API 校验逻辑的基础预留请求在所有资源维度上都不能超过集群总资源量如果队列设置了capability队列容量上限则预留请求在各维度上必须不超过capability实际锁定的预留资源量必须不小于请求量各维度但也不应超出太多——因此需要算法保证恰好够用避免浪费支持以集群总节点资源的百分比作为请求方式。此时若同时指定了绝对预留量需要决策以哪一种配置为准。该百分比方式在所有节点规格几乎相同的集群中更有用。在预留算法层面文档提出了三条温和处理gentle treatment原则用于平衡调度性能与预留效果被目标队列作业锁定的节点不能被选为预留节点避免与队列自身作业互相干扰被其他队列锁定的节点不能被选为预留节点队列间互不侵犯;在满足请求的前提下尽量锁定总资源量和节点数都尽可能少的节点组合避免对集群调度性能造成剧烈影响。文档还专门讨论了安全性恶意的超大预留申请会挤占其他队列的作业空间。因此在实现上需要与权限/配额体系配合控制谁可以为哪个队列申请预留——这是运维侧的治理要求而非纯粹的调度算法问题。3. API 设计spec.guarantee 与 status.reservation设计文档给出的 Queue CR 形态如下保留原文档示例apiVersion: scheduling.volcano.sh/v1beta1 kind: Queue metadata: name: q1 spec: reclaimable: true weight: 1 guarantee: # 预留配置关键字 policy: Best-Effort # 抢占式预留或非抢占式预留 percentage: # 锁定节点资源占集群的百分比 dimensions: [cpu, memory, gpu, other-scalable-resource-type...] value: 0.2 resource: # 指定预留资源 cpu: 2 memory: 4G status: state: Open reservation: # 预留状态关键字 nodes: [n1, n2] # 被锁定的节点列表 resource: # 被锁定节点上的总空闲资源 cpu: 1 memory: 2G3.1 各字段语义继承原文档 Fields 章节policy可选取值为Best-Effort或Guaranteed默认Best-Effort。Best-Effort表示调度器预留资源时不驱逐正在运行的工作负载Guaranteed则相反。注意原文档同时声明只考虑非抢占式预留即初始实现聚焦 Best-Effort 路径。percentage可选resource未指定时生效合法取值范围[0, 1]。需要锁定的节点数量按下式计算math.Floor(clusterNodeNumber * percentage)原文档特别指出节点会被随机锁定直至达到百分比要求若同时指定了resource则以预留资源更多者作为最终结果。guarantee.resource可选percentage未指定时生效需要预留的资源类别及数量列表。status.reservation.nodes被锁定锁定 纳入预留范围的节点列表。status.reservation.resource被锁定节点上的总空闲资源。用户可以观察这个字段判断预留是否已经满足需求——这是预留是否到位的观测入口。3.2 当前仓库中的实际 API 定义从源码看预留相关类型定义在 staging/src/volcano.sh/apis/pkg/apis/scheduling/types.go 中Guaranteetypes.go#L336-L341注释为 configuration of queue resource reservation字段Resource v1.ResourceList注释明确 Just set eitherpercentageorresourceReservationtypes.go#L344-L351包含Nodes []string锁定节点列表与Resource v1.ResourceList锁定节点上的总空闲资源与设计文档的status.reservation一一对应QueueSpec.Guaranteetypes.go#L429与QueueStatus.Reservationtypes.go#L370分别把两者挂到 Queue 的 spec 与 status 上v1beta1 对外 API 中同样存在对应定义见 staging/src/volcano.sh/apis/pkg/apis/scheduling/v1beta1/types.go。需要说明的是设计文档是 2020 年的方案稿其中policy/percentage等字段描述了完整的预留策略愿景而当前仓库的 API 中Guarantee结构实际落地的是Resource字段。也就是说为队列声明保底资源量这一核心能力已在 API 中确立并广泛消费百分比/策略化预留属于方案中提出、演进方向上的能力。这一差异在实操中意味着当前以spec.guarantee.resource作为队列保底资源的声明入口最为直接。4. 预留节点选择算法四维加权评分预留的难点不是锁多少而是锁哪些节点。设计文档给出的算法目标是在所有满足队列请求各维度均满足的节点组合中按以下四个维度排序选优每个维度有明确权重维度含义偏好权重sum(nodess resource)组合内节点资源总和越低优先级越高避免过度锁定权重 0.4queue already used队列自身在这些节点上已使用的资源用得越多优先级越高复用队列已有节点更稳定权重 0.35sum(nodess number)组合内节点数量越少优先级越高锁定节点越少对集群影响越小权重 0.15sum(nodess idle resource)组合内节点空闲资源总和越空闲优先级越高锁定更干净权重 0.1四个维度分别对应四条设计取舍继承原文档 Explanation of terms希望(sum - target)尽量小避免浪费集群资源因此权重最高0.4used因素会影响锁定节点的效率与稳定性队列作业已聚集的节点更适合作为其预留地当前两项得分接近时优先选节点数最少的组合因为锁定节点越少、对集群影响越小最不重要的因素是节点空闲度节点越空闲锁定效率越高。完整评分公式原文档 Complete formulaterm 定义sum为组合节点资源总和、target为目标队列请求资源、used为组合节点上已用资源总和、n为组合节点数、idle为组合节点空闲资源总和0.4*1/(sum-target)/[(sum-target)usednidle] 0.35*used/[(sum-target)usednidle] 0.15*1/n/[(sum-target)usednidle] 0.1*idle/[(sum-target)usednidle]可以看到公式采用各项除以统一的归一化分母(sum-target)usednidle的形式让四个量纲不同的维度可以相加比较且权重系数直接显式体现在公式中0.4 / 0.35 / 0.15 / 0.1。5. 锁定策略与控制器实现reserveWorker 周期性重锁设计文档的 Lock Strategy 定义了schedule relock周期重锁机制每 5s 或 10squeueController中的reserveWorker会为目标队列寻找最优的节点组合更新该队列的锁定节点列表并计算锁定节点上的空闲资源、写回status.reservation。这意味着预留不是一次性动作而是持续对账的过程集群负载变化后被锁节点上的空闲资源会波动控制器周期性重新评分选点、刷新 status用户即可通过观察status.reservation.resource感知预留水位。控制器侧的整体工作流见原文档配图插件侧文档提出新增node_reservation调度插件来承接第 4 节的选点算法其分配阶段的工作流为当前仓库实现现状的核对从当前仓库的检索结果看pkg/controllers/queue与pkg/scheduler/plugins目录下未检索到名为node_reservation的插件或reserveWorker的实现说明该设计稿中控制器 独立插件的形态在后续版本中经历了演进或该部分实现位于其他分支/被重构。但设计中沉淀下来的核心概念——spec.guarantee.resource声明保底、status.reservation反映锁定情况——在当前 API 中是真实存在的见第 3.2 节并且guarantee 资源在调度侧已由 Capacity 插件深度消费这正是下一节的内容。6. 落地消费Capacity 插件如何为队列保底资源兜底虽然设计稿中的选点插件已不复见于当前代码树但队列保底资源guarantee作为一个完整概念被 Capacity 插件全面接管实现了对预留资源在**配额计算与回收reclaim**两个关键环节的保护。以下均可在 pkg/scheduler/plugins/capacity/capacity.go 中验证1全集群 guarantee 总量汇总插件在更新队列属性时汇总所有队列的保底资源// capacity.go#L1062-L1068节选 if len(queue.Queue.Spec.Guarantee.Resource) 0 { // 无保底声明跳过 } guarantee : api.NewResource(queue.Queue.Spec.Guarantee.Resource) cp.totalGuarantee.Add(guarantee)2保底资源参与真实容量计算capacity.go#L1095-L1099attr.guarantee api.NewResource(queue.Queue.Spec.Guarantee.Resource) // 真实容量 集群总量超出其他队列保底的部分 本队列自己的保底 realCapability : api.ExceededPart(cp.totalResource, cp.totalGuarantee).Add(attr.guarantee)这行代码的语义是队列可调度容量 集群总资源扣除其他队列的保底后的部分再加上本队列自己的保底——也就是说一个队列声明的保底资源必然被包含在其自身可调度容量之内即使集群被其他队列占满该队列也至少能调度自己的 guarantee 部分。这正是资源预留在配额层面的最终效果。同样的ExceededPart(totalResource, totalGuarantee).Add(guarantee)模式也出现在层级队列hierarchical queue属性聚合逻辑中capacity.go#L1492-L1553父队列会聚合子队列的 guarantee 总量并做保底校验。3回收保护guarantee 资源不可被回收capacity.go#L1861-L1863// checkGuaranteeConstraint checks if removing the reclaimee would violate the queues guarantee. func (cp *capacityPlugin) checkGuaranteeConstraint(...)在 reclaim 路径上capacity.go#L520 与 #L634 附近插件在判定某个作业reclaimee能否被回收前会调用checkGuaranteeConstraint如果回收该作业会突破队列自身的 guarantee 下限则拒绝回收。这保证了预留/保底不只是账面数字而是在最激烈的资源竞争抢占式回收场景下仍然生效的硬约束。此外从源码结构看usage 插件基于影子缓存的使用量预估调度的 estimator 与 shadow cache 中也出现了对 Guarantee 的处理可以推断 guarantee 概念同样会影响 usage 类调度路径中的队列资源评估。7. 与 Job 级资源预留的关系、适用前提与限制Volcano 中存在两层资源预留设计注意区分队列级预留本文主题面向队列目标是保障该队列整体的资源水位与配额下限入口为spec.guarantee作业级预留面向单个作业设计见 docs/design/job-resource-reservation-design.md两者互补而不冲突。适用前提与限制以当前仓库实际状态为准预留声明通过更新 Queue CR 完成无需重启 Volcano 组件满足设计文档动态开关的需求但设计稿中的policy、percentage字段在当前 API 的Guarantee结构里并未保留当前可用的声明方式是spec.guarantee.resource固定资源量guarantee 资源的调度保护由 Capacity 插件承担配额计算 回收约束因此其生效前提是该队列所在调度器启用了 capacity 插件设计稿中 reserveWorker 周期重锁5s/10s与 node_reservation 插件的选点工作流在当前代码树中未检索到对应实现属于设计文档提出的方案形态实操中请以当前版本的实际能力第 6 节所述的 guarantee 消费链路为准安全性约束防止恶意大额度预留依赖集群的权限治理体系Volcano 本身在该设计文档中将其列为需运维侧配合的考虑项。小结Volcano 的队列资源预留设计以guarantee/reservation两个字段为核心抽象——spec 侧声明要预留什么status 侧反馈锁住了哪些节点、还剩多少空闲中间由节点组合的四维加权评分算法0.4/0.35/0.15/0.1解决锁哪些节点问题。从当前仓库源码看这套设计的核心承诺——队列保底资源在容量计算中必然可用、在回收竞争中被checkGuaranteeConstraint保护——已经在 Capacity 插件中形成闭环。【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →