Surmonter les défis de déploiement des GPUs H100 dans Azure Kubernetes Service

21 Décembre 2023 • 6 min

Dans l’écosystème dynamique du cloud computing, les GPU NVIDIA H100 se démarquent par leurs performances exceptionnelles, impulsant des progrès significatifs dans l'IA et le calcul intensif. Disponibles récemment chez la plupart des fournisseurs de cloud, notamment Azure, nous avons eu l’occasion de les intégrer au sein d’un cluster Azure Kubernetes Service (AKS) pour un acteur important de l'IA Générative (LLM).

Notre plan initial de déploiement, fonctionnel avec la génération A100, n’a jamais abouti à un cluster opérationnel. Nous avons fait face à un problème lors du démarrage d’instances de type Standard_ND96isr_H100_v5 (des instances intégrant 8 GPUs H100 de NVIDIA) sur Ubuntu 22.04, au sein d’un cluster Kubernetes 1.27.7.

On partage donc l’expérience avec vous !

Problématique

Nous utilisons la fonctionnalité de Nodepool afin d’augmenter la capacité du cluster Kubernetes à la demande. Les Nodepools d’AKS s’appuient sur les Virtual Machine Scale Sets (VMSS), qui eux-même décident de lancer des instances supplémentaires ou bien d’en retirer.

Une fois le tout configuré, nous n’avons toutefois jamais réussi à obtenir une instance dans un état correct, encore moins détectée en tant que nœud dans l’API Kubernetes. L’instanciation d’une nouvelle machine virtuelle avec des GPUs H100 ne se termine tout simplement jamais avec succès.

En creusant un peu, nous avons noté qu'un fichier manque à l’appel lors de l’initialisation des GPUs : /usr/share/nvidia/nvswitch/dgxh100_hgxh100_topology. Ce fichier manquant met en défaut le service systemd nvidia-fabric-manager, ce qui empêche l’initialisation complète de l’instance. Elle n’est ainsi jamais associée en tant que Node dans l’API Kubernetes.

Si on pousse l’analyse, on remarque que les images préparées par Azure pour AKS contiennent une installation simplifiée des drivers GPU (en version 525.85.12 à ce jour). Ce n’est pas illogique quand on connaît la taille démesurée des installations complètes NVIDIA, et que d’un autre côté, tout le monde n’utilise pas de GPU sur AKS.

Dommage donc, car là où fonctionnent les A100, les H100 trépassent !

La solution Quick Hack

Afin de débloquer rapidement la situation, nous avons essayé d’agir (manuellement) juste après le démarrage d’une instance … en insérant le fichier manquant, tout simplement !

Spoiler alert : le reste de l’initialisation se comporte correctement et les nœuds Kubernetes apparaissent enfin.

Voici un exemple de la magouille en question :

TMP_NVIDIA=$(mktemp -d)
(
  cd $TMP_NVIDIA
  curl -s -o nvidia-fabricmanager.deb http://azure.archive.ubuntu.com/ubuntu/pool/multiverse/f/fabric-manager-525/nvidia-fabricmanager-525_525.147.05-0ubuntu0.22.04.1_amd64.deb
  ar -x nvidia-fabricmanager.deb data.tar.zst
  tar xf data.tar.zst -C / ./usr/share/nvidia/nvswitch/dgxh100_hgxh100_topology
)
rm -Rf $TMP_NVIDIA

Alors, vous noterez tout de suite qu’on utilise une version différente du driver dont on extrait le fichier … Pas le choix, les registres de paquets Ubuntu configurés sur la machine n’ont pas de correspondance exacte.

Mais on a vérifié (via checksum) que le fichier était, lui, identique entre les versions.

Pas automatisable

Même si il serait aisé d’adapter une image ou bien de customiser son démarrage via les Extensions Custom script, il n’est malheureusement pas possible d’influer sur les images utilisée par AKS. Les réglages sont très limités.

La solution suggérée par Azure

Nous avons donc sollicité notre contact chez Azure afin de trouver une solution.

La stratégie retenue provient d’un article un peu paumé concernant les A100 mais qui indique tout de même certaines spécificités relatives au H100. Bref, il est vite apparu qu’il fallait débrayer le fonctionnement par défaut, pour installer le driver NVIDIA dans un second temps.

Debrayer l’installation par défaut

Avant tout, il faut désactiver le comportement par défaut qui installe les drivers lors du démarrage des instances.

