Kubernetes 怎么把 GPU 分给容器:Device Plugin、GPU Operator 与共享三路线

一张 H100 八十 GB 显存,跑一个只占十 GB 的推理服务,利用率常年趴在百分之十——这是大多数公司 GPU 集群的日常。Kubernetes 原生把 GPU 当「整数个的扩展资源」管理,默认一块卡只能绑给一个容器。要把它切开分给别人,就得理解三件事:Device Plugin 机制、GPU Operator 的组件分工、以及时间片 / MIG / MPS 三条共享路线的取舍。本文基于 NVIDIA 官方文档与 Kubernetes 官方博客(截至 2026-10-07)把这套体系讲清。

Device Plugin:GPU 怎么进 Kubernetes 的资源账本

Kubernetes 调度器只认识 CPU、内存这类原生资源和「扩展资源」。GPU 属于后者,语义是整数:Pod 请求 nvidia.com/gpu: 1,调度器找一个「账上有 1」的节点,仅此而已——它不懂显存、算力或型号。

让「账上出现数字」的是 Device Plugin:NVIDIA 的 device-plugin 以 DaemonSet 跑在每个 GPU 节点上,通过 Unix socket 向 kubelet 上报「本节点有 N 个 nvidia.com/gpu」。Pod 被调度到节点后,kubelet 调插件的 Allocate 接口,把具体设备(设备文件、环境变量 NVIDIA_VISIBLE_DEVICES)注入容器。三个要点:

  1. 插件只做汇报与注入,不做隔离。容器拿到的仍然是整张卡的设备访问权,用量管控靠应用自觉或后续的共享机制。
  2. 扩展资源不可超卖、不可缩容重配——插件上报多少,账面就是多少。
  3. 插件配置变更不会自动生效,改完要手动重启 DaemonSet。

这套机制简单可靠,但粒度是「张」。要共享,得往下走。

GPU Operator:把驱动、运行时、插件打包成 Helm Chart

裸金属或云上装 GPU 节点,传统做法是 SSH 上去装驱动、装 nvidia-container-toolkit、装插件,节点一多就是灾难。GPU Operator 用 Operator 模式解决:一个 Helm Chart 把驱动容器、container toolkit、device plugin、DCGM 监控导出器、GPU 特性发现(node-feature-discovery)各安排一个 DaemonSet,节点打上 nvidia.com/gpu.present=true 标签后自动配置。

对本文主题最重要的是它内置的 MIG Manager:mig.strategy 两个取值——

  • mixed(默认):GPU 被切成 MIG 设备后,每个分区作为独立资源(如 nvidia.com/mig-1g.5gb)单独暴露,不同 Pod 可以各拿各的分区;
  • single:整卡切成一组统一规格的分区,整组绑给单个 Pod,适合一个作业独占整卡但按切片记账的场景。

具体切成什么形状由 mig-parted 的配置名决定(all-1g.10gb、all-balanced 等),通过 ConfigMap 下发给 MIG Manager 重配 GPU。另有集群级策略 ClusterPolicy 控制全局行为——改 device plugin 配置后同样需要 kubectl rollout restart 对应 DaemonSet 才生效。

共享三路线:时间片、MIG、MPS

时间片(Time-Slicing):最简单,也最裸奔

时间片让 CUDA 在进程间轮转时间片,插件把一块卡对外报成 N 个副本。配置长这样(NVIDIA 官方示例):

apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config
data:
  any: |-
    version: v1
    flags:
      migStrategy: none
      sharing:
        timeSlicing:
          renameByDefault: false
          failRequestsGreaterThanOne: false
          resources:
          - name: nvidia.com/gpu
            replicas: 4

