在 Azure Kubernetes 服务 (AKS) 上将 GPU 用于计算密集型工作负荷
图形处理单元 (GPU) 通常用于计算密集型工作负荷,例如图形和可视化工作负载。 AKS 支持启用 GPU 的 Linux 节点池来运行计算密集型 Kubernetes 工作负载。
受支持的启用了 GPU 的 VM
要查看受支持的启用了 GPU 的 VM,请参阅《Azure 中优化了 GPU 的 VM 大小。 对于 AKS 节点池,建议的最小大小为 Standard_NC6s_v3。 AKS 不支持 NVv4 系列(基于 AMD GPU)。
限制
- 如果使用 Azure Linux 已启用 GPU 的节点池,则不会应用自动安全修补程序。 有关节点 OS 升级通道的默认行为,请参阅当前的 AKS API 版本。
注意
对于 AKS API 版本 2023-06-01 或更高版本,节点 OS 升级的默认通道是 NodeImage。 对于以前的版本,默认通道是“无”。 要了解详细信息,请参阅“自动升级”。
- NVadsA10 v5 系列不是推荐用于 GPU VHD 的 SKU。
- 不支持通过更新现有节点池来添加 GPU。
开始之前
本文帮助你在新的和现有 AKS 群集上预配具有可计划 GPU 的节点。 本文假定你拥有现有的 AKS 群集。 如果需要 AKS 群集,请参阅使用 Azure CLI 的 AKS 快速入门、使用 Azure PowerShell 的 AKS 快速入门或使用 Azure 门户的 AKS 快速入门。
注意
如果使用 Azure Linux GPU 节点池,则不会应用自动安全修补程序,并且群集的默认行为是“非托管”。 有关详细信息,请参阅 auto-upgrade。
确保 Azure 订阅可以创建 NCv3 串行 VM(例如 Standard_NC6s_v3),否则,你可以提交一个支持票证,以便为 Azure 订阅启用该类型的 VM 大小。
创建 AKS 群集
如果需要可满足最低要求(启用了 GPU 的节点和 Kubernetes 版本 1.10 或更高版本)的 AKS 群集,请完成以下步骤。 如果已拥有满足这些要求的 AKS 群集,请跳至下一部分。
使用 NVIDIA GPU 的选项
使用 NVIDIA GPU 涉及各种 NVIDIA 软件组件(例如适用于 Kubernetes 的 NVIDIA 设备插件)的安装、GPU 驱动程序的安装,等等。
注意
默认情况下,Microsoft 会在节点映像部署过程中自动维护 NVidia 驱动程序的版本,并且 AKS 将会支持和管理它。 虽然 NVidia 驱动程序默认安装在支持 GPU 的节点上,但你需要安装设备插件。
NVIDIA 设备插件安装
在 AKS 上使用 GPU 时,需要安装 NVIDIA 设备插件。 在某些情况下,安装会自动进行,例如在使用 NVIDIA GPU Operator 或 AKS GPU 映像(预览版)时就是如此。 也可手动安装 NVIDIA 设备插件。
手动安装 NVIDIA 设备插件
可以为 NVIDIA 设备插件部署 DaemonSet,该插件会在每个节点上运行一个 Pod,为 GPU 提供所需的驱动程序。 这是为 Azure Linux 使用支持 GPU 的节点池时推荐使用的方法。
若要使用默认 OS SKU,请在不指定 OS SKU 的情况下创建节点池。 节点池是根据群集的 Kubernetes 版本为默认操作系统配置的。
使用
az aks nodepool add
命令将节点池添加到你的群集。az aks nodepool add \ --resource-group myResourceGroup \ --cluster-name myAKSCluster \ --name gpunp \ --node-count 1 \ --node-vm-size Standard_NC6s_v3 \ --node-taints sku=gpu:NoSchedule \ --enable-cluster-autoscaler \ --min-count 1 \ --max-count 3
此命令将名为 gpunp 的节点池添加到 myResourceGroup 中的 myAKSCluster,并使用参数配置以下节点池设置:
--node-vm-size
:将节点池中节点的 VM 大小设置为 Standard_NC6s_v3。--node-taints
:指定节点池上的 sku=gpu:NoSchedule 污点。--enable-cluster-autoscaler
:启用群集自动缩放程序。--min-count
:将群集自动缩放程序配置为在节点池中至少保留一个节点。--max-count
:将群集自动缩放程序配置为在节点池中至多保留三个节点。
注意
只能在创建节点池期间为节点池设置污点和 VM 大小,但随时可以更新自动缩放程序的设置。
使用
kubectl create namespace
命令创建命名空间。kubectl create namespace gpu-resources
创建名为 nvidia-device-plugin-ds.yaml 的文件,并粘贴适用于 Kubernetes 项目的 NVIDIA 设备插件中的以下 YAML 清单:
apiVersion: apps/v1 kind: DaemonSet metadata: name: nvidia-device-plugin-daemonset namespace: kube-system spec: selector: matchLabels: name: nvidia-device-plugin-ds updateStrategy: type: RollingUpdate template: metadata: labels: name: nvidia-device-plugin-ds spec: tolerations: - key: "sku" operator: "Equal" value: "gpu" effect: "NoSchedule" # Mark this pod as a critical add-on; when enabled, the critical add-on # scheduler reserves resources for critical add-on pods so that they can # be rescheduled after a failure. # See https://kubernetes.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/ priorityClassName: "system-node-critical" containers: - image: mcr.azk8s.cn/oss/nvidia/k8s-device-plugin:v0.14.1 name: nvidia-device-plugin-ctr env: - name: FAIL_ON_INIT_ERROR value: "false" securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] volumeMounts: - name: device-plugin mountPath: /var/lib/kubelet/device-plugins volumes: - name: device-plugin hostPath: path: /var/lib/kubelet/device-plugins
使用
kubectl apply
命令创建 DaemonSet 并确认已成功创建 NVIDIA 设备插件。kubectl apply -f nvidia-device-plugin-ds.yaml
成功安装 NVIDIA 设备插件后,就可以检查 GPU 是否可调度并运行 GPU 工作负荷了。
跳过 GPU 驱动程序安装(预览版)
如果要控制 NVidia 驱动程序的安装或使用 NVIDIA GPU 运营商,则可以跳过默认的 GPU 驱动程序安装。 Microsoft 不支持,也不会在节点映像部署过程中管理 NVidia 驱动程序的维护和兼容性。
重要
AKS 预览功能是可选择启用的自助功能。 预览功能是“按现状”和“按可用”提供的,不包括在服务级别协议和有限保证中。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:
使用
az extension add
或az extension update
命令注册或更新 aks-preview 扩展。# Register the aks-preview extension az extension add --name aks-preview # Update the aks-preview extension az extension update --name aks-preview
使用带有
--skip-gpu-driver-install
标志的az aks nodepool add
命令创建节点池,以跳过自动 GPU 驱动程序安装。az aks nodepool add \ --resource-group myResourceGroup \ --cluster-name myAKSCluster \ --name gpunp \ --node-count 1 \ --skip-gpu-driver-install \ --node-vm-size Standard_NC6s_v3 \ --enable-cluster-autoscaler \ --min-count 1 \ --max-count 3
在节点池创建期间添加
--skip-gpu-driver-install
标志会跳过自动 GPU 驱动程序安装。 不会更改任何现有节点。 可以将节点池缩放至零,然后进行备份,以使更改生效。
将 NVIDIA GPU Operator 与 AKS 配合使用
NVIDIA GPU Operator 可自动管理预配 GPU 所需的所有 NVIDIA 软件组件,包括驱动程序安装、适用于 Kubernetes 的 NVIDIA 设备插件、NVIDIA 容器运行时等。 由于 GPU Operator 会处理这些组件,因此无需手动安装 NVIDIA 设备插件。 这也意味着不再需要在 AKS 上自动安装 GPU 驱动程序。
通过使用带
--skip-gpu-driver-install
的az aks nodepool add
命令创建节点池,跳过自动 GPU 驱动程序安装。 在节点池创建期间添加--skip-gpu-driver-install
标志会跳过自动 GPU 驱动程序安装。 不会更改任何现有节点。 可以将节点池缩放至零,然后进行备份,以使更改生效。按照 NVIDIA 文档安装 GPU Operator。
成功安装 GPU Operator 后,就可以检查 GPU 是否可调度并运行 GPU 工作负荷了。
警告
不建议使用 AKS GPU 映像手动安装具有群集的 NVIDIA 设备插件守护程序集。
注意
使用 NVIDIA GPU Operator 在 SPOT 实例上部署时,还可能需要考虑其他一些因素。 请参考 https://github.com/NVIDIA/gpu-operator/issues/577
使用 AKS GPU 映像(预览版)
注意
AKS GPU 映像(预览版)将于 2025 年 1 月 10 日停用。 下面的自定义标头将不再可用,这意味着无法使用 AKS GPU 映像创建新的已启用 GPU 的节点池。 建议迁移到或使用默认 GPU 配置,而不是专用 GPU 映像,因为专用 GPU 映像不再受支持。 有关详细信息,请参阅 AKS 发行说明,或在 AKS 公共路线图中查看此停用公告。
AKS 提供了配置完全的 AKS 映像,其中包含适用于 Kubernetes 的 NVIDIA 设备插件。 AKS GPU 映像目前仅在 Ubuntu 18.04 上可用。
重要
AKS 预览功能是可选择启用的自助功能。 预览功能是“按现状”和“按可用”提供的,不包括在服务级别协议和有限保证中。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:
使用
az extension add
命令安装aks-preview
Azure CLI 扩展。az extension add --name aks-preview
使用
az extension update
命令更新到扩展的最新版本。az extension update --name aks-preview
使用
az feature register
命令注册GPUDedicatedVHDPreview
功能标志。az feature register --namespace "Microsoft.ContainerService" --name "GPUDedicatedVHDPreview"
状态显示为“已注册”需要几分钟时间。
使用
az feature show
命令验证注册状态。az feature show --namespace "Microsoft.ContainerService" --name "GPUDedicatedVHDPreview"
当状态反映为已注册时,使用
az provider register
命令刷新 Microsoft.ContainerService 资源提供程序的注册。az provider register --namespace Microsoft.ContainerService
将群集更新为使用 AKS GPU 映像后,可以将 GPU 节点的节点池添加到你的群集。
使用
az aks nodepool add
命令添加一个节点池。az aks nodepool add \ --resource-group myResourceGroup \ --cluster-name myAKSCluster \ --name gpunp \ --node-count 1 \ --node-vm-size Standard_NC6s_v3 \ --node-taints sku=gpu:NoSchedule \ --aks-custom-headers UseGPUDedicatedVHD=true \ --enable-cluster-autoscaler \ --min-count 1 \ --max-count 3
前面的示例命令将名为 gpunp 的节点池添加到 myResourceGroup 中的 myAKSCluster,并使用参数配置以下节点池设置:
--node-vm-size
:将节点池中节点的 VM 大小设置为 Standard_NC6s_v3。--node-taints
:指定节点池上的 sku=gpu:NoSchedule 污点。--aks-custom-headers
:指定专用 AKS GPU 映像 UseGPUDedicatedVHD=true。 如果你的 GPU SKU 需要第二代 VM,请改为使用 --aks-custom-headers UseGPUDedicatedVHD=true,usegen2vm=true。--enable-cluster-autoscaler
:启用群集自动缩放程序。--min-count
:将群集自动缩放程序配置为在节点池中至少保留一个节点。--max-count
:将群集自动缩放程序配置为在节点池中至多保留三个节点。
注意
只能在创建节点池期间为节点池设置污点和 VM 大小,但随时可以更新自动缩放程序的设置。
成功地使用 GPU 映像创建节点池后,就可以检查 GPU 是否可调度并运行 GPU 工作负荷了。
确认 GPU 是可计划的
创建完群集后,确认 GPU 在 Kubernetes 中是可计划的。
使用
kubectl get nodes
命令列出群集中的节点。kubectl get nodes
输出应类似于以下示例输出:
NAME STATUS ROLES AGE VERSION aks-gpunp-28993262-0 Ready agent 13m v1.20.7
使用
kubectl describe node
命令确认 GPU 可计划。kubectl describe node aks-gpunp-28993262-0
在“容量”部分下,GPU 应列为
nvidia.com/gpu: 1
。 输出应该类似于以下简洁示例输出:Name: aks-gpunp-28993262-0 Roles: agent Labels: accelerator=nvidia [...] Capacity: [...] nvidia.com/gpu: 1 [...]
安装 GPU 插件
kubectl create -f https://raw.githubusercontent.com/andyzhangx/demo/master/linux/gpu/nvidia-device-plugin-ds-mooncake.yaml
运行启用了 GPU 的工作负荷
若要查看 GPU 的实际运行情况,可通过相应的资源请求计划启用了 GPU 的工作负载。 在此示例中,我们将针对 MNIST 数据集运行一个 Tensorflow 作业。
创建名为“samples-tf-mnist-demo.yaml”的文件并粘贴以下 YAML 清单,它包含
nvidia.com/gpu: 1
的资源限制:注意
如果在调用驱动程序时收到版本不匹配错误,例如,CUDA 驱动程序版本不足以支持 CUDA 运行时版本,请查看 NVIDIA 驱动程序矩阵兼容性图表。
apiVersion: batch/v1 kind: Job metadata: labels: app: samples-tf-mnist-demo name: samples-tf-mnist-demo spec: template: metadata: labels: app: samples-tf-mnist-demo spec: containers: - name: samples-tf-mnist-demo image: mcr.azk8s.cn/azuredocs/samples-tf-mnist-demo:gpu args: ["--max_steps", "500"] imagePullPolicy: IfNotPresent resources: limits: nvidia.com/gpu: 1 restartPolicy: OnFailure tolerations: - key: "sku" operator: "Equal" value: "gpu" effect: "NoSchedule"
使用
kubectl apply
命令运行作业,该命令会分析清单文件并创建定义的 Kubernetes 对象。kubectl apply -f samples-tf-mnist-demo.yaml
查看启用了 GPU 的工作负载的状态
将
kubectl get jobs
命令与--watch
标志配合使用,以监视作业的进度。 先拉取映像并处理数据集可能需要几分钟时间。kubectl get jobs samples-tf-mnist-demo --watch
当 COMPLETIONS 列显示 1/1 时,作业已成功完成,如以下示例输出所示:
NAME COMPLETIONS DURATION AGE samples-tf-mnist-demo 0/1 3m29s 3m29s samples-tf-mnist-demo 1/1 3m10s 3m36s
使用 Ctrl-C 退出
kubectl --watch
进程。使用
kubectl get pods
命令获取 pod 的名称。kubectl get pods --selector app=samples-tf-mnist-demo
使用
kubectl logs
命令查看启用了 GPU 的工作负载的输出。kubectl logs samples-tf-mnist-demo-smnr6
Pod 日志的以下精简示例输出确认已发现相应的 GPU 设备
Tesla K80
:2019-05-16 16:08:31.258328: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA 2019-05-16 16:08:31.396846: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 0 with properties: name: Tesla K80 major: 3 minor: 7 memoryClockRate(GHz): 0.8235 pciBusID: 2fd7:00:00.0 totalMemory: 11.17GiB freeMemory: 11.10GiB 2019-05-16 16:08:31.396886: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: Tesla K80, pci bus id: 2fd7:00:00.0, compute capability: 3.7) 2019-05-16 16:08:36.076962: I tensorflow/stream_executor/dso_loader.cc:139] successfully opened CUDA library libcupti.so.8.0 locally Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes. Extracting /tmp/tensorflow/input_data/train-images-idx3-ubyte.gz Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes. Extracting /tmp/tensorflow/input_data/train-labels-idx1-ubyte.gz Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes. Extracting /tmp/tensorflow/input_data/t10k-images-idx3-ubyte.gz Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes. Extracting /tmp/tensorflow/input_data/t10k-labels-idx1-ubyte.gz Accuracy at step 0: 0.1081 Accuracy at step 10: 0.7457 Accuracy at step 20: 0.8233 Accuracy at step 30: 0.8644 Accuracy at step 40: 0.8848 Accuracy at step 50: 0.8889 Accuracy at step 60: 0.8898 Accuracy at step 70: 0.8979 Accuracy at step 80: 0.9087 Accuracy at step 90: 0.9099 Adding run metadata for 99 Accuracy at step 100: 0.9125 Accuracy at step 110: 0.9184 Accuracy at step 120: 0.922 Accuracy at step 130: 0.9161 Accuracy at step 140: 0.9219 Accuracy at step 150: 0.9151 Accuracy at step 160: 0.9199 Accuracy at step 170: 0.9305 Accuracy at step 180: 0.9251 Accuracy at step 190: 0.9258 Adding run metadata for 199 [...] Adding run metadata for 499
使用容器见解监视 GPU 使用情况
适用于 AKS 的容器见解监视以下 GPU 使用情况指标:
指标名称 | 指标维度(标记) | 说明 |
---|---|---|
containerGpuDutyCycle | container.azm.ms/clusterId ,container.azm.ms/clusterName ,containerName ,gpuId ,gpuModel ,gpuVendor |
在刚过去的采样周期(60 秒)中,GPU 处于繁忙/积极处理容器的状态的时间百分比。 占空比是 1 到 100 之间的数字。 |
containerGpuLimits | container.azm.ms/clusterId ,container.azm.ms/clusterName ,containerName |
每个容器可以将限值指定为一个或多个 GPU。 不能请求或限制为 GPU 的一部分。 |
containerGpuRequests | container.azm.ms/clusterId ,container.azm.ms/clusterName ,containerName |
每个容器可以请求一个或多个 GPU。 不能请求或限制为 GPU 的一部分。 |
containerGpumemoryTotalBytes | container.azm.ms/clusterId ,container.azm.ms/clusterName ,containerName ,gpuId ,gpuModel ,gpuVendor |
可用于特定容器的 GPU 内存量(以字节为单位)。 |
containerGpumemoryUsedBytes | container.azm.ms/clusterId ,container.azm.ms/clusterName ,containerName ,gpuId ,gpuModel ,gpuVendor |
特定容器使用的 GPU 内存量(以字节为单位)。 |
nodeGpuAllocatable | container.azm.ms/clusterId ,container.azm.ms/clusterName ,gpuVendor |
节点中可供 Kubernetes 使用的 GPU 数。 |
nodeGpuCapacity | container.azm.ms/clusterId ,container.azm.ms/clusterName ,gpuVendor |
节点中的 GPU 总数。 |
清理资源
使用
kubectl delete job
命令移除在本文中创建的相关 Kubernetes 对象。kubectl delete jobs samples-tf-mnist-demo
后续步骤
- 若要运行 Apache Spark 作业,请参阅在 AKS 上运行 Apache Spark 作业。
- 有关 Kubernetes 计划程序功能的详细信息,请参阅有关 AKS 中的高级计划程序功能的最佳做法。
- 有关 Azure Kubernetes 服务和 Azure 机器学习的详细信息,请参阅: