Kubernetes 的设备资源抽象与演进
真正理解 Kubernetes 设备模型的边界,才能为 GPU 平台的可扩展性和治理能力打下坚实基础。
本章将解释 Kubernetes 的设备资源语义为何天然倾向于“整卡分配”,以及更细粒度表达在工程上意味着什么。重点聚焦“边界与责任”,为后续 MIG/HAMi 的数据平面讨论与 Volcano/Kueue 的控制面讨论提供共同前提。
结论先行:Kubernetes 并非“缺少 GPU 调度能力”,而是其资源抽象天然偏向“离散设备”
Kubernetes 的核心资源模型是为 CPU/内存这类“可分割、可约束、可度量”的资源设计的;而 GPU、FPGA、NIC 这类 设备资源(Device Resource) 更接近“离散、稀缺、强状态”。因此,Kubernetes 对设备资源的主流抽象是:
- 以 Extended Resource 的形式做“整数计数”调度(例如
nvidia.com/gpu: 1),调度器只负责把 Pod 放到“具备足够整数设备”的节点上。 - 把“具体哪一块设备、如何准备/挂载/注入”下沉到 kubelet 侧的 Device Manager + Device Plugin,在
Allocate阶段完成。
这意味着,后续讨论 MIG、HAMi、GPUStack 时,必须先明确“责任边界”:Kubernetes 默认只提供离散资源的声明与调度,不承诺更细粒度共享与 QoS。细粒度能力要么靠数据平面扩展,要么依赖新一代资源 API(DRA, Dynamic Resource Allocation)。
设备资源在 Kubernetes 里的基本表达:Extended Resources(标量、整数、不可超卖)
在 Kubernetes 中,设备资源的表达方式有其独特之处,主要体现在 Extended Resource 的使用上。
为什么 GPU 看起来总是“整卡整数”
Kubernetes 调度器擅长处理“标量资源(Scalar Resource)”,设备资源通过 Extended Resource 被当作一个标量计数:节点上有多少、Pod 要多少。以 GPU 为例,官方任务文档直接将 GPU 作为一种可被调度的节点资源,强调其依赖 device plugin,并同时指出实现存在限制。
这解释了为什么“资源请求”在 Pod spec 里几乎总是 nvidia.com/gpu: 1/2/…:这并非 GPU 的全部能力,而是 Kubernetes 资源模型对设备的主流折中。
为什么设备资源通常只放在 limits(并且要求 requests=limits)
Kubernetes 对设备资源的调度依赖于“你要用多少设备”,但设备本身无法像 CPU 一样被 cgroup 精确限流。因此,设备资源通常只在 limits 中声明,并被实现要求“requests == limits”才能获得确定的调度与分配语义(这也是 GPU 相关文档里常见的写法)。
Device Plugin 机制:控制面只做“放哪”,数据平面负责“给什么”
Device Plugin 是 Kubernetes 官方为“非核心硬件资源”提供的标准扩展机制。厂商或项目实现一个 plugin,kubelet 通过 gRPC 注册并与之交互。官方文档给出了 registration gRPC 的接口形态,并描述了注册与后续交互流程。
在 kubelet 内部,由 Device Manager 负责与 device plugins 通信并完成设备发现、广告与分配。Kubernetes 官方博客总结了其工作方式:device plugin 通过 Unix socket 与 kubelet 通信,负责设备发现/广告(作为 extended resources)与 allocation。
整个链路可抽象为三步(对后续排障极其关键):
- Advertise:device plugin 发现设备并让 kubelet 将其作为 Extended Resource 暴露给调度器。
- Bind:调度器完成 Pod→Node 绑定。
- Allocate:kubelet 调用 device plugin 的
Allocate,把“具体设备 ID”交付给容器运行时(并做必要的 mount/环境变量/设备文件准备)。
下图展示了 Device Manager 的完整工作流程:
这意味着:**调度器并不知道你最终拿到的是哪块 GPU,更不知道你希望的是 MIG profile、时间片还是显存配额。**这些都属于数据平面“兑现层”的事情。
设备资源抽象的天然边界:为什么“更细粒度 GPU”在 Kubernetes 里并不自然
当你把 GPU 视作整数计数时,会立刻出现三类不可避免的缺口:
连续资源与多维约束无法表达
显存、带宽、拓扑、干扰都不是一个整数能表达的。调度阶段只有“有/没有、够/不够”的判断,难以对 P99、抖动与干扰建立承诺。“共享”不是 Kubernetes 资源模型的一等公民
Device Plugin 的语义是“把一个离散设备交付给容器”。如果你想让多个 Pod 共享一块 GPU,本质是在做“超卖/分时/切分”的资源复用,这会越过原生模型边界,必须由数据平面实现并自行承担 QoS、隔离与计量责任。拓扑与可用性由节点侧决定,控制面很难推理
设备的健康、驱动兼容、MIG 重配置、CUDA runtime 差异,都可能在 Allocate 阶段才暴露。你看到的可能是“调度成功但运行失败”,而这种失败不能靠调度算法本身解决。 下图清晰地展示了 Kubernetes 设备资源的抽象层次与各层的责任边界:
“演进”发生在哪里:从 Device Manager GA 到 DRA
Kubernetes 对设备资源的演进路线,本质是在回答一个问题:如何让设备的“选择、参数化、共享与生命周期”变成可声明、可推理、可自动化的 API,而不仅仅是 kubelet 本地的 Allocate 黑盒。
Device Manager / Device Plugin 的成熟:把“接入异构设备”标准化
Device Plugin 让厂商无需修改 Kubernetes 核心代码就能接入设备;Device Manager 在 kubelet 内部承接交互并成为标准通道。官方对 Device Manager 的总结强调它通过 gRPC 与 plugin 完成设备发现、广告与分配,是设备接入的关键基础设施。这条路线解决的是“接得进来”,但对“怎么选、怎么共享、怎么治理”支持有限。
DRA(Dynamic Resource Allocation):把设备选择从“节点本地黑盒”推进到“可声明的资源 API”
DRA(Dynamic Resource Allocation)机制让 Pod 能请求并共享(尤其是硬件加速器等附加设备)资源。管理员定义 device classes,Kubernetes 为 claim 分配匹配设备,并把 Pod 放到能访问已分配设备的节点上。 对应的 KEP 也明确:Resource driver 负责 ResourceClaim 的分配/回收等与设备相关的操作。
从“GPU 平台化”的视角看,DRA 解决的关键问题是:
- 参数化请求:不再只能声明“1 块 GPU”,而是声明“某类设备 + 某组参数”的 claim。
- 可推理的分配对象:设备分配从 kubelet 的 Allocate 走向控制面可见、可审计的资源对象。
- 为生态扩展预留接口:驱动/厂商/平台可以通过 DRA driver 实现设备分配逻辑,而不是把所有策略塞进 scheduler extender 或私有实现。
需要注意的是,DRA 的不同实现路径和版本特性在不同 Kubernetes 版本下处于不同阶段。例如,Kubernetes 文档的日文版本对 DRA 标注了 beta/alpha 的不同 feature state。
把“更细粒度 GPU”放回正确的层:MIG、时间片与资源命名
有了上述边界,你就能更清晰地理解“细粒度”的两种典型落点:
MIG:把“细粒度”变成新的离散设备单位
MIG(Multi-Instance GPU)的工程化路径通常是:在节点上把一张 GPU 切出多个 MIG 实例,然后通过 device plugin 把这些实例作为可调度资源暴露出来。NVIDIA 的 device plugin 甚至会在mixed策略下暴露形如nvidia.com/mig-<slice_count>g.<memory_size>gb的资源名供 Pod 精确申请。 NVIDIA 官方文档也专门描述了在 Kubernetes 中启用 MIG 的软件栈与前置条件,以及通过 GPU Operator 管理 MIG 配置的方式。 本质上,MIG 是把“连续资源问题”重新离散化,让它重新适配 Kubernetes 的整数模型。时间片/共享:用数据平面扩展把“共享”强行塞进整数模型
NVIDIA 在其生态中提供了 GPU time-slicing 等共享机制,并通过 device plugin/operator 提供相关能力与文档。 这条路线的本质是:控制面依然只看到整数资源,但数据平面在交付阶段用时间片复用同一物理设备。其优点是弹性与利用率,代价是隔离、可预测性与计量口径需要你在平台层补齐。
本章对后续章节的“共同前提”:边界与责任
到这里,你应当得到三条可直接复用的判断准则(后续对比 HAMi、GPUStack、Volcano、Kueue 时都用得上):
- 凡是解决“谁先用、谁等、配额怎么承诺”的,属于控制面问题(典型是 Kueue / Volcano 的队列与策略语义)。
- 凡是解决“GPU 如何切、如何共享、如何隔离、如何交付”的,属于数据平面问题(MIG / time-slicing / 各类虚拟化与 device plugin 扩展)。
- Kubernetes 原生设备模型默认只保证“离散设备的声明与交付”,不保证共享 QoS。你想要“可治理共享”,就必须引入数据平面机制与观测/计量闭环,或者走向 DRA 这类更强的资源 API。
下一章“决策轴”会把这些抽象落到可评审的矩阵上:粒度、隔离、干扰、可观测、运维成本与兼容性,让你可以用同一套语言比较 MIG、HAMi、时间片共享,以及它们与 Volcano/Kueue 的组合方式。
总结
本章梳理了 Kubernetes 设备资源模型的天然边界与责任划分,明确了控制面与数据平面的分工。理解这些基础,有助于后续在平台治理、资源共享、隔离与扩展性等方面做出更合理的架构决策。
参考文献
- Schedule GPUs - kubernetes.io
- Device Plugins - kubernetes.io
- Kubernetes 1.26: Device Manager graduates to GA - kubernetes.io
- Dynamic Resource Allocation - kubernetes.io
- KEP-3063: Dynamic Resource Allocation with Control - github.com
- NVIDIA device plugin for Kubernetes - github.com
- MIG Support in Kubernetes - docs.nvidia.com
- Improving GPU Utilization in Kubernetes - developer.nvidia.com