你肯定遇到过这种场景:花20万买了张A100-80G,想部署一个BERT推理服务和一个GPT推理服务。结果发现——一个只占3GB显存,另一个需要40GB显存。但这张卡一次只能跑一个Pod,剩下的全闲着?
以前你可能听说过Time Slicing,但那玩意儿在资源争抢的时候就跟早高峰的地铁一样——谁都在挤,谁都慢。今天聊另一个更硬核的方案:NVIDIA MIG(Multi-Instance GPU)。
MIG是NVIDIA在Ampere架构开始引入的物理级别GPU分区技术。它不是"分时共享",而是把GPU从物理层面切成几块,每块有独立的显存、独立的内存带宽、独立的缓存——互不打架。
目录
一、MIG到底是什么玩意儿?
MIG vs 其他方案一句话
二、哪些GPU能用MIG?
三、MIG分区规格一览:能切多大
四、实战:开启MIG + 创建分区
4.1 检查GPU是否支持MIG
4.2 开启MIG模式
4.3 创建MIG分区(GI + CI)
4.4 保留配置(持久化)
五、K8s里跑MIG:Device Plugin配置策略
5.1 安装NVIDIA Device Plugin(MIG模式)
5.2 完整的values.yaml配置
5.3 给MIG节点打标签
六、Pod资源请求怎么写?
6.1 1g.10gb实例的Pod
6.2 混合场景:不同Pod请求不同规格
6.3 用Deployment部署推理服务
七、DCGM Exporter + MIG监控
7.1 安装DCGM Exporter
7.2 完整的DCGM Exporter配置(含MIG指标)
7.3 验证MIG指标是否正常
7.4 Grafana看板建议
八、生产环境最佳实践与避坑
8.1 什么时候用MIG,什么时候别用
8.2 避坑清单
8.3 容量规划经验
一、MIG到底是什么玩意儿?
先说人话:MIG = 一张物理GPU,拆成多个独立的"小GPU"。
每个MIG实例拥有:
- 独立的显存— 你的MIG实例用的显存,别人碰不到
- 独立的内存带宽— 别人跑再猛也抢不了你的带宽
- 独立的L2缓存— 不会发生缓存污染
- 独立的内存控制器— 数据访问路径完全隔离
- 独立的中断和错误域— 一个MIG实例崩了,不影响其他MIG
⚠️MIG是硬隔离,不是软隔离。它不共享SM(流式多处理器),每个MIG实例拿到的是物理上独立的SM和显存切片。不像Time Slicing那样在软件层面轮流用同一组SM。
画个图你就明白了:
graph TB subgraph 物理GPU["💻 一张物理GPU A100-80GB"] subgraph MIG1["MIG Instance 1 — 1g.10gb"] SM1["SM × 14<br/>显存: 10GB<br/>L2缓存: 1/8"] Pod1["Pod A: BERT推理"] SM1 --- Pod1 end subgraph MIG2["MIG Instance 2 — 1g.10gb"] SM2["SM × 14<br/>显存: 10GB<br/>L2缓存: 1/8"] Pod2["Pod B: ResNet推理"] SM2 --- Pod2 end subgraph MIG3["MIG Instance 3 — 2g.20gb"] SM3["SM × 28<br/>显存: 20GB<br/>L2缓存: 1/4"] Pod3["Pod C: Llama推理"] SM3 --- Pod3 end subgraph MIG4["MIG Instance 4 — 3g.40gb"] SM4["SM × 42<br/>显存: 40GB<br/>L2缓存: 3/8"] Pod4["Pod D: GPT微调"] SM4 --- Pod4 end end style MIG1 fill:#e1f5fe,stroke:#01579b style MIG2 fill:#f3e5f5,stroke:#7b1fa2 style MIG3 fill:#fff3e0,stroke:#e65100 style MIG4 fill:#e8f5e9,stroke:#1b5e20💡关键理解:MIG的隔离发生在物理层,不是调度器层。你不需要担心A Pod的显存泄漏会搞垮B Pod,因为它们的物理路径从一开始就是分开的。这是MIG和所有软件级共享方案最本质的区别。
MIG vs 其他方案一句话
| 方案 | 隔离级别 | 显存隔离 | SM隔离 | 性能损失 | 适合场景 |
|---|---|---|---|---|---|
| MIG | 🔴 物理级 | ✅ 绝对隔离 | ✅ 绝对隔离 | ~0% | 生产多租户、合规要求 |
| vGPU | 🟡 虚拟化级 | ✅ 隔离 | ✅ 隔离 | ~5-10% | 虚拟化环境、VDI |
| Time Slicing | 🟢 软件级 | ❌ 不隔离 | ❌ 共享 | 争抢时50%+ | 开发测试、低负载 |
| HAMi | 🟡 中间层 | ✅ 显存隔离 | ❌ 算力共享 | ~10-15% | 内部平台、性价比优先 |
二、哪些GPU能用MIG?
不是所有NVIDIA GPU都支持MIG。目前支持的型号:
| GPU型号 | 架构 | 最大MIG实例数 | 可用状态 |
|---|---|---|---|
| A100 SXM / PCIe | Ampere GA100 | 7 | ✅ 已量产 |
| A30 | Ampere GA100 (cut) | 4 | ✅ 已量产 |
| H100 SXM / PCIe | Hopper GH100 | 7 | ✅ 已量产 |
| H200 | Hopper GH100 | 7 | ✅ 已量产 |
| B100 / B200 | Blackwell | TBD | 🔲 待验证 |
💡A30也能用MIG,最多切4个实例。A30比A100便宜不少,如果业务对单个实例的显存要求不大(单实例≤12GB),A30是性价比之选。
⚠️以下GPU不支持MIG:V100、T4、A10、A2、A40、L40、L40S。这些卡只能用Time Slicing或vGPU来实现共享。
三、MIG分区规格一览:能切多大
A100/H100支持的分区规格如下:
| 规格名称 | GPU Slice | SM数量 | 显存 | 内存带宽 | 最大实例数(A100-80G) |
|---|---|---|---|---|---|
1g.10gb | 1/7 GPU | 14 | 10 GB | 1/8 | 7 |
1g.10gb+me | 1/7+媒体引擎 | 14 | 10 GB | 1/8 | 1 |
2g.20gb | 2/7 GPU | 28 | 20 GB | 1/4 | 3 |
3g.40gb | 3/7 GPU | 42 | 40 GB | 3/8 | 2 |
4g.40gb | 4/7 GPU | 56 | 40 GB | 1/2 | 1 |
7g.80gb | 全卡 | 108(A100)/132(H100) | 80 GB | 全 | 1 |
💡命名规则解读:
1g.10gb= 1个GPU切片 + 10GB显存。2g.20gb= 2个切片 + 20GB显存。记得这是物理切片,不是逻辑划分。
最常用的分区方案:
graph LR subgraph 方案1["方案1:均衡型 — 7个1g.10gb"] S1M1["MIG 1: 推理A"] S1M2["MIG 2: 推理B"] S1M3["MIG 3: 推理C"] S1M4["MIG 4: 推理D"] S1M5["MIG 5: 推理E"] S1M6["MIG 6: 推理F"] S1M7["MIG 7: 推理G"] end subgraph 方案2["方案2:混合型 — 3g.40gb + 2g.20gb + 1g.10gb × 2"] S2M1["MIG 1: 3g.40gb<br/>大模型推理"] S2M2["MIG 2: 2g.20gb<br/>中型模型"] S2M3["MIG 3: 1g.10gb<br/>小模型A"] S2M4["MIG 4: 1g.10gb<br/>小模型B"] end- 方案1:7个1g.10gb,适合部署7个独立的小型推理服务(每个≤10GB显存)
- 方案2:混合搭配,一个大的40GB+一个20GB+两个10GB
四、实战:开启MIG + 创建分区
下面从头到尾演示怎么在一台A100-80G上开启MIG并创建分区。
4.1 检查GPU是否支持MIG
# 检查GPU是否支持MIG nvidia-smi --query-gpu=name,mig.mode.current,mig.mode.pending --format=csv # 输出示例 name, mig.mode.current, mig.mode.pending "NVIDIA A100-SXM4-80GB", "Disabled", "Disabled"如果看到Disabled,说明MIG还没开启。
4.2 开启MIG模式
MIG需要在GPU级别和驱动级别都开启:
# 1. 在驱动层面启用MIG sudo nvidia-smi -mig 1 # 2. 重启nvidia-persistenced(确保持久化) sudo systemctl restart nvidia-persistenced # 3. 验证MIG模式已开启 nvidia-smi --query-gpu=name,mig.mode.current --format=csv # 输出应该显示 "Enabled"⚠️开启MIG后GPU会重启,正在跑的任务会中断。生产环境务必在维护窗口操作。
4.3 创建MIG分区(GI + CI)
MIG的配置分两层:
- GI(GPU Instance):定义"切多大"(规格选择)
- CI(Compute Instance):定义"怎么用"(每个GI下可创建多个CI,用来做更细粒度的算力隔离)
💡最少配法:一般情况下,一个GI配一个CI就够了。除非你需要在同一个GI内再切算力。
创建7个1g.10gb实例(最常用方案):
# 检查可用配置 nvidia-smi mig -lgip # 获取1g.10gb的GPU Instance Profile ID(通常是19) # 创建7个1g.10gb实例 sudo nvidia-smi mig -i 0 -cgi 19,19,19,19,19,19,19 # 然后在每个GI下创建CI for i in $(seq 0 6); do sudo nvidia-smi mig -i 0 -gi $i -cci done创建混合方案(3g.40gb × 1 + 2g.20gb × 1 + 1g.10gb × 2):
# 先查询GI Profile ID # 3g.40gb → 通常为 16 # 2g.20gb → 通常为 15 # 1g.10gb → 通常为 19 # 创建混合布局 sudo nvidia-smi mig -i 0 -cgi 16,15,19,19 # 在创建的4个GI下各创建1个CI sudo nvidia-smi mig -i 0 -gi 0 -cci sudo nvidia-smi mig -i 0 -gi 1 -cci sudo nvidia-smi mig -i 0 -gi 2 -cci sudo nvidia-smi mig -i 0 -gi 3 -cci # 查看分区结果 nvidia-smi mig -i 0 -lgi查看最终的分区效果:
nvidia-smi输出应该会看到类似这样的结果——GPU 0下面有多个MIG实例,每个实例都有自己的进程和显存占用。
4.4 保留配置(持久化)
手工创建的分区在重启后会丢失。需要用mig-parted工具持久化:
# 编辑配置文件 sudo vim /etc/nvidia/mig-parted.cfg # 写入配置 cat > /etc/nvidia/mig-parted.cfg << 'EOF' { "mig_configs": { "7x1g.10gb": { "mig_devices": { "GPU-00000000-0000-0000-0000-000000000000": [19, 19, 19, 19, 19, 19, 19] } }, "mixed": { "mig_devices": { "GPU-00000000-0000-0000-0000-000000000000": [16, 15, 19, 19] } } } } EOF # 应用配置并重启 sudo nvidia-mig-parted -a apply -c /etc/nvidia/mig-parted.cfg -p 7x1g.10gb sudo systemctl restart nvidia-mig-parted⚠️UUID一定要改成你实际的GPU UUID,可以用
nvidia-smi -L查看。
五、K8s里跑MIG:Device Plugin配置策略
MIG在裸机上配置好之后,还需要让Kubernetes认识这些MIG实例。这需要NVIDIA Device Plugin的支持。
5.1 安装NVIDIA Device Plugin(MIG模式)
# 使用Helm安装(推荐) helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update # 安装时启用MIG支持 helm install nvidia-device-plugin \ nvidia/nvidia-device-plugin \ --namespace nvidia-device-plugin \ --create-namespace \ --set migStrategy=mixedMIG Strategy参数详解:
| 策略值 | 说明 | 使用场景 |
|---|---|---|
none | 不感知MIG,把整卡给Pod | 不用MIG时 |
single | 每个MIG实例当一块独立GPU | 最常用!Pod直接请求具体规格 |
mixed | 同时暴露整卡和MIG实例 | 有些Pod要整卡,有些Pod要MIG实例 |
💡生产环境建议用
single。这样每个MIG实例就像一块独立的GPU,Pod通过标签nvidia.com/mig-1g.10gb请求具体的规格。不会出现一个Pod意外占用整张卡的情况。
5.2 完整的values.yaml配置
# nvidia-device-plugin-values.yaml replicas: 1 updateStrategy: type: RollingUpdate config: default: "mig-single-config" map: mig-single-config: |- version: v1 flags: migStrategy: "single" sharing: timeSlicing: resources: # 这里不要配MIG相关资源,MIG有自己的资源名 mig: # MIG策略选型 strategy: "single" # 节点选择器:只安装在有MIG的A100节点上 nodeSelector: nvidia.com/gpu.mig: "true" # 容忍污点 tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule resources: limits: nvidia.com/gpu: 1 runtimeClassName: nvidia5.3 给MIG节点打标签
为了让调度器知道哪些节点有MIG实例可用:
# 给A100节点打MIG标签 kubectl label node a100-node-01 nvidia.com/gpu.mig=true # 确认Device Plugin的Pod已正确运行 kubectl -n nvidia-device-plugin get pods六、Pod资源请求怎么写?
MIG配置好之后,Pod怎么使用MIG实例呢?关键在于资源请求的写法。
6.1 1g.10gb实例的Pod
apiVersion: v1 kind: Pod metadata: name: bert-inference-mig labels: app: bert-serving gpu-type: mig-1g.10gb spec: containers: - name: bert-inference image: nvcr.io/nvidia/tritonserver:23.12-py3 command: ["/bin/bash", "-c"] args: - | tritonserver \ --model-repository=/models/bert \ --model-control-mode=explicit resources: limits: # 关键:请求1g.10gb的MIG实例 nvidia.com/mig-1g.10gb: 1 memory: 8Gi cpu: 4 env: - name: NVIDIA_VISIBLE_DEVICES value: "mig-1g.10gb" nodeSelector: nvidia.com/gpu.mig: "true"6.2 混合场景:不同Pod请求不同规格
--- # Pod A — 大模型推理,用3g.40gb apiVersion: v1 kind: Pod metadata: name: llama2-inference labels: app: llama2 mig-profile: 3g.40gb spec: containers: - name: llama image: nvcr.io/nvidia/tritonserver:23.12-py3 resources: limits: nvidia.com/mig-3g.40gb: 1 cpu: 8 memory: 16Gi --- # Pod B — 中型模型推理,用2g.20gb apiVersion: v1 kind: Pod metadata: name: resnet-inference labels: app: resnet mig-profile: 2g.20gb spec: containers: - name: resnet image: nvcr.io/nvidia/tritonserver:23.12-py3 resources: limits: nvidia.com/mig-2g.20gb: 1 cpu: 4 memory: 8Gi --- # Pod C — 小型模型推理,用1g.10gb apiVersion: v1 kind: Pod metadata: name: tiny-bert-inference labels: app: tinybert mig-profile: 1g.10gb spec: containers: - name: tinybert image: nvcr.io/nvidia/tritonserver:23.12-py3 resources: limits: nvidia.com/mig-1g.10gb: 1 cpu: 2 memory: 4Gi⚠️资源名必须是
nvidia.com/mig-{规格}格式,不能写nvidia.com/gpu。如果你写nvidia.com/gpu: 1,调度器会给你一整张A100,而不是MIG实例。
6.3 用Deployment部署推理服务
apiVersion: apps/v1 kind: Deployment metadata: name: bert-serving-deployment labels: app: bert-serving spec: replicas: 3 selector: matchLabels: app: bert-serving template: metadata: labels: app: bert-serving spec: nodeSelector: nvidia.com/gpu.mig: "true" containers: - name: triton-server image: nvcr.io/nvidia/tritonserver:23.12-py3 ports: - containerPort: 8000 name: http - containerPort: 8001 name: grpc - containerPort: 8002 name: metrics resources: limits: nvidia.com/mig-1g.10gb: 1 cpu: 4 memory: 8Gi env: - name: NVIDIA_VISIBLE_DEVICES value: "mig-1g.10gb" - name: CUDA_VISIBLE_DEVICES value: "0" readinessProbe: httpGet: path: /v2/health/ready port: 8000 initialDelaySeconds: 30 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: bert-serving-service spec: type: ClusterIP selector: app: bert-serving ports: - name: http port: 8000 targetPort: 8000 - name: grpc port: 8001 targetPort: 8001七、DCGM Exporter + MIG监控
MIG分区跑起来之后,怎么知道每个MIG实例的资源使用情况?用DCGM Exporter。
7.1 安装DCGM Exporter
DCGM(Data Center GPU Manager)是NVIDIA官方的GPU监控工具,支持MIG级别的指标采集。
# 使用Helm安装DCGM Exporter helm repo add gpu-helm-charts \ https://nvidia.github.io/dcgm-exporter/helm-charts helm repo update helm install dcgm-exporter \ gpu-helm-charts/dcgm-exporter \ --namespace gpu-monitoring \ --create-namespace7.2 完整的DCGM Exporter配置(含MIG指标)
# dcgm-exporter-values.yaml serviceMonitor: enabled: true namespace: gpu-monitoring interval: 15s # 自定义采集指标 customMetrics: 1: # GPU利用率(整卡级别) - name: DCGM_FI_PROF_GR_ENGINE_ACTIVE 068: "gpu_utilization" # 显存利用率 - name: DCGM_FI_DEV_FB_USED 152: "memory_used_bytes" # 显存总量 - name: DCGM_FI_DEV_FB_TOTAL 154: "memory_total_bytes" # GPU温度 - name: DCGM_FI_DEV_GPU_TEMP 096: "gpu_temperature_celsius" # 功耗 - name: DCGM_FI_DEV_POWER_USAGE 100: "power_usage_watts" 2: # MIG级别指标 - name: DCGM_FI_PROF_GR_ENGINE_ACTIVE 1007: "mig_gpu_utilization" mig_profile: "true" - name: DCGM_FI_DEV_FB_USED 1008: "mig_memory_used_bytes" mig_profile: "true" - name: DCGM_FI_DEV_FB_TOTAL 1009: "mig_memory_total_bytes" mig_profile: "true" # 配置MIG模式 arguments: - --collectors - /etc/dcgm-exporter/dcp-metrics-included.csv - -f - /etc/dcgm-exporter/collectors_added.csv # 节点选择器 nodeSelector: nvidia.com/gpu.mig: "true"7.3 验证MIG指标是否正常
# 查看DCGM暴露的指标 kubectl -n gpu-monitoring port-forward svc/dcgm-exporter 9400:9400 # 访问指标端点 curl -s http://localhost:9400/metrics | grep mig你会看到类似的指标输出:
# HELP DCGM_FI_PROF_GR_ENGINE_ACTIVE GPU utilization # TYPE DCGM_FI_PROF_GR_ENGINE_ACTIVE gauge DCGM_FI_PROF_GR_ENGINE_ACTIVE{gpu="0",mig_profile="1g.10gb",mig_index="0"} 32.5 DCGM_FI_PROF_GR_ENGINE_ACTIVE{gpu="0",mig_profile="1g.10gb",mig_index="1"} 67.2 DCGM_FI_PROF_GR_ENGINE_ACTIVE{gpu="0",mig_profile="3g.40gb",mig_index="0"} 89.1 # HELP DCGM_FI_DEV_FB_USED FB Memory usage (MB) # TYPE DCGM_FI_DEV_FB_USED gauge DCGM_FI_DEV_FB_USED{gpu="0",mig_profile="1g.10gb",mig_index="0"} 2048 DCGM_FI_DEV_FB_USED{gpu="0",mig_profile="1g.10gb",mig_index="1"} 4096 DCGM_FI_DEV_FB_USED{gpu="0",mig_profile="3g.40gb",mig_index="0"} 327687.4 Grafana看板建议
配合Prometheus + Grafana,你可以在Dashboard里添加以下MIG面板:
- 各MIG实例GPU利用率— 区分每个实例的算力使用情况
- 各MIG实例显存使用— 监控显存是否接近上限
- 各MIG实例功耗分摊— 整卡功耗按比例分摊到各实例
- MIG实例可用性— 是否有实例异常退出
八、生产环境最佳实践与避坑
8.1 什么时候用MIG,什么时候别用
✅ 适合MIG的场景:
- 多租户生产环境,不同团队/客户共用GPU集群
- 不同模型推理任务混合部署(BERT小模型 + Llama大模型)
- 有合规要求,必须做到租户间资源硬隔离
- 金融、医疗等对隔离性有严格要求的行业
❌ 不适合MIG的场景:
- 单一大模型训练 — 会吃掉整张卡的显存和算力,MIG反而降低了可用资源
- 开发测试环境 — MIG配置改变需要重启GPU,开发环境切换频繁会让人崩溃
- GPU型号不支持 — 上面列过,V100/T4/A10等别想了
- 需要动态调整分区大小 — MIG是静态的,改分区要重启GPU
8.2 避坑清单
⚠️MIG不支持CUDA Unified Memory和CUDA IPC。如果你的AI框架用了这两者之一的特性,跑在MIG上会炸。PyTorch的
torch.distributed跨MIG实例通信也可能有问题。
⚠️改MIG分区配置需要重启GPU。这不是热插拔。部署前想清楚分区策略,别频繁改。
⚠️MIG实例不能热迁移。Pod如果从一个MIG实例移到另一个,等于在新卡上冷启动。别把它当容器调度那样做无状态迁移。
💡MIG实际性能 ≈ 物理卡 × 切片比例。你拿1/7的A100,就跑1/7的性能。不存在MIG带来额外开销的说法(但要注意内存带宽分配不是完全的线性,1g.10gb拿1/8带宽而不是1/7)。
8.3 容量规划经验
一张A100-80G怎么分区最划算?
| 业务场景 | 推荐分区方案 | 可同时跑的Pod数 |
|---|---|---|
| 7个轻量推理 | 7 × 1g.10gb | 7 |
| 2中2小 | 1 × 3g.40gb + 1 × 2g.20gb + 2 × 1g.10gb | 4 |
| 1大+几小 | 1 × 4g.40gb + 3 × 1g.10gb | 4 |
| 纯大模型 | 1 × 7g.80gb(整卡模式) | 1 |
💡不要把显存规划卡得太死。比如你的模型推理占9GB显存,留1GB给CUDA driver和TensorRT的额外开销。所以9GB的模型只适合2g.20gb或3g.40gb,别硬怼1g.10gb。
九、总结:什么时候该上MIG
MIG的核心理念就是一句话:用物理隔离换安全,用静态分区换确定性。
| 维度 | MIG | Time Slicing |
|---|---|---|
| 隔离级别 | 🔴 物理级 | 🟢 软件级 |
| 安全性 | ✅ 租户间互不影响 | ❌ Pod可以互相争抢/干扰 |
| 性能 | 稳定可预期 | 争抢时抖动大 |
| 灵活性 | ❌ 改分区要重启GPU | ✅ 动态调整 |
| 适用阶段 | ✅ 生产环境 | ✅ 开发测试 |
如果你正在做GPU集群的生产环境多租户方案,MIG是当前最靠谱的隔离方案,没有之一。特别是金融、医疗这类对隔离性有明确合规要求的行业,MIG是唯一的选择。
但代价也很明显——不够灵活。分区改了就要重启GPU,所以分区计划一定要想清楚再做。
下一期预告:Time Slicing配置——开发测试环境的GPU共享。跟MIG不同,Time Slicing不需要重启GPU、支持动态调整、所有GPU都支持。但性能上的坑也不少。敬请期待。
🏷️ 标签:#NVIDIA MIG #GPU分区 #A100 #H100 #K8s #硬隔离 #多租户
📦 文末三件套:
- 收藏— 这篇实操配置够你从零到一把MIG跑起来,收藏了下次配的时候直接翻
- 点赞👍— 如果你觉得有收获,点个赞让我知道
- 关注➕— 整个AI云原生实战系列持续更新中,不关注就错过了
🔗 相关阅读:
- 一张A100掰成7瓣用?NVIDIA MIG+Time Slicing+HAMi GPU共享深度对比
- Kubernetes GPU调度:从Pod到Node的AI工作负载管理
📢 下期预告:Time Slicing配置——开发测试环境的GPU共享