Uso de GPU para cargas de trabajo de cálculo intensivo en Azure Kubernetes Service (AKS)

Por lo general, las unidades de procesamiento gráfico (GPU) se usan para cargas de trabajo de cálculo intensivo, como cargas de trabajo de visualización y gráficos. AKS admite grupos de nodos Linux habilitados para GPU para ejecutar cargas de trabajo de Kubernetes que consumen muchos procesos.

Este artículo le permite aprovisionar nodos con GPU programables en clústeres de AKS nuevos y existentes.

Máquinas virtuales habilitadas para GPU compatibles

Para ver las máquinas virtuales habilitadas para GPU compatibles, consulte Tamaños de máquinas virtuales optimizadas para GPU en Azure. Para grupos de nodos de AKS, se recomienda un tamaño mínimo de Standard_NC6s_v3. La serie NVv4 (basada en GPU de AMD) no es compatible con AKS.

Nota:

Las máquinas virtuales habilitadas para GPU contienen hardware especializado que está sujeto a una mayor disponibilidad de precios y región. Para obtener más información, consulte la herramienta de precios y la disponibilidad de regiones.

Limitaciones

  • Si usa un grupo de nodos habilitados para GPU de Linux de Azure, no se aplican revisiones de seguridad automáticas y el comportamiento predeterminado del clúster es No administrado. Para más información, vea Actualización automática.
  • La serie NVadsA10 v5 no es una SKU recomendada para VHD de GPU.
  • No se admite la actualización de un grupo de nodos existente para agregar la GPU.

Antes de empezar

  • Este artículo supone que ya tiene un clúster de AKS. Si no dispone de un clúster, cree uno mediante Azure CLI, Azure PowerShell o el Azure Portal.
  • Es preciso que esté instalada y configurada la versión 2.0.64 de la CLI de Azure, o cualquier otra posterior. Ejecute az --version para encontrar la versión. Si necesita instalarla o actualizarla, vea Instalación de la CLI de Azure.

Obtención de las credenciales del clúster

  • Obtenga las credenciales del clúster de AKS mediante el comando az aks get-credentials. Con el siguiente comando de ejemplo se obtienen las credenciales del clúster myAKSCluster en el grupo de recursos myResourceGroup:

    az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
    

Opciones para usar GPU de NVIDIA

El uso de GPU de NVIDIA implica la instalación de varios componentes de software NVIDIA, como el complemento de dispositivo NVIDIA para Kubernetes, la instalación del controlador de GPU, etc.

Omisión de la instalación del controlador de GPU (versión preliminar)

AKS tiene habilitada, de forma predeterminada, la instalación automática del controlador de GPU. En algunos casos, como al instalar sus propios controladores o usar el operador de GPU de NVIDIA, es posible que quiera omitir la instalación de controladores de GPU.

Importante

Las características en versión preliminar de AKS están disponibles como opción de participación y autoservicio. Las versiones preliminares se proporcionan "tal cual" y "como están disponibles", y están excluidas de los Acuerdos de nivel de servicio y garantía limitada. Las versiones preliminares de AKS reciben cobertura parcial del soporte al cliente en la medida de lo posible. Por lo tanto, estas características no están diseñadas para su uso en producción. Para más información, consulte los siguientes artículos de soporte:

  1. Registre o actualice la extensión aks-preview mediante el comando az extension add o az extension update.

    # Register the aks-preview extension
    az extension add --name aks-preview
    
    # Update the aks-preview extension
    az extension update --name aks-preview
    
  2. Cree un grupo de nodos mediante el comando az aks nodepool add con la marca --skip-gpu-driver-install para omitir la instalación automática del controlador de 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
    

    Al agregar la marca --skip-gpu-driver-install durante la creación del grupo de nodos, se omite la instalación automática del controlador de GPU. No se cambian los nodos existentes. Puede escalar el grupo de nodos a cero y, a continuación, realizar una copia de seguridad para que el cambio surta efecto.

Instalación del complemento de dispositivo NVIDIA

La instalación del complemento de dispositivo NVIDIA es necesaria cuando se usan GPU en AKS. En algunos casos, la instalación se controla automáticamente, como cuando se usa el operador de GPU de NVIDIA o la imagen de GPU de AKS (versión preliminar). Además, puede instalar manualmente el complemento del dispositivo NVIDIA.