建好 ConfigMap 后 patch ClusterPolicy 即可生效(Helm 安装时也可以用 --set devicePlugin.config.name=... 直接传入)。四个关键行为:

  • replicas: 4 意味着一块卡在账面上变成 4 个 nvidia.com/gpu,可以调 4 个 Pod;
  • renameByDefault: true 时资源改名为 nvidia.com/gpu.shared,便于在调度策略里区分独占与共享;
  • failRequestsGreaterThanOne: true 时,Pod 请求超过 1 个副本会直接 Admission 失败——防止有人以为「请求 2 个副本 = 半张卡」;
  • 官方文档的原话级警告:副本之间没有内存隔离,也没有故障隔离,一个 Pod 显存打爆会把整卡上的邻居一起拖垮;时间片也不保证算力按副本数比例分配,只是「所有进程平分时间」。

时间片适合开发测试、低利用率办公推理这类「凑合用」场景,生产关键负载慎用。

MIG:硬隔离,粒度以切片为单位

MIG(Multi-Instance GPU,A100/H100 及之后的数据中心卡支持)在硬件层把一张卡切成最多 7 个实例,每个实例有独立的 SM、独立的显存分区、独立的故障域。资源名直接编码规格:nvidia.com/mig-1g.5gb(A100 40GB 上 1/7 算力 + 5GB 显存)到 nvidia.com/mig-7g.40gb(整卡)。

MIG 与时间片不是二选一:官方支持「MIG 切片之上再做时间片」,把一个 MIG 实例再报成多个副本。代价是几何固定、重配需要排空节点上的 GPU Pod,且切片后单实例显存变小——大模型推理可能塞不下。MIG 适合多租户推理、 Notebook 平台这类需要真隔离的场景。

MPS:并发执行的中间态

CUDA MPS(Multi-Process Service)让多个进程的 kernel 同时在 SM 上并发执行,而不是像时间片那样轮流。吞吐比时间片好,尤其对小 kernel 密集的推理负载;但隔离性弱于 MIG——客户端进程共享一个 MPS 守护进程,一个进程崩溃可能影响同组其他进程,显存依旧不隔离。MPS 适合「互相信任的内部负载」共享一张卡榨吞吐。

怎么选

路线 隔离性 粒度 典型场景
时间片 无内存/故障隔离 副本数任意定 开发测试、低利用率共享
MIG 硬件级隔离 最多 7 切片 多租户推理、独立显存诉求
MPS 进程级(弱) 进程数 互信内部负载榨吞吐
独占 完全 整卡 训练、大模型推理

DRA:1.34 起 GA 的新玩法

Device Plugin 的整数语义用了近十年,Kubernetes v1.34(2025 年 8 月发布)终于让 DRA(Dynamic Resource Allocation)转正 GA。DRA 让工作负载按属性声明要什么设备——显存多大、什么型号、哪个厂商——而不是「给我 2 个」;ResourceClaim、ResourceSlice、DeviceClass 等一组 API 的体验类似 CSI 之于存储:第三方驱动自己描述与分配设备,调度器做整体裁决。对 GPU 集群这意味着分区、拓扑约束、多卡协同分配这些 device plugin 时代做不了或做不好的事有了标准入口。官方博客同时澄清了一个常见误解:DRA 不是给运行中的 Pod 热插 GPU,分配仍发生在调度期。

生态跟进需要时间(vLLM 等推理框架的 DRA 支持在社区追踪中),未来一两年的时间片 / MIG 配置经验仍是主流技能,但新集群的 GPU 管理规划值得把 DRA 纳入路线图。

实践清单

  • 先用 GPU Operator 把驱动、插件、监控标准化,再谈共享;
  • 共享配置变更后记得重启 device plugin DaemonSet,别在「改了没生效」上浪费时间;
  • 时间片一定配 failRequestsGreaterThanOne: true,并在节点标签上区分共享/独占池;
  • 多租户产品用 MIG,重配窗口放进变更流程(需要排空);
  • 监控注意:时间片下 DCGM 指标无法对应到具体容器,配额记账要靠资源名,别指望指标。

GPU 分享的本质是「利用率与故障半径」的交换。把这张交换表想清楚,再动手改配置,比直接抄 YAML 重要。

参考资料

← 返回资讯列表

读者留言

COMMENTS 暂无
仅本站原创文章开放留言 · 请勿留下手机号、邮箱等个人信息

还没有留言,来说第一句?