Usar GPUs para cargas de trabalho de computação intensiva no AKS (Serviço de Kubernetes do Azure)

As unidades de processamento gráfico (GPU) geralmente são usadas para cargas de trabalho de computação intensiva, tais como gráficos e cargas de trabalho de visualização. AKS dá suporte a pools de nós Linux habilitados para GPU para executar cargas de trabalho do Kubernetes com uso intensivo de computação.

Este artigo ajuda você a provisionar nós com GPUs programáveis em clusters do AKS novos e existentes.

VMs habilitadas para GPU com suporte

Para exibir VMs habilitadas para GPU com suporte, consulte tamanhos de VM com otimização de GPU no Azure. Para pools de nós do AKS, é recomendável um tamanho mínimo de Standard_NC6s_v3. A série NVv4 (baseada em GPUs AMD) não tem suporte no AKS.

Observação

As VMs habilitadas para GPU contêm hardware especializado sujeito a preços mais altos e disponibilidade da região. Para obter mais informações, confira a ferramenta preço e a disponibilidade de região.

Limitações

  • Se você estiver usando um pool de nós de habilitado para GPU do Linux do Azure, os patches de segurança automáticos não serão aplicados e o comportamento padrão para o cluster será Não gerenciado. Para obter mais informações, confira auto-upgrade.
  • A série NVadsA10 v5 não é uma SKU recomendada para VHD de GPU.
  • Não há suporte para a atualização de um pool de nós existente para adicionar GPU.

Antes de começar

  • Este artigo pressupõe que você tenha um cluster do AKS. Se você não tiver um cluster, crie um usando a CLI do Azure, Azure PowerShell, ou o portal do Azure.
  • Será necessária a CLI do Azure versão 2.0.64 ou posterior instalada e configurada. Execute az --version para encontrar a versão. Se você precisa instalar ou atualizar, consulte Instalar a CLI do Azure.

Obter as credenciais para o cluster

  • Obtenha as credenciais do cluster do AKS usando o comando az aks get-credentials. O seguinte comando de exemplo obtém as credenciais para o myAKSCluster no grupo de recursos myResourceGroup:

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

Opções para usar GPUs NVIDIA

O uso de GPUs NVIDIA envolve a instalação de vários componentes de software NVIDIA, como o plug-in de dispositivo NVIDIA para Kubernetes, instalação do driver de GPU e muito mais.

Ignorar a instalação do driver de GPU (versão prévia)

O AKS tem a instalação automática do driver de GPU habilitada por padrão. Em alguns casos, como instalar seus próprios drivers ou usar o Operador de GPU NVIDIA, convém ignorar a instalação do driver de GPU.

Importante

As versões prévias do recurso AKS estão disponíveis em uma base de autoatendimento e aceitação. As visualizações são fornecidas "como estão" e "conforme disponíveis" e estão excluídas dos acordos de nível de serviço e da garantia limitada. As versões prévias do AKS são parcialmente cobertas pelo suporte ao cliente em uma base de melhor esforço. Dessa forma, esses recursos não são destinados ao uso em produção. Para obter mais informações, consulte os seguintes artigos:

  1. Registre ou atualize a extensão aks-preview usando o comando az extension add ou 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. Crie um pool de nós usando o comando az aks nodepool add com o sinalizador --skip-gpu-driver-install para ignorar a instalação automática do driver 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
    

    Adicionar o sinalizador --skip-gpu-driver-install durante a criação do pool de nós ignora a instalação automática do driver de GPU. Os nós existentes não são alterados. Você pode dimensionar o pool de nós para zero e fazer backup para fazer a alteração entrar em vigor.

Instalação do plug-in do dispositivo NVIDIA

A instalação do plug-in de dispositivo NVIDIA é necessária ao usar GPUs no AKS. Em alguns casos, a instalação é tratada automaticamente, como ao usar o Operador de GPU NVIDIA ou a imagem de GPU do AKS (versão prévia). Como alternativa, você pode instalar manualmente o plug-in de dispositivo NVIDIA.

Instalar manualmente o plug-in do dispositivo NVIDIA

Você pode implantar um DaemonSet para o plug-in do dispositivo NVIDIA, que executa um pod em cada nó para fornecer os drivers necessários para as GPUs. Essa é a abordagem recomendada ao usar pools de nós habilitados para GPU para o Azure Linux.

