从ignoredResources说起:Kubernetes早期异构资源调度思路

2026-04-27
9 min read

最近在看一个比较具体的问题:当异构资源的资源调度需要做到动态分配时,Kubernetes各组件的资源管理逻辑到底分别承担什么职责? 顺着社区文档往回看,能比较清楚地看到两条关键线索:一条是早期的Resource API/ResourceClass的设计思路,而这又和DRA(Dynamic Resource Allocation)的发展相关;另一条是围绕NodeResourcesFitignoredResources/ignoredResourceGroups讨论。

摘要

这篇文章主要介绍Kubernetes社区在第一个阶段(2018)是如何处理“异构资源动态分配”这个问题的。当资源不再是同质、可简单计数的资源(例如CPU、内存),而是具备型号、拓扑、状态等差异的异构资源时,Kubernetes要如何处理这类资源的动态分配。 围绕这个问题,本文聚焦两部分内容:一是NodeResourcesFit为什么需要增加ignoredResources一类能力,这段代码背后的动机是什么;二是Resource API / ResourceClass设想到底想解决什么问题。

DRA 时间线

先放一个简化版本的DRA时间线,帮助理解这篇文章讨论的问题背景;更完整的部分放到后续系列文章里再展开。

  • 2018:Resource API提案提出:在“扩展资源不应该只是整数计数器”的基础上,构思出表达设备属性、资源类别和更丰富的匹配语义。Resource API Proposal

  • 2021:classic DRA提案提出:开始把动态资源分配抽象成一组独立API(ResourceClaim、ResourceClass等),支持在不同Pod间访问同一个资源实例。Dynamic resource allocation

  • 2022:classic DRA在v1.26进入alpha阶段:提供resource.k8s.io/v1alpha1 API group,Pod spec里可以通过新的resourceClaims字段声明运行所需的claim,容器里则通过resources.claims决定自己访问哪些资源声明。Kubernetes 1.26: Alpha API For Dynamic Resource Allocation

  • 2024:structured parameters DRA提案提出:把原来主要由设备驱动解释的分配参数,改造成Kubernetes控制面也能理解和处理的结构化信息。Dynamic Resource Allocation with Structured Parameters

  • 2025:structured parameters DRA进入GA:Kubernetes v1.34发布,DRA核心能力正式进入GA/stable阶段。Kubernetes v1.34: DRA has graduated to GA

结论

  1. Resource API / ResourceClass想要解决的问题是:当资源不再是简单整数时,Kubernetes要怎样描述资源、理解资源,并把设备选择逻辑前移到调度阶段。
  2. 社区在2020年围绕NodeResourcesFit有过一次讨论:是否允许kube-scheduler忽略一批动态生成的扩展资源名,把这部分资源交给自定义调度插件处理。ignoredResources解决的是默认调度插件的可扩展性问题,也就是默认调度器怎样给异构资源的自定义调度逻辑让路。
  3. 在社区视角,scheduler和kubelet承担不同层面的职责:scheduler负责节点选择和资源分配决策,kubelet则负责在目标节点上把分配结果准备好并交给Pod使用。因此,scheduler上的ignoredResources可以理解为默认调度逻辑对自定义资源判断交给自定义逻辑;但kubelet是否也能复用ignoredResources思路,要看具体场景。如果资源仍然是需要严格兑现的硬资源,kubelet就不能简单忽略;如果节点侧本来就有自定义资源管理逻辑接管分配和切换,那么kubelet可以让位给这套逻辑。

下面先看NodeResourcesFit这段代码讨论,再回到它背后的Resource API/ResourceClass设想。

NodeResourcesFit为什么需要增加ignoredResources

从原始issue和PR中讨论来看,提案背后的场景不是普通的nvidia.com/gpu这类固定的异构设备映射资源,而是更加动态的异构资源分配。例如下面这类设备资源:

vendor.com/rc1
vendor.com/rc2

这里的rc1rc2不是固定型号,而是按需生成的ResourceClass名称。在原有的NodeResourcesFit调度流程中,这种资源分配会遇到这些问题:

  • NodeResourcesFit的默认逻辑只知道资源请求和节点容量来检查资源是否足够,却不知道异构设备上的匹配约束;
  • 这类异构资源真正需要的,是更高语义的匹配和分配逻辑,比如资源类兼容性、设备拓扑、共享/切分能力、绑定约束等;

从这个角度看,scheduler忽略部分资源校验本质上不是取消约束,而是一种责任转移:默认的NodeResourcesFit不再对这类资源做通用判断,而是把决策权交给更了解资源语义的自定义插件