Instalar manualmente el complemento.

Puede implementar un DaemonSet para el complemento de dispositivo NVIDIA, que ejecuta un pod en cada nodo para proporcionar los controladores necesarios para las GPU. Este es el enfoque recomendado al usar grupos de nodos habilitados para GPU para Azure Linux.

Para usar la SKU predeterminada del sistema operativo, cree el grupo de nodos sin especificar una SKU del sistema operativo. El grupo de nodos está configurado para el sistema operativo predeterminado en función de la versión de Kubernetes del clúster.

  1. Agregue un grupo de nodos a su clúster mediante el comando 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
    

    Este comando agrega un grupo de nodos denominado gpunp a myAKSCluster en myResourceGroup y utiliza parámetros para configurar las siguientes opciones del grupo de nodos:

    • --node-vm-size: establece el tamaño de la máquina virtual para el nodo en el grupo de nodos en Standard_NC6s_v3.
    • --node-taints: especifica sku=gpu:NoSchedule en el grupo de nodos.
    • --enable-cluster-autoscaler: habilita el autoescalador del clúster.
    • --min-count: configura el autoescalador del clúster para mantener un mínimo de un nodo en el grupo de nodos.
    • --max-count: configura el autoescalador de clúster para mantener un máximo de tres nodos en el grupo de nodos.

    Nota:

    El tamaño de los nodos y de las máquinas virtuales solo puede configurarse durante la creación del grupo de nodos, pero puede actualizar la configuración del autoescalador en cualquier momento.

  1. Cree un espacio de nombres mediante el comando kubectl create namespace.

    kubectl create namespace gpu-resources
    
  2. Cree un archivo llamado nvidia-device-plugin-ds.yaml y pegue el siguiente manifiesto YAML proporcionado como parte del proyecto NVIDIA device plugin for Kubernetes:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: nvidia-device-plugin-daemonset
      namespace: gpu-resources
    spec:
      selector:
        matchLabels:
          name: nvidia-device-plugin-ds
      updateStrategy:
        type: RollingUpdate
      template:
        metadata:
          # 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.  This annotation works in tandem with the toleration below.
          annotations:
            scheduler.alpha.kubernetes.io/critical-pod: ""
          labels:
            name: nvidia-device-plugin-ds
        spec:
          tolerations:
          # Allow this pod to be rescheduled while the node is in "critical add-ons only" mode.
          # This, along with the annotation above marks this pod as a critical add-on.
          - key: CriticalAddonsOnly
            operator: Exists
          - key: nvidia.com/gpu
            operator: Exists
            effect: NoSchedule
          - key: "sku"
            operator: "Equal"
            value: "gpu"
            effect: "NoSchedule"
          containers:
          - image: mcr.microsoft.com/oss/nvidia/k8s-device-plugin:v0.14.1
            name: nvidia-device-plugin-ctr
            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
    
  3. Cree el DaemonSet y confirme que el plugin de dispositivos NVIDIA se ha creado correctamente mediante el comando kubectl apply.

    kubectl apply -f nvidia-device-plugin-ds.yaml
    
  4. Ahora que instaló correctamente el complemento de dispositivo NVIDIA, puede comprobar que las GPU son programables y ejecutan una carga de trabajo de GPU.

Uso del operador de GPU de NVIDIA con AKS

El operador de GPU de NVIDIA automatiza la administración de todos los componentes de software de NVIDIA necesarios para aprovisionar la GPU, incluida la instalación del controlador, el complemento de dispositivo NVIDIA para Kubernetes, el entorno de ejecución del contenedor NVIDIA, etc. Dado que el operador de GPU controla estos componentes, no es necesario instalar manualmente el complemento de dispositivo NVIDIA. Esto también significa que la instalación automática del controlador de GPU en AKS ya no es necesaria.

  1. Omita la instalación automática del controlador de GPU mediante la creación de un grupo de nodos mediante el comando az aks nodepool add con --skip-gpu-driver-install. Al agregar la marca --skip-gpu-driver-install durante la creación del grupo de nodos, se omite la instalación automática del controlador de GPU. No se cambian los nodos existentes. Puede escalar el grupo de nodos a cero y, a continuación, realizar una copia de seguridad para que el cambio surta efecto.

  2. Siga la documentación de NVIDIA para instalar el operador de GPU.

  3. Ahora que instaló correctamente el operador de GPU, puede comprobar que las GPU son programables y ejecutan una carga de trabajo de GPU.

