一张 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)注入容器。三个要点:
- 插件只做汇报与注入,不做隔离。容器拿到的仍然是整张卡的设备访问权,用量管控靠应用自觉或后续的共享机制。
- 扩展资源不可超卖、不可缩容重配——插件上报多少,账面就是多少。
- 插件配置变更不会自动生效,改完要手动重启 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 暂无还没有留言,来说第一句?