进一步看,如果异构设备还会持续更新,那么仅靠按精确资源名配置ignoredResources参数会显得不够用。相比之下,ignoredResourceGroups参数能将一组vendor.com/*设备从默认的资源检查插件中排除。当新的型号(例如rc3)加入可以不需要每次都重启调度器。

这一点很重要,因为它说明 ignoredResources / ignoredResourceGroups 解决的并不是“资源能不能被调度”这个问题,而是“默认调度插件应该在什么边界上退出,并把决策权交给更高语义的异构资源调度逻辑”这个问题。这也正是它会进一步连接到更大范围异构资源建模讨论的原因。

顺着这个问题继续往下看,就会看到一个更大的主题:当资源已经不再是简单的整数对象时,Kubernetes应该如何建模资源与表达资源需求。 这也正是后续Resource API/ResourceClass试图回答的问题。

Resource API/ResourceClass解决什么问题

我这里更倾向于把这份KEP理解成一份早期的 Resource API草案。它想解决的不是某一个单点问题,而是一整类“异构资源怎么建模、怎么调度、怎么分配”的问题。

这个草案关注的核心问题是:现有的extended resource结构适合同质、可按整数计数的资源,却不适合表达异构设备的属性差异。对 scheduler 来说,vendor.com/gpu: 1只能表示“要一个资源”,却无法表示“我要哪一类资源、应该按什么约束来匹配”。而对异构设备来说,真正影响调度结果的往往不是数量本身,而是型号、拓扑、是否支持共享或切分等属性。

1. 资源如何表达

这份草案首先想解决的是资源表达问题:不再只把设备当成一个整数资源名,而是把它提升为带属性、带分类的资源对象。从这个角度看,这份草案把资源从“计数对象”升级成“可描述对象”。资源名本身不再承载全部语义,真正的资源语义应该由额外的属性信息(CRD)来表达。这样,scheduler在看节点资源时,看到的就不只是一个抽象数量,而是一组可供匹配和筛选的异构资源。

2. 需求如何表达

Pod不再只是请求具体的1个“扩展资源”,而是请求“满足某类属性约束的一类资源”。因此,ResourceClass 要解决的不是数量表达问题,而是需求抽象问题:它试图把容器对异构设备的需求,从“请求一个资源名”提升成“请求一类满足特定条件的资源”。

3. 选择由谁完成

异构资源的选择往往需要全局视角:不仅要比较不同节点之间的资源差异,还要把设备属性和 CPU、内存、拓扑等其他约束一起考虑。如果把这一步留在 kubelet,本质上就是先决定“Pod 落到哪个节点”,再在节点上做局部选择;而草案希望的是,scheduler 在全局调度阶段就尽可能把这类决策做完。

而kubelet更多负责节点侧的分配落地和运行时执行。device plugin也不是独立的节点资源分配控制组件,它是kubelet的一个扩展接口;真正和Pod生命周期、单机资源分配调用串起来的主体一直是kubelet。

这背后的动机其实很自然:

  • 调度阶段拥有全集群视角,更适合做全局最优选择;
  • kubelet是节点本地组件,天然更适合处理Pod已经落到本节点之后的本地分配;
  • 如果设备挑选要同时考虑跨节点比较、设备属性匹配,以及和其他资源的联合决策,那么把逻辑放在scheduler里会更顺手。

如果把这三点合在一起,这份草案的核心目标就比较清楚了:

当设备或扩展资源不再是简单的同质整数资源时,需要一种比原生extended resource更高语义的资源模型,让scheduler主导设备选择。

其实也就能解释为什么这篇文章要同时看Resource API / ResourceClassignoredResources这两部分材料:

  • ignoredResources是把一部分资源选择逻辑交给来自定义插件时,调度器的默认资源校验应该如何适配,为这类自定义逻辑让出空间;
  • Resource API / ResourceClass想解决的是资源模型的定义:当资源是异构设备时,Kubernetes 应该如何描述资源、理解资源、选择资源;

虽然两者对应的不是同一个层面的问题,但它们恰好又是连在一起的。从代码历史上看,scheduler忽略部分扩展资源的能力更早进入主线;而Resource API / ResourceClass讨论的是更高层的资源建模问题。二者不是同一条实现路径,但在异构资源调度问题上前后相连。

小结

本文重点梳理两条线索:一条是调度器的NodeResourcesFit插件引入ignoredResources/ignoredResourceGroups的动机;另一条是Resource API/ResourceClass草案试图解决的资源建模问题(虽然这个解决方案最后被重置了)。前者关注默认调度器如何给自定义资源逻辑让路,后者关注异构资源应如何表达、如何描述需求,以及资源选择应由谁主导。

参考资料

comments powered by Disqus