Kubernetes 中的 MIG 支持
多实例 GPU (MIG) 功能支持将 GPU(例如 NVIDIA A100)安全地划分为多个独立的 GPU 实例,用于 CUDA 应用程序。例如,NVIDIA A100 最多支持七个独立的 GPU 实例。
MIG 为多个用户提供独立的 GPU 资源,以实现最佳的 GPU 利用率。此功能对于不能完全饱和 GPU 计算能力的工作负载尤其有益,因此用户可能希望并行运行不同的工作负载以最大化利用率。
本文档概述了启用 Kubernetes 的 MIG 支持所需的必要软件。有关技术概念、MIG 设置以及使用 MIG 运行容器的 NVIDIA Container Toolkit 的更多详细信息,请参阅 MIG 用户指南。
部署工作流程需要以下先决条件
您已安装 NVIDIA A100 所需的 NVIDIA R450+ 数据中心 (450.80.02+) 驱动程序。
您已安装 NVIDIA Container Toolkit v2.5.0+
您已经有一个 Kubernetes 部署正在运行,并且可以访问至少一个 NVIDIA A100 GPU。
满足这些先决条件后,您可以继续在集群中部署 NVIDIA k8s-device-plugin
和(可选)gpu-feature-discovery
组件的 MIG 功能版本,以便 Kubernetes 可以在可用的 MIG 设备上调度 Pod。
下面列出了所需软件组件的最低版本
NVIDIA R450+ 数据中心驱动程序:450.80.02+
NVIDIA Container Toolkit (
nvidia-docker2
):v2.5.0+NVIDIA k8s-device-plugin:v0.7.0+
NVIDIA gpu-feature-discovery:v0.2.0+
MIG 策略
NVIDIA 提供了两种在 Kubernetes 节点上公开 MIG 设备的策略。有关策略的更多详细信息,请参阅 设计文档。
在 Kubernetes 中使用 MIG 策略
本节将逐步介绍部署和运行各种 MIG 策略的 k8s-device-plugin
和 gpu-feature-discovery
组件所需的步骤。首选的部署方法是通过 Helm。
对于备用部署方法,请参阅以下 GitHub 存储库中的安装说明
首先,添加 nvidia-device-plugin
和 gpu-feature-discovery
helm 存储库
$ helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
$ helm repo add nvgfd https://nvidia.github.io/gpu-feature-discovery
$ helm repo update
然后,验证 nvidia-device-plugin 的 v0.7.0 版本和 gpu-feature-discovery 的 v0.2.0 版本是否可用
$ helm search repo nvdp --devel
NAME CHART VERSION APP VERSION DESCRIPTION
nvdp/nvidia-device-plugin 0.7.0 0.7.0 A Helm chart for ...
$ helm search repo nvgfd --devel
NAME CHART VERSION APP VERSION DESCRIPTION
nvgfd/gpu-feature-discovery 0.2.0 0.2.0 A Helm chart for ...
最后,选择一个 MIG 策略并部署 nvidia-device-plugin 和 gpu-feature-discovery 组件
$ export MIG_STRATEGY=<none | single | mixed>
$ helm install \
--version=0.7.0 \
--generate-name \
--set migStrategy=${MIG_STRATEGY} \
nvdp/nvidia-device-plugin
$ helm install \
--version=0.2.0 \
--generate-name \
--set migStrategy=${MIG_STRATEGY} \
nvgfd/gpu-feature-discovery
使用不同策略进行测试
本节将逐步介绍测试每种 MIG 策略所需的步骤。
注意
在默认设置下,对于 mixed 策略,一个容器一次只能请求 一种 设备类型。如果容器请求多种设备类型,则接收到的设备是未定义的。例如,容器不能同时请求 nvidia.com/gpu
和 nvidia.com/mig-3g.20gb
。但是,它可以请求同一资源类型的多个实例(例如,nvidia.com/gpu: 2
或 nvidia.com/mig-3g.20gb: 2
),而没有限制。
为了缓解此行为,我们建议遵循 文档 中概述的指南。
none 策略
none
策略旨在使 nvidia-device-plugin 的运行方式与以往相同。该插件不会区分启用或未启用 MIG 的 GPU,并将枚举节点上的所有 GPU,使其可以使用 nvidia.com/gpu
资源类型。
测试
为了测试此策略,我们检查启用和未启用 MIG 的 GPU 的枚举,并确保在这两种情况下都能看到它。此测试假设集群中的单个节点上有一个 GPU。
验证 GPU 上是否禁用了 MIG
$ nvidia-smi
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 450.80.02 Driver Version: 450.80.02 CUDA Version: 11.0 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 A100-SXM4-40GB Off | 00000000:36:00.0 Off | 0 | | N/A 29C P0 62W / 400W | 0MiB / 40537MiB | 6% Default | | | | Disabled | +-------------------------------+----------------------+----------------------+
使用上一节中描述的
none
策略启动 nvidia-device-plugin。如果插件已在运行,请重新启动它。观察到节点上有一个 GPU 可用,资源类型为
nvidia.com/gpu
$ kubectl describe node ... Capacity: nvidia.com/gpu: 1 ... Allocatable: nvidia.com/gpu: 1 ...
使用上一节中描述的
none
策略启动 gpu-feature-discovery。如果插件已在运行,请重新启动它。观察到已为此 MIG 策略应用了正确的标签集
$ kubectl get node -o json | \ jq '.items[0].metadata.labels | with_entries(select(.key | startswith("nvidia.com")))'
{ "nvidia.com/cuda.driver.major": "450", "nvidia.com/cuda.driver.minor": "80", "nvidia.com/cuda.driver.rev": "02", "nvidia.com/cuda.runtime.major": "11", "nvidia.com/cuda.runtime.minor": "0", "nvidia.com/gfd.timestamp": "1605312111", "nvidia.com/gpu.compute.major": "8", "nvidia.com/gpu.compute.minor": "0", "nvidia.com/gpu.count": "1", "nvidia.com/gpu.family": "ampere", "nvidia.com/gpu.machine": "NVIDIA DGX", "nvidia.com/gpu.memory": "40537", "nvidia.com/gpu.product": "A100-SXM4-40GB" }
部署一个 Pod 以使用 GPU 并运行
nvidia-smi
$ kubectl run -it --rm \ --image=nvidia/cuda:11.0-base \ --restart=Never \ --limits=nvidia.com/gpu=1 \ mig-none-example -- nvidia-smi -L
GPU 0: A100-SXM4-40GB (UUID: GPU-15f0798d-c807-231d-6525-a7827081f0f1)
在 GPU 上启用 MIG(首先需要停止所有 GPU 客户端)
$ sudo systemctl stop kubelet
$ sudo nvidia-smi -mig 1
Enabled MIG Mode for GPU 00000000:36:00.0 All done.
$ nvidia-smi --query-gpu=mig.mode.current --format=csv,noheader
Enabled
重新启动
kubelet
和插件$ sudo systemctl start kubelet
观察到节点上有一个 GPU 可用,资源类型为
nvidia.com/gpu
。$ kubectl describe node ... Capacity: nvidia.com/gpu: 1 ... Allocatable: nvidia.com/gpu: 1 ...
观察到标签没有改变
$ kubectl get node -o json | \ jq '.items[0].metadata.labels | with_entries(select(.key | startswith("nvidia.com")))'
{ "nvidia.com/cuda.driver.major": "450", "nvidia.com/cuda.driver.minor": "80", "nvidia.com/cuda.driver.rev": "02", "nvidia.com/cuda.runtime.major": "11", "nvidia.com/cuda.runtime.minor": "0", "nvidia.com/gfd.timestamp": "1605312111", "nvidia.com/gpu.compute.major": "8", "nvidia.com/gpu.compute.minor": "0", "nvidia.com/gpu.count": "1", "nvidia.com/gpu.family": "ampere", "nvidia.com/gpu.machine": "NVIDIA DGX", "nvidia.com/gpu.memory": "40537", "nvidia.com/gpu.product": "A100-SXM4-40GB" }
部署一个 Pod 以使用 GPU 并运行 nvidia-smi
$ kubectl run -it --rm \ --image=nvidia/cuda:9.0-base \ --restart=Never \ --limits=nvidia.com/gpu=1 \ mig-none-example -- nvidia-smi -L
GPU 0: A100-SXM4-40GB (UUID: GPU-15f0798d-c807-231d-6525-a7827081f0f1)
single 策略
single
策略旨在保持在 Kubernetes 中使用 GPU 的用户体验与以往相同。MIG 设备像以前一样使用 nvidia.com/gpu 资源类型进行枚举。但是,与该资源类型关联的属性现在映射到该节点上可用的 MIG 设备,而不是完整的 GPU。
测试
为了测试此策略,我们检查是否使用传统的 nvidia.com/gpu
资源类型枚举了单一类型的 MIG 设备。此测试假设集群中的单个节点上有一个 GPU,并且已在其上启用 MIG。
验证 GPU 上是否启用了 MIG 并且没有 MIG 设备
$ nvidia-smi
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 450.80.02 Driver Version: 450.80.02 CUDA Version: 11.0 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 A100-SXM4-40GB On | 00000000:00:04.0 Off | On | | N/A 32C P0 43W / 400W | 0MiB / 40537MiB | N/A Default | | | | Enabled | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | MIG devices: | +------------------+----------------------+-----------+-----------------------+ | GPU GI CI MIG | Memory-Usage | Vol| Shared | | ID ID Dev | BAR1-Usage | SM Unc| CE ENC DEC OFA JPG| | | | ECC| | |==================+======================+===========+=======================| | No MIG devices found | +-----------------------------------------------------------------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
在 GPU 上创建 7 个单片 MIG 设备
$ sudo nvidia-smi mig -cgi 19,19,19,19,19,19,19 -C
$ nvidia-smi -L
GPU 0: A100-SXM4-40GB (UUID: GPU-4200ccc0-2667-d4cb-9137-f932c716232a) MIG 1g.5gb Device 0: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/7/0) MIG 1g.5gb Device 1: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/8/0) MIG 1g.5gb Device 2: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/9/0) MIG 1g.5gb Device 3: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/10/0) MIG 1g.5gb Device 4: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/11/0) MIG 1g.5gb Device 5: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/12/0) MIG 1g.5gb Device 6: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/13/0)
使用上一节中描述的
single
策略启动 nvidia-device-plugin 插件。如果插件已在运行,请重新启动它。观察到节点上有 7 个 MIG 设备可用,资源类型为
nvidia.com/gpu
$ kubectl describe node ... Capacity: nvidia.com/gpu: 7 ... Allocatable: nvidia.com/gpu: 7 ...
使用上一节中描述的
single
策略启动 gpu-feature-discovery。如果插件已在运行,请重新启动它。观察到已为此 MIG 策略应用了正确的标签集
$ kubectl get node -o json | \ jq '.items[0].metadata.labels | with_entries(select(.key | startswith("nvidia.com")))'
{ "nvidia.com/cuda.driver.major": "450", "nvidia.com/cuda.driver.minor": "80", "nvidia.com/cuda.driver.rev": "02", "nvidia.com/cuda.runtime.major": "11", "nvidia.com/cuda.runtime.minor": "0", "nvidia.com/gfd.timestamp": "1605657366", "nvidia.com/gpu.compute.major": "8", "nvidia.com/gpu.compute.minor": "0", "nvidia.com/gpu.count": "7", "nvidia.com/gpu.engines.copy": "1", "nvidia.com/gpu.engines.decoder": "0", "nvidia.com/gpu.engines.encoder": "0", "nvidia.com/gpu.engines.jpeg": "0", "nvidia.com/gpu.engines.ofa": "0", "nvidia.com/gpu.family": "ampere", "nvidia.com/gpu.machine": "NVIDIA DGX", "nvidia.com/gpu.memory": "4864", "nvidia.com/gpu.multiprocessors": "14", "nvidia.com/gpu.product": "A100-SXM4-40GB-MIG-1g.5gb", "nvidia.com/gpu.slices.ci": "1", "nvidia.com/gpu.slices.gi": "1", "nvidia.com/mig.strategy": "single" }
部署 7 个 Pod,每个 Pod 消耗一个 MIG 设备(然后读取其日志并删除它们)
$ for i in $(seq 7); do kubectl run \ --image=nvidia/cuda:11.0-base \ --restart=Never \ --limits=nvidia.com/gpu=1 \ mig-single-example-${i} -- bash -c "nvidia-smi -L; sleep infinity" done
pod/mig-single-example-1 created pod/mig-single-example-2 created pod/mig-single-example-3 created pod/mig-single-example-4 created pod/mig-single-example-5 created pod/mig-single-example-6 created pod/mig-single-example-7 created
$ for i in $(seq 7); do echo "mig-single-example-${i}"; kubectl logs mig-single-example-${i} echo ""; done
mig-single-example-1 GPU 0: A100-SXM4-40GB (UUID: GPU-4200ccc0-2667-d4cb-9137-f932c716232a) MIG 1g.5gb Device 0: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/7/0) mig-single-example-2 GPU 0: A100-SXM4-40GB (UUID: GPU-4200ccc0-2667-d4cb-9137-f932c716232a) MIG 1g.5gb Device 0: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/9/0) ...
$ for i in $(seq 7); do kubectl delete pod mig-single-example-${i}; done
pod "mig-single-example-1" deleted pod "mig-single-example-2" deleted ...
mixed 策略
mixed
策略旨在为集群中可用的每个 MIG 设备配置枚举不同的资源类型。
测试
为了测试此策略,我们检查是否使用其完全限定名称(格式为 nvidia.com/mig-<slice_count>g.<memory_size>gb
)枚举了所有 MIG 设备。此测试假设集群中的单个节点上有一个 GPU,并且已在其上启用 MIG。
验证 GPU 上是否启用了 MIG 并且没有 MIG 设备
$ nvidia-smi
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 450.80.02 Driver Version: 450.80.02 CUDA Version: 11.0 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 A100-SXM4-40GB On | 00000000:00:04.0 Off | On | | N/A 32C P0 43W / 400W | 0MiB / 40537MiB | N/A Default | | | | Enabled | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | MIG devices: | +------------------+----------------------+-----------+-----------------------+ | GPU GI CI MIG | Memory-Usage | Vol| Shared | | ID ID Dev | BAR1-Usage | SM Unc| CE ENC DEC OFA JPG| | | | ECC| | |==================+======================+===========+=======================| | No MIG devices found | +-----------------------------------------------------------------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
在 GPU 上创建 3 个不同大小的不同 MIG 设备
$ sudo nvidia-smi mig -cgi 9,14,19 -C
$ nvidia-smi -L
GPU 0: A100-SXM4-40GB (UUID: GPU-4200ccc0-2667-d4cb-9137-f932c716232a) MIG 3g.20gb Device 0: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/2/0) MIG 2g.10gb Device 1: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/3/0) MIG 1g.5gb Device 2: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/9/0)
使用上一节中描述的
mixed
策略启动 nvidia-device-plugin 插件。如果插件已在运行,请重新启动它。观察到节点上有 3 个 MIG 设备可用,资源类型为
nvidia.com/gpu
$ kubectl describe node ... Capacity: nvidia.com/mig-1g.5gb: 1 nvidia.com/mig-2g.10gb: 1 nvidia.com/mig-3g.20gb: 1 ... Allocatable: nvidia.com/mig-1g.5gb: 1 nvidia.com/mig-2g.10gb: 1 nvidia.com/mig-3g.20gb: 1 ...
使用上一节中描述的
mixed
策略启动 gpu-feature-discovery。如果插件已在运行,请重新启动它。观察到已为此 MIG 策略应用了正确的标签集
$ kubectl get node -o json | \ jq '.items[0].metadata.labels | with_entries(select(.key | startswith("nvidia.com")))'
{ "nvidia.com/cuda.driver.major": "450", "nvidia.com/cuda.driver.minor": "80", "nvidia.com/cuda.driver.rev": "02", "nvidia.com/cuda.runtime.major": "11", "nvidia.com/cuda.runtime.minor": "0", "nvidia.com/gfd.timestamp": "1605658841", "nvidia.com/gpu.compute.major": "8", "nvidia.com/gpu.compute.minor": "0", "nvidia.com/gpu.count": "1", "nvidia.com/gpu.family": "ampere", "nvidia.com/gpu.machine": "NVIDIA DGX", "nvidia.com/gpu.memory": "40537", "nvidia.com/gpu.product": "A100-SXM4-40GB", "nvidia.com/mig-1g.5gb.count": "1", "nvidia.com/mig-1g.5gb.engines.copy": "1", "nvidia.com/mig-1g.5gb.engines.decoder": "0", "nvidia.com/mig-1g.5gb.engines.encoder": "0", "nvidia.com/mig-1g.5gb.engines.jpeg": "0", "nvidia.com/mig-1g.5gb.engines.ofa": "0", "nvidia.com/mig-1g.5gb.memory": "4864", "nvidia.com/mig-1g.5gb.multiprocessors": "14", "nvidia.com/mig-1g.5gb.slices.ci": "1", "nvidia.com/mig-1g.5gb.slices.gi": "1", "nvidia.com/mig-2g.10gb.count": "1", "nvidia.com/mig-2g.10gb.engines.copy": "2", "nvidia.com/mig-2g.10gb.engines.decoder": "1", "nvidia.com/mig-2g.10gb.engines.encoder": "0", "nvidia.com/mig-2g.10gb.engines.jpeg": "0", "nvidia.com/mig-2g.10gb.engines.ofa": "0", "nvidia.com/mig-2g.10gb.memory": "9984", "nvidia.com/mig-2g.10gb.multiprocessors": "28", "nvidia.com/mig-2g.10gb.slices.ci": "2", "nvidia.com/mig-2g.10gb.slices.gi": "2", "nvidia.com/mig-3g.21gb.count": "1", "nvidia.com/mig-3g.21gb.engines.copy": "3", "nvidia.com/mig-3g.21gb.engines.decoder": "2", "nvidia.com/mig-3g.21gb.engines.encoder": "0", "nvidia.com/mig-3g.21gb.engines.jpeg": "0", "nvidia.com/mig-3g.21gb.engines.ofa": "0", "nvidia.com/mig-3g.21gb.memory": "20096", "nvidia.com/mig-3g.21gb.multiprocessors": "42", "nvidia.com/mig-3g.21gb.slices.ci": "3", "nvidia.com/mig-3g.21gb.slices.gi": "3", "nvidia.com/mig.strategy": "mixed" }
部署 3 个 Pod,每个 Pod 消耗一个可用的 MIG 设备
$ kubectl run -it --rm \ --image=nvidia/cuda:11.0-base \ --restart=Never \ --limits=nvidia.com/mig-1g.5gb=1 \ mig-mixed-example -- nvidia-smi -L
GPU 0: A100-SXM4-40GB (UUID: GPU-4200ccc0-2667-d4cb-9137-f932c716232a) MIG 1g.5gb Device 0: (UUID: MIG-GPU-4200ccc0-2667-d4cb-9137-f932c716232a/9/0) pod "mig-mixed-example" deleted