Advertencia

No se recomienda instalar manualmente el conjunto de demonios del complemento de dispositivo NVIDIA con clústeres mediante la imagen de GPU de AKS.

Uso de la imagen de GPU de AKS (versión preliminar)

AKS proporciona una imagen AKS totalmente configurada que contiene el plugin de dispositivo NVIDIA para Kubernetes. La imagen de GPU de AKS solo se admite actualmente para Ubuntu 18.04.

Importante

Las características en versión preliminar de AKS están disponibles como opción de participación y autoservicio. Las versiones preliminares se proporcionan "tal cual" y "como están disponibles", y están excluidas de los Acuerdos de nivel de servicio y garantía limitada. Las versiones preliminares de AKS reciben cobertura parcial del soporte al cliente en la medida de lo posible. Por lo tanto, estas características no están diseñadas para su uso en producción. Para más información, consulte los siguientes artículos de soporte:

  1. Instale la extensión aks-preview Azure CLI mediante el comando az extension add.

    az extension add --name aks-preview
    
  2. Actualiza a la última versión de la extensión mediante el comando az extension update.

    az extension update --name aks-preview
    
  3. Registre la marca de características de GPUDedicatedVHDPreview mediante el comando az feature register.

    az feature register --namespace "Microsoft.ContainerService" --name "GPUDedicatedVHDPreview"
    

    Tarda unos minutos en que el estado muestre Registrado.

  4. Comprobar el estado del registro mediante el comando az feature show.

    az feature show --namespace "Microsoft.ContainerService" --name "GPUDedicatedVHDPreview"
    
  5. Cuando aparezca el estado Registrado, actualice el registro del proveedor de recursos Microsoft.ContainerService mediante el comando az provider register.

    az provider register --namespace Microsoft.ContainerService
    

    Ahora que actualizó su clúster para utilizar la imagen de GPU de AKS, puede agregar un grupo de nodos para nodos de GPU a su clúster.

  6. Agregue un grupo de nodos utilizando el comando 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
    

    El comando de ejemplo anterior agrega un grupo de nodos denominado gpunp a myAKSCluster en myResourceGroup y utiliza parámetros para configurar las siguientes opciones del grupo de nodos:

    • --node-vm-size: establece el tamaño de la máquina virtual para el nodo en el grupo de nodos en Standard_NC6s_v3.
    • --node-taints: especifica sku=gpu:NoSchedule en el grupo de nodos.
    • --aks-custom-headers: especifica una imagen de GPU AKS especializada, UseGPUDedicatedVHD=true. Si su SKU de GPU requiere máquinas virtuales de generación 2, utilice --aks-custom-headers UseGPUDedicatedVHD=true,usegen2vm=true en su lugar.
    • --enable-cluster-autoscaler: habilita el autoescalador del clúster.
    • --min-count: configura el autoescalador del clúster para mantener un mínimo de un nodo en el grupo de nodos.
    • --max-count: configura el autoescalador de clúster para mantener un máximo de tres nodos en el grupo de nodos.

    Nota:

    El tamaño de los nodos y de las máquinas virtuales solo puede configurarse durante la creación del grupo de nodos, pero puede actualizar la configuración del autoescalador en cualquier momento.

  7. Ahora que ha creado correctamente un grupo de nodos mediante la imagen de GPU, puede comprobar que las GPU son programables y ejecutan una carga de trabajo de GPU.

Confirmación de que las GPU son programables

Después de crear el clúster, confirme que las GPUs son programables en Kubernetes.

  1. Enumere los nodos de su clúster mediante el comando kubectl get nodes.

    kubectl get nodes
    

    El resultado debería ser similar al ejemplo siguiente:

    NAME                   STATUS   ROLES   AGE   VERSION
    aks-gpunp-28993262-0   Ready    agent   13m   v1.20.7
    
  2. Confirme que las GPU son programables mediante el comando kubectl describe node.

    kubectl describe node aks-gpunp-28993262-0
    

    En la sección Capacidad, la GPU debe aparecer como nvidia.com/gpu: 1. El resultado debería ser similar al siguiente ejemplo reducido:

    Name:               aks-gpunp-28993262-0
    Roles:              agent
    Labels:             accelerator=nvidia
    
    [...]
    
    Capacity:
    [...]
     nvidia.com/gpu:                 1
    [...]
    