Para usar o SKU do sistema operacional padrão, crie o pool de nós sem especificar um SKU do sistema operacional. O pool de nós está configurado para o sistema operacional padrão com base na versão do Kubernetes do cluster.

  1. Adicione um pool de nós ao seu cluster usando o 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
    

    O exemplo anterior de comando adiciona um pool de nós nomeado gpunp ao myAKSCluster em myResourceGroup e usa parâmetros para definir as seguintes configurações do pool de nós:

    • --node-vm-size: Define o tamanho da VM para o nó no pool de nós para Standard_NC6s_v3.
    • --node-taints: Especifica uma tonalidade sku=gpu:NoSchedule no pool de nós.
    • --enable-cluster-autoscaler: Habilita o dimensionador automático de cluster.
    • --min-count: Configura o dimensionador automático de cluster para manter um mínimo de um nó no pool de nós.
    • --max-count: Configura o dimensionador automático de cluster para manter um máximo de três nós no pool de nós.

    Observação

    Os tamanho e tonalidades de VMs só podem ser definidos para os pools de nós durante a criação do pool de nós, mas você pode atualizar as configurações do dimensionamento automático a qualquer momento.

  1. Crie um namespace usando o comando kubectl create namespace.

    kubectl create namespace gpu-resources
    
  2. Crie um arquivo nomeado nvidia-device-plugin-ds.yaml e cole o seguinte manifesto YAML fornecido como parte do plug-in do dispositivo NVIDIA para o projeto 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. Crie o DaemonSet e confirme se o plug-in do dispositivo NVIDIA é criado com sucesso usando o comando kubectl apply.

    kubectl apply -f nvidia-device-plugin-ds.yaml
    
  4. Agora que você instalou com êxito o plug-in de dispositivo NVIDIA, você pode verificar se suas GPUs são programáveis e executar uma carga de trabalho de GPU.

Usar o operador de GPU NVIDIA com AKS

O Operador de GPU NVIDIA automatiza o gerenciamento de todos os componentes de software NVIDIA necessários para provisionar a GPU, incluindo a instalação do driver, o plug-in de dispositivo NVIDIA para Kubernetes, o runtime de contêiner NVIDIA e muito mais. Como o Operador de GPU manipula esses componentes, não é necessário instalar manualmente o plug-in do dispositivo NVIDIA. Isso também significa que a instalação automática do driver de GPU no AKS não é mais necessária.

  1. Ignore a instalação automática do driver de GPU criando um pool de nós usando o comando az aks nodepool add com --skip-gpu-driver-install. Adicionar o sinalizador --skip-gpu-driver-install durante a criação do pool de nós ignora a instalação automática do driver de GPU. Os nós existentes não são alterados. Você pode dimensionar o pool de nós para zero e fazer backup para fazer a alteração entrar em vigor.

  2. Siga a documentação da NVIDIA para instalar o operador de GPU.

  3. Agora que você instalou com êxito o Operador GPU, você pode verificar se suas GPUs são programáveis e executar uma carga de trabalho de GPU.

Aviso

Não recomendamos instalar manualmente o conjunto de daemon plug-in de dispositivos NVIDIA com clusters usando a imagem de AKS GPU.

Usar a imagem de GPU do AKS (versão prévia)

AKS fornece uma imagem de AKS totalmente configurada contendo o plug-in de dispositivos NVIDIA para Kubernetes. Atualmente, a imagem de GPU do AKS só tem suporte para o Ubuntu 18.04.

Importante

As versões prévias do recurso AKS estão disponíveis em uma base de autoatendimento e aceitação. As visualizações são fornecidas "como estão" e "conforme disponíveis" e estão excluídas dos acordos de nível de serviço e da garantia limitada. As versões prévias do AKS são parcialmente cobertas pelo suporte ao cliente em uma base de melhor esforço. Dessa forma, esses recursos não são destinados ao uso em produção. Para obter mais informações, consulte os seguintes artigos:

  1. Instale a extensão aks-preview da CLI do Azure usando o comando az extension add.

    az extension add --name aks-preview
    
  2. Atualize para a última versão da extensão usando o comando az extension update.

    az extension update --name aks-preview
    
  3. Registre o sinalizador de recurso GPUDedicatedVHDPreview usando o comando az feature register.

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

    Demora alguns minutos para o status exibir Registrado.

  4. Verifique o status do registro usando o comando az feature show.

    az feature show --namespace "Microsoft.ContainerService" --name "GPUDedicatedVHDPreview"
    
  5. Quando o status reflete Registrado, atualize o registro do provedor de recursos Microsoft.ContainerService usando o comando az provider register.

    az provider register --namespace Microsoft.ContainerService
    

    Agora que você atualizou seu cluster para usar a imagem de AKS GPU, você pode adicionar um pool de nós para nós GPU ao seu cluster.

  6. Adicione um pool de nós usando o 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
    

    O exemplo anterior de comando adiciona um pool de nós nomeado gpunp ao myAKSCluster em myResourceGroup e usa parâmetros para definir as seguintes configurações do pool de nós:

    • --node-vm-size: Define o tamanho da VM para o nó no pool de nós para Standard_NC6s_v3.
    • --node-taints: Especifica uma tonalidade sku=gpu:NoSchedule no pool de nós.
    • --aks-custom-headers: Especifica uma imagem de AKS GPU especializada, UseGPUDedicatedVHD=true. Se o SKU de sua GPU exigir a VMs geração 2, use --aks-custom-headers UseGPUDedicatedVHD=true,usegen2vm=true em seu lugar.
    • --enable-cluster-autoscaler: Habilita o dimensionador automático de cluster.
    • --min-count: Configura o dimensionador automático de cluster para manter um mínimo de um nó no pool de nós.
    • --max-count: Configura o dimensionador automático de cluster para manter um máximo de três nós no pool de nós.

    Observação

    Os tamanho e tonalidades de VMs só podem ser definidos para os pools de nós durante a criação do pool de nós, mas você pode atualizar as configurações do dimensionamento automático a qualquer momento.

  7. Agora que você criou com êxito um pool de nós usando a imagem de GPU, você pode verificar se suas GPUs são programáveis e executar uma carga de trabalho de GPU.

Confirmar se as GPUs são agendáveis

Após criar seu cluster, confirme que as GPUs são agendáveis no Kubernetes.

  1. Listar os nós em seu cluster usando o comando kubectl get nodes.

    kubectl get nodes
    

    Seu resultado deve ser semelhante ao seguinte exemplo de saída:

    NAME                   STATUS   ROLES   AGE   VERSION
    aks-gpunp-28993262-0   Ready    agent   13m   v1.20.7
    
  2. Confirme se as GPUs são agendáveis usando o comando kubectl describe node.

    kubectl describe node aks-gpunp-28993262-0
    

    Na seção Capacidade, a GPU deve ser listada como nvidia.com/gpu: 1. Seu resultado deve ser semelhante ao seguinte exemplo de saída condensado:

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

Executar uma carga de trabalho habilitada para GPU

Para ver a GPU em ação, você pode agendar uma carga de trabalho habilitada para GPU com a solicitação de recurso adequada. Neste exemplo, vamos executar um trabalho do Tensorflow contra o conjunto de dados do MNIST.

  1. Crie um arquivo nomeado samples-tf-mnist-demo.yaml e cole o seguinte manifesto YAML, que inclui um limite de recursos de nvidia.com/gpu: 1:

    Observação

    Se você receber um erro de incompatibilidade de versão durante uma chamada de drivers, como “A versão do driver CUDA é insuficiente para a versão de runtime CUDA”, examine o gráfico de compatibilidade da matriz de drivers 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. Execute o trabalho usando o comando kubectl apply, que analisa o arquivo de manifesto e cria os objetos definidos do Kubernetes.

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

Exibir o status da carga de trabalho habilitada para GPU

  1. Monitore o andamento do trabalho usando o comando kubectl get jobs com o sinalizador --watch. Poderá levar alguns minutos para efetuar pull da imagem e processar o conjunto de dados pela primeira vez.

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

    Quando a coluna COMPLETIONS mostra 1/1, o trabalho foi concluído com sucesso, conforme mostrado no exemplo de saída a seguir:

    NAME                    COMPLETIONS   DURATION   AGE
    
    samples-tf-mnist-demo   0/1           3m29s      3m29s
    samples-tf-mnist-demo   1/1   3m10s   3m36s
    
  2. Saia do processo kubectl --watch com Ctrl-C.

  3. Obtenha o nome do pod usando o comando kubectl get pods.

    kubectl get pods --selector app=samples-tf-mnist-demo
    
  4. Exiba a saída da carga de trabalho habilitada para GPU usando o comando kubectl logs.

    kubectl logs samples-tf-mnist-demo-smnr6
    

    O seguinte exemplo condensado de saída dos logs de pod confirma que o dispositivo GPU apropriado, Tesla K80, foi descoberto:

    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
    

Usar o Container Insights para monitorar o uso da GPU

Container Insights com AKS monitora as seguintes métricas de uso da GPU:

Nome da métrica Dimensão métrica (marcas) Descrição
containerGpuDutyCycle container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModel, gpuVendor Percentual de tempo sobre o período amostral passado (60 segundos) durante o qual a GPU estava ocupada/em processamento ativo para um contêiner. O ciclo de serviço é um número entre 1 e 100.
containerGpuLimits container.azm.ms/clusterId, container.azm.ms/clusterName, containerName Cada contêiner pode especificar limites como uma ou mais GPUs. Não é possível solicitar nem limitar uma fração de uma GPU.
containerGpuRequests container.azm.ms/clusterId, container.azm.ms/clusterName, containerName Cada contêiner pode solicitar uma ou mais GPUs. Não é possível solicitar nem limitar uma fração de uma GPU.
containerGpumemoryTotalBytes container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModel, gpuVendor Quantidade de memória de GPU, em bytes, disponível para uso em um contêiner específico.
containerGpumemoryUsedBytes container.azm.ms/clusterId, container.azm.ms/clusterName, containerName, gpuId, gpuModel, gpuVendor Quantidade de memória de GPU, em bytes, usada por um contêiner específico.
nodeGpuAllocatable container.azm.ms/clusterId, container.azm.ms/clusterName, gpuVendor Número de GPUs em um nó que pode ser usado pelo Kubernetes.
nodeGpuCapacity container.azm.ms/clusterId, container.azm.ms/clusterName, gpuVendor Número total de GPUs em um nó.

Limpar recursos

  • Remova os objetos do Kubernetes associados que você criou neste artigo usando o comando kubectl delete job.

    kubectl delete jobs samples-tf-mnist-demo
    

Próximas etapas