Cela se fait à l’aide du tag SkipGPUDriverInstall.

az aks nodepool add \
  --resource-group <AKS_RG> --cluster-name <AKS_NAME> \
  --name <NODEPOOL_NAME> --node-count 1 \
  --os-sku Ubuntu --node-osdisk-size 128 \
  --node-vm-size Standard_ND96isr_H100_v5 \
  --tags SkipGPUDriverInstall=true

Le gpu-operator de NVIDIA

Il s’agît d’un opérateur Kubernetes comme il en existe bien d’autre pour gérer des tâches complexes sur Kubernetes.

En très bref, une fois un nouveau nœud ajouté dans Kubernetes, l’opérateur va successivement :

  • détecter de potentielles cartes installées sur ce nœud
  • détecter la présence ou non de drivers NVIDIA
  • en installer une version récente si ce n’est pas le cas
  • paramétrer un paquet de configurations diverses

Tout ceci en passant par de multiples boucles de réconciliation et autres ajouts de labels sur les nœuds.

Il faut admettre que ce système complexe est intéressant à observer, tant il semble compliqué au premier coup d’oeil.

Bon alors c’est bien tout ça … et ça a l’air de marcher en plus !

Incompatibilité des versions

Mais ils sont où mes 8 GPUs par instance ???

status:
  allocatable:
    nvidia.com/gpu: "5"

Rien n’y fait, et nvidia-smi confirme le comportement ératique : en fonction de l’instance, on obtient 5 6 ou 7 GPUs mais jamais les 8 physiquement présents.

Le coupable est le fameux opérateur qui, dans sa mouture 23.9.0, installe les drivers 535.104.12. Nous n’avons d’ailleurs pas eu plus de succès avec la version 535.129.03. Et plutôt que de perdre du temps à en investiguer la raison, nous sommes donc repassés sur un gpu-operator 23.6.1 en forcant la version 535.86.10.

Et là tout va bien.

Ou presque …

Temps de boot

L’utilisation du gpu-operator induit une perte de temps conséquente avant de pouvoir rendre un nœud Kubernetes utile. Certaines tâches prennent un bon paquet de temps (par ordre décroissant) :

  • Compilation du driver
  • Téléchargement du driver
  • Téléchargement des images de conteneurs impliquées (il y en a en masse)
  • Détection hardware sur les nœuds
  • Reconfiguration de containerd avec ajout du support des gpu

C’est dommage quand on connait le coût de ce genre d’équipement à la minute. Mais c’est encore plus regrettable quand on souhaite profiter du cluster autoscaler qui réagit très mal au fait que les pods ne sont pas schedulés rapidement sur le nœud. Précisément, les ressources nvidia.com/gpu associées au nœud n’apparaissent qu’une fois le process terminé, après 6 bonnes minutes !

Ah l’autoscaling, tout un sujet … qui mérite son propre blogpost :)

Drivers précompilés

Dans certains cas, le gpu-operator profite de la disponibilité de drivers précompilés pour votre instance afin d’accélérer le processus. La liste est disponible ici, malheusement on ne peut choisir que la version majeure, ex : 535-5.15.0-1053-azure-ubuntu22.04

Conclusion

En conclusion la situation est plutôt scabreuse à l’heure actuelle.

Nous espérons que les équipes d’Azure pourront intégrer une version corrigée (mais pas forcément plus récente) des drivers dans leur image de base. Cela permettra d’obtenir des nœuds avec GPU H100 dans un cluster AKS rapidement, et sans installation d’un système compliqué. Ou bien qu’ils permettront de modifier plus finement les réglages des instances lancées par AKS.

J’en profite pour remercier Aurélien, Thibault et Romain, mes “Monkey” collègues chez Enix. Ils ont retroussé leur manches comme jamais pour tenir des délais courts.

Je remercie également notre contact chez Azure, qui se reconnaîtra, pour ses nombreux retours sur le sujet pendant la phase problématique.

Bonus terraform

En guise de bonus, un petit détail hors sujet :

Nous utilisons Terraform pour mettre en place et maintenir le cluster AKS. Nous aurions notamment souhaité utiliser les images GPU Preview disponibles via l’utilisation de Custom Headers. Malheureusement ce n’est pas possible lorsqu’on utilise Terraform ici, la cause est plutôt située au niveau de l’API côté Azure ici !

Allez, ciao !


Ne ratez pas nos prochains articles DevOps et Cloud Native! Suivez Enix sur Twitter!