Escalado automático de cargas de trabajo de GPU en AKS mediante métricas DCGM y KEDA

En este artículo, aprenderá a escalar automáticamente cargas de trabajo de GPU en Azure Kubernetes Service (AKS) mediante las métricas de GPU recopiladas por el exportador de NVIDIA Data Center GPU Manager (DCGM). Estas métricas se exponen a través de Azure Managed Prometheus y son consumidas por Kubernetes Event-Driven Autoscaling (KEDA) para escalar automáticamente las cargas de trabajo en función de la utilización de la GPU en tiempo real. Esta solución ayuda a optimizar el uso de recursos de GPU y a controlar los costos operativos ajustando dinámicamente la escala de la aplicación en respuesta a la demanda de cargas de trabajo.

Prerequisites

  • CLI de Azure versión 2.60.0 o posterior. Ejecute az --version para encontrar la versión. Si necesita instalar o actualizar, consulte Install CLI de Azure.
  • Helm versión 3.17.0 o posterior instalada.
  • kubectl versión 1.28.9 o posterior instalada.
  • Cuota de GPU de NVIDIA en la suscripción de Azure. En este ejemplo se usa la Standard_NC40ads_H100_v5 SKU, pero también se admiten otras SKU de máquina virtual nvidia H100.

Antes de continuar, asegúrese de que el clúster de AKS esté configurado con lo siguiente:

En este momento, debe tener:

Creación de un nuevo escalador KEDA mediante las métricas de NVIDIA DCGM Exporter

Para crear un escalador KEDA, necesita dos componentes:

  1. El punto de conexión para consultas de Prometheus.
  2. Identidad administrada asignada por el usuario.

Recuperar el punto de conexión de consulta de Prometheus administrado por Azure

  1. Puede encontrar este valor en la sección Información general del área de trabajo de Azure Monitor adjunta al clúster de AKS en el portal de Azure.

    Captura de pantalla del extremo de consulta de Managed Prometheus.

  2. Exporte el punto de conexión de consulta de Azure Managed Prometheus a una variable de entorno:

    export PROMETHEUS_QUERY_ENDPOINT="https://example.prometheus.monitor.azure.com"
    

Recuperación de la identidad administrada asignada por el usuario

La identidad administrada asignada por el usuario se creó anteriormente siguiendo los pasos de integración de KEDA. Si es necesario, vuelva a cargar este valor con el az identity show comando :

export USER_ASSIGNED_CLIENT_ID="$(az identity show --resource-group $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query 'clientId' -o tsv)"

Creación del manifiesto del escalador KEDA

Este manifiesto crea el TriggerAuthentication y el ScaledObject para el escalado automático en función de la utilización de la GPU medida por la métrica DCGM_FI_DEV_GPU_UTIL.

Note

En este ejemplo se usa la métrica , que mide el DCGM_FI_DEV_GPU_UTIL uso de GPU. También hay otras métricas disponibles a través del exportador DCGM, en función de los requisitos de la carga de trabajo. Para obtener una lista completa de las métricas disponibles, consulte la documentación de NVIDIA DCGM Exporter.

Campo Description
metricName Especifica la métrica de GPU que se va a supervisar. DCGM_FI_DEV_GPU_UTIL informa del porcentaje de tiempo que la GPU está procesando activamente las cargas de trabajo. Este valor suele oscilar entre 0 y 100.
query Consulta PromQL que calcula la utilización media de la GPU en todos los pods del despliegue my-gpu-workload. Esto garantiza que las decisiones de escalado se basen en el uso general de GPU, no en un solo pod.
threshold Porcentaje de uso medio de GPU de destino que desencadena el escalado. Si el promedio supera 5 %, el escalador aumenta el número de réplicas de pod.
activationThreshold El promedio mínimo de uso de GPU necesario para activar el escalado. Si el uso es inferior a 2%, no se producirán acciones de escalado, lo que impide el escalado innecesario durante períodos de actividad bajos.
  1. Cree el siguiente manifiesto de KEDA:

    cat <<EOF > keda-gpu-scaler-prometheus.yaml
    apiVersion: keda.sh/v1alpha1
    kind: TriggerAuthentication
    metadata:
      name: azure-managed-prometheus-trigger-auth
    spec:
      podIdentity:
        provider: azure-workload
        identityId: ${USER_ASSIGNED_CLIENT_ID}
    ---
    apiVersion: keda.sh/v1alpha1
    kind: ScaledObject
    metadata:
      name: my-gpu-workload
    spec:
      scaleTargetRef:
        name: my-gpu-workload
      minReplicaCount: 1
      maxReplicaCount: 20
      triggers:
        - type: prometheus
          metadata:
            serverAddress: ${PROMETHEUS_QUERY_ENDPOINT}
            metricName: DCGM_FI_DEV_GPU_UTIL
            query: avg(DCGM_FI_DEV_GPU_UTIL{deployment="my-gpu-workload"})
            threshold: '5'
            activationThreshold: '2'
          authenticationRef:
            name: azure-managed-prometheus-trigger-auth
    EOF
    
  2. Aplique este manifiesto mediante el kubectl apply comando :

    kubectl apply -f keda-gpu-scaler-prometheus.yaml
    

