AI Infrastructure

Génie du chaos pour l'inférence LLM

Introduction : Au-delà des microservices standard

Les systèmes d'inférence de grands modèles de langage (LLM) fonctionnent sous des contraintes uniques, distinctes des microservices traditionnels. Contrairement aux API web sans état, les points de terminaison LLM s'appuient fortement sur la mémoire GPU limitée pour la gestion du cache KV et maintiennent souvent des connexions de longue durée pour les réponses en streaming. Cette dépendance à du matériel spécialisé rend les pratiques standard de génie du chaos insuffisantes. Nous ne pouvons pas simplement tuer un conteneur ; nous devons tenir compte de l'état conservé dans la VRAM, du coût de réinitialisation du modèle et des pics de latence causés par les cycles de réinitialisation du GPU. Dans cet article, nous explorons comment concevoir des expériences de chaos ciblant spécifiquement les pannes GPU et les partitions réseau. L'objectif est de passer au-delà du simple « ça redémarre » pour atteindre « ça redémarre avec une latence acceptable et sans perte de données pour les clients en streaming ».

Scénario 1 : Simulation d'une panne soudaine du GPU

Un mode de défaillance courant en production est le détachement d'un GPU du bus PCI en raison d'un ralentissement thermique ou d'un plantage du pilote. Dans les environnements Kubernetes exécutant des pilotes NVIDIA, cela se manifeste souvent par un nœud mis en cordon ou un pod qui plante avec une erreur `SIGBUS`. Pour tester cela, nous devons simuler la perte du dispositif de calcul sans nécessairement redémarrer le nœud entier, car le temps de réaction de l'orchestrateur peut masquer la gestion interne des erreurs de l'application. Nous pouvons utiliser `nvidia-smi` combiné à des appels système pour simuler cela, ou plus pratiquement, injecter un plantage dans le processus du serveur d'inférence pendant que le GPU est sous charge.

#!/bin/bash
# chaos_gpu_crash.sh
# Injecte un SIGBUS dans le processus d'inférence pour simuler une défaillance d'accès GPU

PID=$(pgrep -f "vllm.engine" | head -n 1)
if [ -z "$PID" ]; then
    echo "Processus d'inférence introuvable"
    exit 1
fi

echo "Simulation d'une défaillance d'accès mémoire GPU sur le PID $PID"
# SIGBUS est souvent levé lorsque la mémoire est décartographiée, simulant une erreur d'accès VRAM
kill -BUS $PID
**Indicateurs clés à surveiller :** * **Latence de démarrage à froid :** Combien de temps faut-il pour que la prochaine requête soit traitée par une réplique saine ? * **Comportement de nouvelle tentative des clients :** Vos équilibreurs de charge ou clients effectuent-ils de nouvelles tentatives immédiatement ? Si oui, submergez-vous les nœuds sains restants avec le retard accumulé ? * **Perte du cache KV :** Vérifiez que toute génération partielle en cours est correctement terminée ou reprise depuis un point de contrôle si votre framework le prend en charge.

Scénario 2 : Partitions réseau et nœuds retardataires

Dans les configurations d'inférence distribuées (par exemple, en utilisant DeepSpeed ou le parallélisme tensoriel de vLLM), la partition réseau est critique. Si un nœud d'un groupe de parallélisme tensoriel perd sa connectivité, le lot d'inférence entier échoue. Cependant, dans une architecture désagrégée (séparation Prefill et Decode), une partition entre l'équilibreur de charge frontal et les workers d'inférence provoque des symptômes différents. Simulons une partition réseau où le backend d'inférence devient inaccessible mais où la passerelle API reste active.

# Utilisez tc (traffic control) pour introduire une perte de paquets de 100 % vers le pod du backend d'inférence
# Cela simule une partition réseau sans faire tomber le nœud entièrement

POD_IP=$(kubectl get pod -l app=inference-backend -o jsonpath='{.items[0].status.podIP}')

# Supprimez tout le trafic destiné au backend d'inférence
kubectl exec -it [gateway-pod] -- tc qdisc add dev eth0 root netem loss 100%

# Attendez la fenêtre de chaos
sleep 30

# Restaurez le trafic
kubectl exec -it [gateway-pod] -- tc qdisc del dev eth0 root
**Comportement attendu :** 1. La passerelle API doit expirer les requêtes dans le délai configuré `proxy_read_timeout` (par exemple, 5 s). 2. La passerelle doit basculer rapidement vers des répliques alternatives si disponibles. 3. **Point crucial :** Pour les réponses en streaming (SSE), le client doit détecter la connexion fermée. Testez si votre code côté client gère correctement une coupure en cours de flux et remet la requête en file d'attente, ou s'il échoue silencieusement, ce qui entraîne la frustration de l'utilisateur.

Mise en œuvre de tests de chaos automatisés dans CI/CD

Le test de chaos manuel n'est pas soutenable. Intégrez ces scénarios à votre pipeline de préproduction à l'aide d'outils comme LitmusChaos ou Chaos Mesh.

apiVersion: litmuschaos.github.io/v1alpha1
kind: ChaosExperiment
metadata:
  name: llm-gpu-chaos
spec:
  appinfo:
    appkind: deployment
    labelselector: "app=vllm-server"
  chaosConfig:
    chaosKind: "pod-kill"
    # Simule un arrêt brutal pour déclencher la récupération GPU au niveau du nœud
    mode: "all"
    duration: "120s"
**Stratégie de validation :** Ne vérifiez pas simplement si le pod redémarre. Validez la *qualité* du service. * **Vérification de la latence P99 :** Affirmez que la latence P99 ne dépasse pas 2 fois la valeur de référence pendant la fenêtre de défaillance. * **Vérification de la perte de jetons :** Pour le streaming, vérifiez que le nombre total de jetons reçus par le client correspond au nombre attendu ou qu'une erreur propre est renvoyée, plutôt qu'une réponse tronquée et corrompue.

Conclusion

L'inférence LLM n'est pas un simple service sans état. Son caractère à état dans la VRAM, son empreinte mémoire élevée et sa nature de streaming de longue durée exigent une approche spécialisée du génie du chaos. En simulant des pannes GPU et des partitions réseau, vous pouvez découvrir des lacunes critiques dans votre logique de nouvelle tentative, vos stratégies d'équilibrage de charge et votre gestion des erreurs côté client. Commencez petit : injectez une panne GPU unique en préproduction. Surveillez le rayon d'impact. Itérez. La résilience se construit par l'échec intentionnel.
Share: