Usare le GPU per carichi di lavoro a elevato utilizzo di calcolo nel servizio Azure Kubernetes

Le unità di elaborazione grafica (GPU) sono spesso usate per carichi di lavoro a elevato utilizzo di calcolo, ad esempio i carichi di lavoro di visualizzazione o di grafica. Il servizio Azure Kubernetes supporta pool di nodi Linux abilitati per GPU per eseguire carichi di lavoro Kubernetes a elevato utilizzo di calcolo.

Questo articolo illustra come effettuare il provisioning dei nodi con GPU pianificabili in cluster del servizio Azure Kubernetes nuovi ed esistenti.

Macchine virtuali abilitate per GPU supportate

Per visualizzare le macchine virtuali abilitate per GPU supportate, vedere Dimensioni delle macchine virtuali ottimizzate per la GPU in Azure. Per i pool del nodo del servizio Azure Kubernetes è consigliabile una dimensione minima di Standard_NC6s_v3. La serie NVv4 (basata sulle GPU AMD) non è supportata nel servizio Azure Kubernetes.

Nota

Le macchine virtuali abilitate per la GPU contengono hardware specializzato soggetto a prezzi maggiori e alla disponibilità regionale. Per altre informazioni, vedere il calcolatore dei prezzi e la disponibilità a livello di area.

Limiti

  • Se si usa un pool di nodi abilitato per GPU Linux di Azure, le patch di sicurezza automatiche non vengono applicate e il comportamento predefinito per il cluster è Non gestito. Per altre informazioni, vedere Aggiornamento automatico.
  • La serie NVadsA10 v5 non è uno SKU consigliato per il disco rigido virtuale GPU.
  • L'aggiornamento di un pool di nodi esistente per aggiungere GPU non è supportato.

Operazioni preliminari

Ottenere le credenziali per il cluster

  • Ottenere le credenziali per il cluster del servizio Azure Kubernetes usando il comando az aks get-credentials. Il comando di esempio seguente ottiene le credenziali per myAKSCluster nel gruppo di risorse myResourceGroup:

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

Opzioni per l'uso di GPU NVIDIA

L'uso di GPU NVIDIA prevede l'installazione di vari componenti software NVIDIA, ad esempio il plug-in del dispositivo NVIDIA per Kubernetes, l'installazione del driver GPU e altro ancora.

Ignorare l'installazione del driver GPU (anteprima)

Il servizio Azure Kubernetes ha l'installazione automatica del driver GPU abilitata per impostazione predefinita. In alcuni casi, ad esempio l'installazione di driver personalizzati o l'uso dell'operatore GPU NVIDIA, è possibile ignorare l'installazione del driver GPU.

Importante

Le funzionalità di anteprima del servizio Azure Kubernetes sono disponibili in modalità self-service e di consenso esplicito. Le anteprime vengono fornite “così come sono” e ”come disponibili” e sono escluse dai contratti di servizio e dalla garanzia limitata. Le anteprime del servizio Azure Kubernetes sono parzialmente coperte dal supporto clienti con la massima diligenza possibile. Di conseguenza, queste funzionalità non sono destinate all'uso in produzione. Per altre informazioni, vedere gli articoli di supporto seguenti:

  1. Registrare o aggiornare l'estensione aks-preview usando il 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. Creare un pool di nodi usando il comando az aks nodepool add con il flag --skip-gpu-driver-install per ignorare l'installazione automatica del driver 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
    

    L'aggiunta del flag --skip-gpu-driver-install durante la creazione del pool di nodi ignora l'installazione automatica del driver GPU. Tutti i nodi esistenti non vengono modificati. È possibile ridimensionare il pool di nodi a zero e quindi eseguire il backup per rendere effettiva la modifica.

Installazione del plug-in del dispositivo NVIDIA