Prueba de las nuevas funcionalidades de escalado

  1. Cree una carga de trabajo de ejemplo que consuma recursos de GPU en el clúster de AKS. Puede empezar con el ejemplo siguiente:

    cat <<EOF > my-gpu-workload.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-gpu-workload
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-gpu-workload
      template:
        metadata:
          labels:
            app: my-gpu-workload
        spec:
          tolerations:
            - key: "sku"
              operator: "Equal"
              value: "gpu"
              effect: "NoSchedule"
          containers:
            - name: my-gpu-workload
              image: mcr.microsoft.com/azuredocs/samples-tf-mnist-demo:gpu
              command: ["/bin/sh"]
              args: ["-c", "while true; do python /app/main.py --max_steps=500; done"]
              resources:
                limits:
                  nvidia.com/gpu: 1
    EOF
    
  2. Aplique este manifiesto de implementación mediante el kubectl apply comando :

    kubectl apply -f my-gpu-workload.yaml
    

    Note

    Si no hay nodos de GPU disponibles actualmente, el pod permanecerá en un Pending estado hasta que se aprovisione un nodo, en el que se muestra el mensaje siguiente:

    Events:
      Type     Reason            Age    From                Message
      ----     ------            ----   ----                -------
      Warning  FailedScheduling  3m19s  default-scheduler   0/2 nodes are available: 2 Insufficient nvidia.com/gpu. preemption: 0/2 nodes are available: 2 No preemption victims found for incoming pod.
    

    El escalador automático del clúster se iniciará y aprovisionará un nuevo nodo de GPU:

    Normal   TriggeredScaleUp  2m43s  cluster-autoscaler  pod triggered scale-up: [{aks-gpunp-36854149-vmss 0->1 (max: 2)}]
    

    Note

    Según el tamaño de la SKU de GPU aprovisionada, el aprovisionamiento de nodos puede tardar varios minutos.

  3. Para comprobar el progreso, compruebe los eventos Horizontal Pod Autoscaler (HPA) mediante el kubectl describe comando :

    kubectl describe hpa my-gpu-workload
    

    La salida debe ser similar a la siguiente:

    Conditions:
      Type            Status  Reason            Message
      ----            ------  ------            -------
      AbleToScale     True    ReadyForNewScale  recommended size matches current size
      ScalingActive   True    ValidMetricFound  the HPA successfully calculated a replica count from external metric s0-prometheus(&LabelSelector{MatchLabels:map[string]string{scaledobject.keda.sh/name: my-gpu-workload}})
      ScalingLimited  True    TooFewReplicas    the desired replica count is less than the minimum replica count
    
  4. Confirme que se ha agregado el nodo de GPU y que el pod se está ejecutando con el kubectl get comando :

    kubectl get nodes
    

    La salida debe ser similar a la siguiente:

    NAME                                STATUS   ROLES    AGE     VERSION
    aks-gpunp-36854149-vmss000005       Ready    <none>   4m36s   v1.31.7
    aks-nodepool1-34179260-vmss000002   Ready    <none>   26h     v1.31.7
    aks-nodepool1-34179260-vmss000003   Ready    <none>   26h     v1.31.7
    

Reducir el grupo de nodos de GPU

Para reducir verticalmente el grupo de nodos de GPU, elimine la implementación de la carga de trabajo mediante el comando kubectl delete:

kubectl delete deployment my-gpu-workload

Note

Puede configurar el grupo de nodos para escalar hasta cero habilitando el escalador automático del clúster y estableciendo min-count en 0 al crear el grupo de nodos. Por ejemplo:

az aks nodepool add \
 --resource-group myResourceGroup \
 --cluster-name myAKSCluster \
 --name gpunp \
 --node-count 1 \
 --node-vm-size Standard_NC40ads_H100_v5 \
 --node-taints sku=gpu:NoSchedule \
 --enable-cluster-autoscaler \
 --min-count 0 \
 --max-count 3

Pasos siguientes