Mise à l’échelle automatique des charges de travail GPU sur AKS à l’aide des métriques DCGM et KEDA

Dans cet article, vous allez apprendre à mettre à l’échelle automatiquement des charges de travail GPU sur Azure Kubernetes Service (AKS) à l’aide de métriques GPU collectées par l’exportateur DCGM (NVIDIA Data Center GPU Manager). Ces métriques sont exposées via Azure Managed Prometheus et utilisées par Kubernetes Event-Driven Autoscaling (KEDA) pour mettre automatiquement à l’échelle les charges de travail en fonction de l’utilisation du GPU en temps réel. Cette solution permet d’optimiser l’utilisation des ressources GPU et de contrôler les coûts opérationnels en ajustant dynamiquement l’échelle de l’application en réponse à la demande de charge de travail.

Prerequisites

  • Azure CLI version 2.60.0 ou ultérieure. Exécutez az --version pour trouver la version. Si vous devez installer ou mettre à niveau, voir Installer Azure CLI.
  • Helm version 3.17.0 ou ultérieure installée.
  • kubectl version 1.28.9 ou ultérieure installée.
  • Quota GPU NVIDIA dans votre abonnement Azure. Cet exemple utilise la Standard_NC40ads_H100_v5 référence SKU, mais d’autres références SKU de machine virtuelle NVIDIA H100 sont également prises en charge.

Avant de continuer, vérifiez que votre cluster AKS est configuré avec les éléments suivants :

À ce stade, vous devez avoir :

Créer un nouvel outil de mise à l’échelle KEDA à l’aide des métriques de NVIDIA DCGM Exporter

Pour créer un scaler KEDA, vous avez besoin de deux composants :

  1. Le point de terminaison de requête de Prometheus.
  2. L’identité managée attribuée par l’utilisateur.

Récupérer le point de terminaison de requête d’Azure Managed Prometheus

  1. Vous trouverez cette valeur dans la section Vue d’ensemble de l’espace de travail Azure Monitor attaché à votre cluster AKS dans le portail Azure.

    Capture d’écran du point de terminaison de requête Managed Prometheus.

  2. Exportez le point de terminaison de requête Azure Prometheus managé vers une variable environnementale :

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

Récupérer l’identité managée affectée par l’utilisateur

L’identité managée affectée par l’utilisateur a été créée précédemment en suivant les étapes d’intégration KEDA. Si nécessaire, rechargez cette valeur avec la az identity show commande :

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

Créer le manifeste du scaler KEDA

Ce manifeste crée les TriggerAuthentication et ScaledObject pour la mise à l’échelle automatique basée sur l’utilisation du GPU mesurée par la métrique DCGM_FI_DEV_GPU_UTIL.

Note

Cet exemple utilise la métrique, qui mesure l’utilisation DCGM_FI_DEV_GPU_UTIL du GPU. D’autres métriques sont également disponibles auprès de l’exportateur DCGM en fonction des besoins de votre charge de travail. Pour obtenir la liste complète des métriques disponibles, consultez la documentation NVIDIA DCGM Exporter.

Champ Description
metricName Spécifie la métrique GPU à surveiller. DCGM_FI_DEV_GPU_UTIL signale le pourcentage de temps pendant laquelle le GPU traite activement les charges de travail. Cette valeur est généralement comprise entre 0 et 100.
query Requête PromQL qui calcule l’utilisation moyenne du GPU sur tous les pods du déploiement my-gpu-workload. Cela garantit que les décisions de mise à l’échelle sont basées sur l’utilisation globale du GPU, et non sur un seul pod.
threshold Pourcentage d’utilisation moyenne du GPU cible qui déclenche la mise à l’échelle. Si la moyenne dépasse 5 %, l’outil de mise à l’échelle augmente le nombre de répliques de pods.
activationThreshold Utilisation moyenne minimale du GPU nécessaire pour activer la mise à l’échelle. Si l’utilisation est inférieure à 2%, les actions de mise à l’échelle ne se produisent pas, ce qui empêche la mise à l’échelle inutile pendant les périodes de faible activité.
  1. Créez le manifeste KEDA suivant :

    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. Appliquez ce manifeste à l’aide de la kubectl apply commande :

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

Tester les nouvelles fonctionnalités de mise à l’échelle

  1. Créez un exemple de charge de travail qui consomme des ressources GPU dans votre cluster AKS. Vous pouvez commencer par l’exemple suivant :

    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. Appliquez ce manifeste de déploiement à l’aide de la kubectl apply commande :

    kubectl apply -f my-gpu-workload.yaml
    

    Note

    Si aucun nœud GPU n’est actuellement disponible, le pod reste dans un Pending état jusqu’à ce qu’un nœud soit approvisionné, affichant le message suivant :

    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.
    

    L’autoscaler de cluster démarre et provisionne un nouveau nœud GPU :

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

    Note

    En fonction de la taille de votre référence SKU GPU provisionnée, l’approvisionnement de nœuds peut prendre plusieurs minutes.

  3. Pour vérifier la progression, vérifiez les événements HPA (Horizontal Pod Autoscaler) à l’aide de la kubectl describe commande :

    kubectl describe hpa my-gpu-workload
    

    La sortie doit ressembler à ce qui suit :

    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. Vérifiez que le nœud GPU a été ajouté et que le pod est en cours d’exécution avec la kubectl get commande :

    kubectl get nodes
    

    La sortie doit ressembler à ce qui suit :

    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
    

Effectuer un scale-down du pool de nœuds GPU

Pour effectuer un scale-down du pool de nœuds GPU, supprimez votre déploiement de charge de travail à l’aide de la kubectl delete commande :

kubectl delete deployment my-gpu-workload

Note

Vous pouvez configurer le pool de nœuds pour effectuer un scale-down à zéro en activant l’autoscaler de cluster et en définissant la valeur min-count0 au moment de la création du pool de nœuds. Par exemple:

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

Étapes suivantes