L'installazione del plug-in del dispositivo NVIDIA è necessaria quando si usano GPU nel servizio Azure Kubernetes. In alcuni casi, l'installazione viene gestita automaticamente, ad esempio quando si usa l'operatore GPU NVIDIA o l'immagine GPU del servizio Azure Kubernetes (anteprima). In alternativa, è possibile installare manualmente il plug-in del dispositivo NVIDIA.

Installare manualmente il plug-in del dispositivo NVIDIA

È possibile distribuire un DaemonSet per il plug-in del dispositivo NVIDIA, che esegue un pod in ogni nodo per fornire i driver necessari per le GPU. Questo è l'approccio consigliato quando si usano pool di nodi abilitati per GPU per Azure Linux.

Per utilizzare la SKU OS predefinita, creare il pool di nodi senza specificare una SKU OS. Il pool di nodi è configurato per il sistema operativo predefinito in base alla versione Kubernetes del cluster.

  1. Aggiungere un pool di nodi al cluster usando il 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
    

    Questo comando aggiunge un pool di nodi denominato gpunp a myAKSCluster in myResourceGroup e usa i parametri per configurare le impostazioni del pool di nodi seguenti:

    • --node-vm-size: imposta le dimensioni della macchina virtuale per il nodo nel pool di nodi su Standard_NC6s_v3.
    • --node-taints: specifica un taint sku=gpu:NoSchedule nel pool di nodi.
    • --enable-cluster-autoscaler: abilita il ridimensionamento automatico del cluster.
    • --min-count: configura il ridimensionamento automatico del cluster per mantenere almeno un nodo nel pool di nodi.
    • --max-count: configura il ridimensionamento automatico del cluster per mantenere un massimo di tre nodi nel pool di nodi.

    Nota

    Le dimensioni di Taints e VM possono essere impostate solo per i pool di nodi durante la creazione del pool di nodi, ma è possibile aggiornare le impostazioni di scalabilità automatica in qualsiasi momento.

  1. Creare uno spazio dei nomi usando il comando kubectl create namespace.

    kubectl create namespace gpu-resources
    
  2. Creare un file denominato nvidia-device-plugin-ds.yaml e incollare il manifesto YAML seguente fornito come parte del progetto 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. Creare il DaemonSet e verificare che il plug-in del dispositivo NVIDIA sia stato creato correttamente usando il comando kubectl apply.

    kubectl apply -f nvidia-device-plugin-ds.yaml
    
  4. Dopo aver installato correttamente il plug-in del dispositivo NVIDIA, è possibile verificare che le GPU siano pianificabili ed eseguano un carico di lavoro GPU.

Usare l'operatore GPU NVIDIA con il servizio Azure Kubernetes

L'operatore GPU NVIDIA automatizza la gestione di tutti i componenti software NVIDIA necessari per effettuare il provisioning della GPU, tra cui l'installazione del driver, il plug-in del dispositivo NVIDIA per Kubernetes, il runtime del contenitore NVIDIA e altro ancora. Poiché l'operatore GPU gestisce questi componenti, non è necessario installare manualmente il plug-in del dispositivo NVIDIA. Ciò significa anche che l'installazione automatica del driver GPU nel servizio Azure Kubernetes non è più necessaria.

  1. Ignorare l'installazione automatica del driver GPU creando un pool di nodi usando il comando az aks nodepool add con --skip-gpu-driver-install. L'aggiunta del flag --skip-gpu-driver-install durante la creazione del pool di nodi ignora l'installazione automatica del driver GPU. Tutti i nodi esistenti non vengono modificati. È possibile ridimensionare il pool di nodi a zero e quindi eseguire il backup per rendere effettiva la modifica.

  2. Seguire la documentazione NVIDIA per installare l'operatore GPU.

  3. Dopo aver installato correttamente l'operatore GPU, è possibile verificare che le GPU siano pianificabili ed eseguano un carico di lavoro GPU.

Avviso

Non è consigliabile installare manualmente il set di daemon del plug-in del dispositivo NVIDIA con i cluster usando l'immagine GPU del servizio Azure Kubernetes.

Usare l'immagine GPU del servizio Azure Kubernetes (anteprima)