Ejecución de una carga de trabajo habilitada para GPU

Para ver la GPU en acción, puede programar una carga de trabajo habilitada para GPU con la solicitud de recursos adecuada. En este ejemplo, ejecutaremos un trabajo Tensorflow con el conjunto de datos MNIST.

  1. Cree un archivo llamado samples-tf-mnist-demo.yaml y pegue el siguiente manifiesto YAML, que incluye un límite de recursos de nvidia.com/gpu: 1:

    Nota

    Si recibe un error de coincidencia de versión al llamar a los controladores, como, por ejemplo, que la versión del controlador CUDA no es suficiente para la versión en tiempo de ejecución de CUDA, revise el gráfico de compatibilidad de la matriz de controladores de 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.microsoft.com/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"
    
  2. Ejecute el trabajo mediante el comando kubectl apply, que analiza el archivo de manifiesto y crea los objetos de Kubernetes definidos.

    kubectl apply -f samples-tf-mnist-demo.yaml
    

Ver el estado de la carga de trabajo habilitada para GPU

  1. Supervisa el progreso del trabajo mediante el comando kubectl get jobs con el indicador --watch. Puede tardar unos minutos en extraer primero la imagen y procesar el conjunto de datos.

    kubectl get jobs samples-tf-mnist-demo --watch
    

    Cuando la columna FINALIZACIONES muestra 1/1, el trabajo ha finalizado correctamente, como se muestra en la salida de ejemplo siguiente:

    NAME                    COMPLETIONS   DURATION   AGE
    
    samples-tf-mnist-demo   0/1           3m29s      3m29s
    samples-tf-mnist-demo   1/1   3m10s   3m36s
    
  2. Salga del proceso kubectl --watch con Ctrl-C.

  3. Obtenga el nombre del pod mediante el comando kubectl get pods.

    kubectl get pods --selector app=samples-tf-mnist-demo
    
  4. Vea la salida de la carga de trabajo habilitada para GPU utilizando el comando kubectl logs.

    kubectl logs samples-tf-mnist-demo-smnr6
    

    l siguiente ejemplo de salida condensada de los registros del pod confirma que el dispositivo GPU apropiado, Tesla K80, ha sido descubierto:

    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
    

Uso de información de contenedores para supervisar el uso de GPU

Container Insights con AKS supervisa las siguientes métricas de uso de la GPU:

Nombre de métrica Dimensión de métrica (etiquetas) Descripción
containerGpuDutyCycle container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModel, gpuVendor Porcentaje de tiempo del período de muestra anterior (60 segundos) durante el cual la GPU estuvo ocupada o realizando un procesamiento activo para un contenedor. El ciclo de servicio es un número comprendido entre 1 y 100.
containerGpuLimits container.azm.ms/clusterId, container.azm.ms/clusterName, containerName Cada contenedor puede especificar límites para una o varias GPU. No es posible solicitar ni limitar una fracción de GPU.
containerGpuRequests container.azm.ms/clusterId, container.azm.ms/clusterName, containerName Cada contenedor puede solicitar una o varias GPU. No es posible solicitar ni limitar una fracción de GPU.
containerGpumemoryTotalBytes container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModel, gpuVendor Cantidad de memoria de GPU en bytes disponible para su uso en un contenedor específico.
containerGpumemoryUsedBytes container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModel, gpuVendor Cantidad de memoria de GPU en bytes que usa un contenedor específico.
nodeGpuAllocatable container.azm.ms/clusterId, container.azm.ms/clusterName, gpuVendor Número de GPU en un nodo que puede usar Kubernetes.
nodeGpuCapacity container.azm.ms/clusterId, container.azm.ms/clusterName, gpuVendor Número total de GPU en un nodo.

Limpieza de recursos

  • Elimine los objetos Kubernetes asociados que creó en este artículo mediante el comando kubectl delete job.

    kubectl delete jobs samples-tf-mnist-demo
    

Pasos siguientes