kubenow
Se connecterCommencer gratuitement

IA.2 · Héberger, brancher, sécuriser

Servir un modèle sur Kubernetes

Leçon théorique · questionnaire de validation · gratuit, dans le navigateur

Héberger un modèle, c'est faire tourner un serveur d'inférence : un conteneur qui charge les poids en mémoire du GPU et répond aux requêtes. Kubernetes apporte ce qu'il apporte à toute application (déploiement, sondes, mise à l'échelle, isolation), avec trois particularités : des GPU à attribuer, des modèles de plusieurs dizaines de gigaoctets à charger, et une charge qui se mesure en jetons plutôt qu'en requêtes. Cette leçon est théorique : les clusters d'exercice n'ont pas de GPU.

Ce que vous saurez à la fin : rendre des GPU disponibles dans un cluster, déployer vLLM (et Ollama pour les petits besoins), stocker et charger les poids efficacement, régler les sondes et la mise à l'échelle d'un serveur d'inférence, et situer KServe et les autres outils.

1. Des GPU dans Kubernetes

Un GPU n'est pas visible par défaut : il faut le pilote sur le nœud, et un device plugin qui l'annonce au kubelet comme ressource. Chez NVIDIA, le GPU Operator installe tout (pilote, outils du runtime de conteneurs, device plugin, supervision) :

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm install gpu-operator nvidia/gpu-operator -n gpu-operator --create-namespace
kubectl get nodes -o custom-columns=NOM:.metadata.name,GPU:.status.allocatable.nvidia\\.com/gpu

Un pod demande ensuite des GPU comme du CPU, en limite (un GPU entier, non partagé par défaut) :

resources:
  limits: {nvidia.com/gpu: 1}

Les nœuds GPU coûtent cher : réservez-les avec une teinte (nvidia.com/gpu=present:NoSchedule) et une tolérance sur les seuls pods d'inférence (leçon 4.2), pour qu'aucun pod ordinaire ne vienne s'y installer. Le partage d'un GPU (MIG, découpage temporel) existe pour les petits modèles.

2. Déployer vLLM

vLLM est un serveur d'inférence ouvert très répandu : regroupement continu des requêtes, gestion efficace du cache KV, API compatible OpenAI.

apiVersion: apps/v1
kind: Deployment
metadata: {name: llm, labels: {app: llm}}
spec:
  replicas: 1
  selector: {matchLabels: {app: llm}}
  template:
    metadata: {labels: {app: llm}}
    spec:
      tolerations: [{key: nvidia.com/gpu, operator: Exists, effect: NoSchedule}]
      containers:
        - name: vllm
          image: vllm/vllm-openai:v0.11.0            # épinglez une version testée
          args: ["--model", "Qwen/Qwen3-8B", "--served-model-name", "qwen3-8b",
                 "--max-model-len", "16384", "--gpu-memory-utilization", "0.90"]
          env:
            - name: HF_HOME
              value: /modeles
          ports: [{containerPort: 8000}]
          resources:
            requests: {cpu: "4", memory: 24Gi}
            limits: {nvidia.com/gpu: 1, memory: 32Gi}
          volumeMounts:
            - {name: modeles, mountPath: /modeles}
            - {name: shm, mountPath: /dev/shm}
          startupProbe:                              # le chargement prend plusieurs minutes
            httpGet: {path: /health, port: 8000}
            periodSeconds: 10
            failureThreshold: 90
          readinessProbe:
            httpGet: {path: /health, port: 8000}
      volumes:
        - name: modeles
          persistentVolumeClaim: {claimName: modeles}
        - name: shm
          emptyDir: {medium: Memory, sizeLimit: 8Gi}
  • --max-model-len borne le contexte, donc le cache KV : c'est le premier réglage si le serveur manque de mémoire.
  • Une sonde de démarrage généreuse évite que Kubernetes tue le pod pendant le chargement des poids (leçon 2.13).
  • /dev/shm en mémoire : nécessaire dès que plusieurs processus ou GPU coopèrent.

Un Service devant, et toute application compatible OpenAI peut l'utiliser : http://llm.ia.svc:8000/v1.

3. Ollama, pour commencer petit

Ollama est plus simple : il télécharge et fait tourner des modèles quantifiés (GGUF), sur GPU ou sur CPU, avec une API sur le port 11434 (compatible OpenAI sous /v1). Idéal pour un poste, une démonstration ou un petit outil interne ; vLLM l'emporte nettement en débit sous charge.

4. Les poids : où et comment

Télécharger 16 Go depuis Internet à chaque démarrage de pod est lent et fragile. Options :

  • un PVC partagé, rempli une fois par un Job (huggingface-cli download …), monté en lecture par les pods ;
  • une image OCI contenant le modèle (montée comme volume image, ou en modelcar avec KServe) : le modèle se versionne et se distribue comme une image, depuis votre registre ;
  • un stockage objet (S3) avec un cache local sur chaque nœud.

Dans tous les cas, épinglez la révision exacte du modèle, et vérifiez sa licence : « ouvert » ne veut pas toujours dire « utilisable commercialement sans condition ».

5. Mise à l'échelle

L'utilisation CPU ne dit rien de la charge d'un serveur d'inférence. Les bons signaux, exposés en métriques Prometheus par vLLM (/metrics) : requêtes en attente, utilisation du cache KV, délai avant le premier jeton. KEDA sait mettre à l'échelle sur une requête Prometheus (leçon 4.4), et l'autoscaler de nœuds ajoute des machines GPU au besoin. Gardez en tête qu'un nouveau réplica met plusieurs minutes à être prêt : on anticipe plutôt qu'on réagit, et on garde un minimum de réplicas pendant les heures ouvrées.

Pour répartir la charge intelligemment entre réplicas (selon leur cache et leur file d'attente plutôt qu'au hasard), le projet Gateway API Inference Extension ajoute un routage spécialisé au-dessus de la Gateway API (leçon 3.7).

6. Les plateformes de service

Outil Rôle
KServe ressource InferenceService : serveur, mise à l'échelle (jusqu'à zéro), canary entre versions de modèle, plusieurs moteurs (vLLM, Triton…)
llm-d inférence distribuée de grands modèles sur Kubernetes, autour de vLLM
NVIDIA Triton / NIM serveurs et conteneurs optimisés du constructeur
Ray Serve (KubeRay) service et calcul distribué Python

Pour un ou deux modèles, un Deployment vLLM bien réglé suffit. Une plateforme se justifie quand de nombreuses équipes publient de nombreux modèles.

Validez la leçon avec le questionnaire.

Contenu aligné sur les programmes publiés par la CNCF (KCNA, CKAD, CKA, CKS), par le Linux Professional Institute (LPIC-1) et par Cisco (CCNA 200-301). KubeNow n'est ni affilié ni approuvé par la CNCF, la Linux Foundation, le LPI ou Cisco ; CKA, CKAD, CKS et KCNA sont des marques de la Linux Foundation, LPIC-1 est une marque du Linux Professional Institute, Cisco et CCNA sont des marques de Cisco Systems.