Il servizio Azure Kubernetes fornisce un'immagine del servizio Azure Kubernetes completamente configurata contenente il plug-in del dispositivo NVIDIA per Kubernetes. L'immagine GPU del servizio Azure Kubernetes è attualmente supportata solo per Ubuntu 18.04.

Importante

Le funzionalità di anteprima del servizio Azure Kubernetes sono disponibili in modalità self-service e di consenso esplicito. Le anteprime vengono fornite “così come sono” e ”come disponibili” e sono escluse dai contratti di servizio e dalla garanzia limitata. Le anteprime del servizio Azure Kubernetes sono parzialmente coperte dal supporto clienti con la massima diligenza possibile. Di conseguenza, queste funzionalità non sono destinate all'uso in produzione. Per altre informazioni, vedere gli articoli di supporto seguenti:

  1. Installare l'aks-previewestensione dell'interfaccia della riga di comando di Azure usando il comando az extension add.

    az extension add --name aks-preview
    
  2. Aggiornare alla versione più recente dell'estensione usando il comando az extension update.

    az extension update --name aks-preview
    
  3. Registrare il flag di funzionalità GPUDedicatedVHDPreview usando il comando az feature register.

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

    Sono necessari alcuni minuti per visualizzare lo stato Registered.

  4. Verificare lo stato della registrazione usando il comando az feature show.

    az feature show --namespace "Microsoft.ContainerService" --name "GPUDedicatedVHDPreview"
    
  5. Quando lo stato diventa Registrato, aggiornare la registrazione del provider di risorse Microsoft.ContainerService usando il comando az provider register.

    az provider register --namespace Microsoft.ContainerService
    

    Dopo aver aggiornato il cluster per usare l'immagine GPU del servizio Azure Kubernetes, è possibile aggiungere un pool di nodi per i nodi GPU al cluster.

  6. Creare un pool di nodi usando il 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
    

    Il comando di esempio precedente aggiunge un pool di nodi denominato gpunp a myAKSCluster in myResourceGroup e usa i parametri per configurare le impostazioni del pool di nodi seguenti:

    • --node-vm-size: imposta le dimensioni della macchina virtuale per il nodo nel pool di nodi su Standard_NC6s_v3.
    • --node-taints: specifica un taint sku=gpu:NoSchedule nel pool di nodi.
    • --aks-custom-headers: specifica un'immagine GPU del servizio Azure Kubernetes specializzata, UseGPUDedicatedVHD=true. Se lo SKU gpu richiede macchine virtuali di seconda generazione, usare invece --aks-custom-headers UseGPUDedicatedVHD=true,usegen2vm=true .
    • --enable-cluster-autoscaler: abilita il ridimensionamento automatico del cluster.
    • --min-count: configura il ridimensionamento automatico del cluster per mantenere almeno un nodo nel pool di nodi.
    • --max-count: configura il ridimensionamento automatico del cluster per mantenere un massimo di tre nodi nel pool di nodi.

    Nota

    Le dimensioni di Taints e VM possono essere impostate solo per i pool di nodi durante la creazione del pool di nodi, ma è possibile aggiornare le impostazioni di scalabilità automatica in qualsiasi momento.

  7. Dopo aver creato correttamente un pool di nodi usando l'immagine GPU, è possibile verificare che le GPU siano pianificabili ed eseguano un carico di lavoro GPU.

Verificare che le GPU siano pianificabili

Dopo aver creato il cluster, verificare che le GPU siano pianificabili in Kubernetes.

  1. Elencare i nodi nel cluster usando il comando kubectl get nodes.

    kubectl get nodes
    

    L'output dovrebbe essere simile all'esempio di output seguente:

    NAME                   STATUS   ROLES   AGE   VERSION
    aks-gpunp-28993262-0   Ready    agent   13m   v1.20.7
    
  2. Verificare che le GPU siano pianificabili usando il comando kubectl describe node.

    kubectl describe node aks-gpunp-28993262-0
    

    Nella sezione Capacity (Capacità) la GPU deve comparire in elenco come nvidia.com/gpu: 1. L'output dovrebbe essere simile all'output di esempio condensato seguente:

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

Eseguire un carico di lavoro abilitato per la GPU

Per vedere la GPU in esecuzione, pianificare un carico di lavoro abilitato per la GPU con la richiesta di risorse appropriata. In questo esempio viene eseguito il processo Tensorflow rispetto al set di dati MNIST.

  1. Creare un file denominato samples-tf-mnist-demo.yaml e incollare il manifesto YAML seguente, che include un limite di risorse di nvidia.com/gpu: 1:

    Nota

    Se si riceve un errore di mancata corrispondenza tra versioni quando si chiamano i driver, ad esempio quando la versione del driver CUDA non è sufficiente per la versione di runtime CUDA, esaminare il grafico di compatibilità di matrice di driver 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. Eseguire il processo usando il comando kubectl apply, che analizza il file manifesto e crea gli oggetti Kubernetes definiti.

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

Visualizzare lo stato del carico di lavoro abilitato per la GPU

  1. Monitorare lo stato di avanzamento del processo usando il comando kubectl get jobs con il flag --watch. L'esecuzione del pull dell'immagine come prima cosa e l'elaborazione del set di dati possono richiedere alcuni minuti.

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

    Quando la colonna COMPLETIONS mostra 1/1, il processo è stato completato correttamente, come illustrato nell'output di esempio seguente:

    NAME                    COMPLETIONS   DURATION   AGE
    
    samples-tf-mnist-demo   0/1           3m29s      3m29s
    samples-tf-mnist-demo   1/1   3m10s   3m36s
    
  2. Uscire dal processo kubectl --watch con CTRL-C.

  3. Ottenere il nome del pod usando il comando kubectl get pods.

    kubectl get pods --selector app=samples-tf-mnist-demo
    
  4. Visualizzare l'output del carico di lavoro abilitato per la GPU usando il comando kubectl logs.

    kubectl logs samples-tf-mnist-demo-smnr6
    

    L'output di esempio condensato seguente dei log dei pod conferma che il dispositivo GPU appropriato, Tesla K80, è stato individuato:

    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
    

Usare Informazioni dettagliate sul contenitore per monitorare l'utilizzo della GPU

Informazioni dettagliate sui contenitori con servizio Azure Kubernetes monitora le metriche di utilizzo della GPU seguenti:

Nome metrica Dimensione metrica (tag) Descrizione
containerGpuDutyCycle container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModelgpuVendor Percentuale di tempo nel periodo di campionamento precedente (60 secondi) durante il quale la GPU è stata occupata/attivamente l'elaborazione per un contenitore. Il ciclo di servizio è un numero compreso tra 1 e 100.
containerGpuLimits container.azm.ms/clusterId, container.azm.ms/clusterName, containerName Ogni contenitore può specificare limiti come una o più GPU. Non è possibile richiedere o limitare una frazione di una GPU.
containerGpuRequests container.azm.ms/clusterId, container.azm.ms/clusterName, containerName Ogni contenitore può richiedere una o più GPU. Non è possibile richiedere o limitare una frazione di una GPU.
containerGpumemoryTotalBytes container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModelgpuVendor Quantità di memoria GPU in byte disponibili per l'uso per un contenitore specifico.
containerGpumemoryUsedBytes container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModelgpuVendor Quantità di memoria GPU in byte usati da un contenitore specifico.
nodeGpuAllocatable container.azm.ms/clusterId, container.azm.ms/clusterName, gpuVendor Numero di GPU in un nodo che può essere usato da Kubernetes.
nodeGpuCapacity container.azm.ms/clusterId, container.azm.ms/clusterName, gpuVendor Numero totale di GPU in un nodo.

Pulire le risorse

  • Rimuovere gli oggetti Kubernetes associati creati in questo articolo usando il comando kubectl delete job.

    kubectl delete jobs samples-tf-mnist-demo
    

Passaggi successivi