Déployer vLLM en production
Pour déployer vLLM en production : installez-le sur Linux (pip ou l'image Docker vllm/vllm-openai), lancez vllm serve avec votre modèle, réglez --gpu-memory-utilization et --max-model-len, activez --api-key, puis placez un reverse proxy devant. Le serveur écoute sur le port 8000 avec une API compatible OpenAI. Il ne sert qu'un modèle à la fois et vise le débit de nombreux utilisateurs simultanés.
vLLM est le serveur d'inférence pensé pour partager un GPU entre de nombreuses requêtes en parallèle. Ce guide couvre le dimensionnement de la mémoire (le vrai sujet), l'installation, le lancement, Docker et systemd, les paramètres qui comptent, la mesure de débit et la sécurité, avec une correction importante : l'option --api-key protège seulement une partie des routes.
#Ce que vLLM fait, et ce qu'il exige
vLLM est un moteur d'inférence open source né au laboratoire Sky Computing de UC Berkeley. Son idée centrale, PagedAttention, gère le cache clé-valeur de l'attention par pages, comme la mémoire virtuelle d'un système d'exploitation. Selon l'annonce initiale du projet en 2023, les systèmes existants gaspillaient une grande part de leur mémoire et vLLM atteignait jusqu'à 24 fois le débit de Hugging Face Transformers et jusqu'à 3,5 fois celui de TGI, sur des tests de l'époque. Ces chiffres sont anciens et propres à ce banc : ils indiquent une direction, pas ce que vous obtiendrez avec votre modèle et votre carte.
Côté prérequis, la documentation actuelle demande Linux et Python de 3.10 à 3.13 ; sur Mac, il existe une voie séparée, vLLM-Metal, qui s'appuie sur MLX. Le serveur expose une API compatible OpenAI, écoute par défaut sur le port 8000 et ne sert qu'un modèle à la fois : pour plusieurs modèles, il faut plusieurs instances.
#Quand choisir vLLM plutôt qu'Ollama
Ton ChatGPT privé et gratuit sur ta machine en 1 heure — LM Studio, Ollama, Open WebUI, tes documents, sans cloud.
- Espace en ligne à vie
- PDF + fichiers
- Remboursé 30 j
La différence ne tient pas à la capacité de traiter des requêtes en parallèle, qu'Ollama offre aussi, mais à la façon dont la mémoire est partagée. Selon la FAQ d'Ollama, le traitement parallèle d'un modèle multiplie la taille du contexte par le nombre de requêtes : un contexte de 2 000 tokens avec 4 requêtes parallèles devient un contexte de 8 000 tokens en mémoire, réservé d'avance. vLLM alloue son cache par blocs, à la demande, et regroupe les requêtes en cours dans les mêmes calculs.
| Critère | Ollama | vLLM |
|---|---|---|
| Utilisateurs simultanés | 1 à quelques-uns ; OLLAMA_NUM_PARALLEL règle le parallélisme | Dizaines de requêtes simultanées |
| Modèles servis | Plusieurs, chargés et déchargés à la demande | Un seul par instance |
| Mise en place | Une commande d'installation | Python, CUDA et paramètres à régler |
| Quantifications | GGUF, choix large | Formats du Hub (AWQ, GPTQ, FP8) ; GGUF partiellement |
| Métriques de suivi | Non détaillées dans ce guide | Point d'accès /metrics documenté |
| Usage type | Poste personnel, petite équipe | Service interne ou produit |
Règle pratique : si moins de trois personnes utilisent le modèle en même temps, ou si vous voulez changer de modèle souvent, Ollama suffit. Au-delà, ou avec un seul modèle servi en continu, vLLM rentabilise sa complexité. Le guide comparatif détaille le choix.
#Quand vLLM est un mauvais choix
vLLM n'apporte rien à un utilisateur seul sur un GPU de 8 à 12 Go : la mémoire manque pour un cache partagé, et Ollama ou llama.cpp démarrent plus simplement. Il convient mal si vous alternez entre cinq modèles au fil de la journée, puisqu'il faut relancer une instance par modèle. Sur un Mac, la voie est différente et repose sur MLX. Enfin, si votre besoin est une interface de chat pour l'équipe plutôt qu'une API à forte charge, une pile Ollama avec Open WebUI répond mieux et demande moins d'exploitation.
#Dimensionner la mémoire : le calcul à faire avant tout
Un serveur vLLM se dimensionne par le cache clé-valeur, pas par les poids. Après avoir chargé le modèle, vLLM réserve une fraction de la mémoire du GPU, 92 % par défaut d'après le code de configuration actuel, et consacre tout ce qui reste au cache. Ce reste détermine combien de tokens de conversation peuvent coexister, donc combien d'utilisateurs simultanés vous servez.
Prenons Qwen2.5-7B-Instruct, dont la fiche indique 7,61 milliards de paramètres, 28 couches et 4 têtes clé-valeur (attention groupée). Le poids en 16 bits est d'environ 15,2 Go. Le cache d'un token vaut 2 (clés et valeurs) × 28 couches × 4 têtes × 128 dimensions × 2 octets, soit 57 344 octets, environ 56 Kio.
| Mémoire du GPU | Réserve à 92 % | Reste pour le cache | Tokens de cache (borne haute) | Équivalent en requêtes de 4 096 tokens |
|---|---|---|---|---|
| 24 Go | 22,1 Go | 6,9 Go | environ 120 000 | environ 29 |
| 48 Go | 44,2 Go | 28,9 Go | environ 500 000 | environ 120 |
| 80 Go | 73,6 Go | 58,4 Go | environ 1 000 000 | environ 250 |
Ces bornes sont hautes : les tampons de calcul et les graphes CUDA consomment une partie du reste, et le modèle peut avoir un autre profil. La méthode reste valable pour tout modèle : lisez les nombres de couches et de têtes clé-valeur dans la fiche, calculez le coût par token, et divisez ce qu'il reste. Si les journaux signalent des préemptions, la documentation recommande d'augmenter gpu_memory_utilization ou de réduire max_num_seqs.
Deux leviers agrandissent le cache sans changer de carte : charger une version quantifiée du modèle, qui libère une partie des poids, ou limiter --max-model-len, ce qui évite de réserver de la place pour des contextes que personne n'utilise. Le premier levier peut coûter un peu de qualité ; le second ne coûte rien tant que vos requêtes restent courtes.
#1. Installation
La documentation recommande uv, qui choisit automatiquement la bonne version de PyTorch selon votre pilote CUDA. Pour un GPU AMD, l'installation passe par un index dédié ; pour Intel, TPU ou Ascend, des plugins existent. En production, l'image Docker évite les conflits de versions CUDA et se met à jour avec un simple changement d'étiquette.
#2. Lancer le serveur
La commande vllm serve remplace l'ancienne invocation python -m vllm.entrypoints.openai.api_server, que la documentation actuelle n'utilise plus. Au premier lancement, les poids sont téléchargés depuis Hugging Face : prévoyez le disque (15 Go environ pour un 7B en 16 bits). Le serveur applique par défaut le fichier generation_config.json du dépôt du modèle, donc les paramètres d'échantillonnage recommandés par son éditeur ; --generation-config vllm rétablit les valeurs par défaut de vLLM.
#3. Docker et systemd
L'image officielle vllm/vllm-openai est la voie la plus sûre. Montez le cache Hugging Face pour ne pas retélécharger les poids, et un volume pour le cache de compilation : chaque nouveau conteneur démarre sinon avec un cache vide et recompile les artefacts de son modèle. Notez que l'image s'exécute en root par défaut ; la documentation décrit une exécution avec un utilisateur non privilégié (--user 2000:0).
#4. Les paramètres qui comptent
| Paramètre | Rôle | Conseil |
|---|---|---|
| --gpu-memory-utilization | Fraction de la mémoire du GPU réservée (0,92 par défaut) | Baisser si un autre processus utilise le GPU ; le monter si les journaux montrent des préemptions |
| --max-model-len | Contexte maximal accepté | Le plus bas possible : chaque token de contexte coûte du cache |
| --max-num-seqs | Nombre maximal de requêtes dans un lot | À baisser en cas de manque de mémoire |
| --tensor-parallel-size | Répartit le modèle sur plusieurs GPU d'un nœud | Seulement si le modèle ne tient pas sur un GPU |
| --api-key | Exige une clé pour certaines routes | Voir la section sécurité : insuffisant seul |
| --generation-config vllm | Ignore generation_config.json du modèle | À utiliser si les réponses diffèrent de vos attentes |
Un principe de la documentation : si le modèle tient sur un seul GPU, la distribution est probablement inutile ; s'il ne tient pas mais tient sur un nœud, on utilise le parallélisme tensoriel avec --tensor-parallel-size. Les modèles déjà quantifiés se chargent directement depuis le Hub, sans option particulière : l'option --quantization ne sert que pour la quantification dynamique.
#5. Mesurer le débit correctement
La commande vllm bench serve envoie des requêtes au serveur et rapporte le débit, le délai avant le premier token (TTFT) et la latence entre tokens. La documentation précise que ces bancs servent surtout à évaluer des fonctions et à détecter des régressions, et recommande GuideLLM pour tester un serveur de production.
#Mise en service et exploitation
Une fois le dimensionnement fait, la mise en service suit toujours la même séquence. Elle vaut pour une équipe d'une vingtaine de personnes interrogeant un même modèle de 7 à 8 milliards de paramètres sur une carte de 24 ou 48 Go.
- 01Choisir le modèle et le formatUn seul modèle par instance. Préférez un dépôt déjà quantifié ou en 16 bits, selon la mémoire disponible.
- 02Calculer le cacheAppliquez le calcul par token de la section de dimensionnement pour fixer --max-model-len et --max-num-seqs.
- 03Démarrer dans DockerUtilisez l'image officielle avec le cache Hugging Face monté et une étiquette de version figée plutôt que latest, pour éviter qu'une mise à jour change le comportement.
- 04Ajouter le proxyReverse proxy avec liste blanche des routes, TLS et limitation de débit, puis la clé d'API en complément.
- 05MesurerLancez un banc de charge avec vllm bench serve en variant la graine, et notez le TTFT et le débit total.
- 06SurveillerBranchez la collecte du point d'accès /metrics sur votre outil de supervision.
Les signaux à surveiller sont ceux qui annoncent un manque de cache : préemptions dans les journaux, TTFT qui grimpe, files d'attente qui s'allongent. La documentation signale que la préemption, dont le mode par défaut est le recalcul, protège le service mais dégrade la latence de bout en bout. Si elle devient fréquente, montez gpu_memory_utilization, réduisez le contexte ou limitez le nombre de requêtes simultanées. En dernier recours, ajoutez un GPU et répartissez le modèle avec le parallélisme tensoriel.
#6. Sécurité et exposition : --api-key ne suffit pas
Contrairement à ce que l'on lit souvent, vLLM sait vérifier une clé d'API, avec --api-key ou la variable VLLM_API_KEY. Mais la documentation de sécurité insiste : la clé ne protège que les routes sous /v1, /v2, /inference et /cohere. D'autres routes restent sans authentification, dont des routes d'inférence hors /v1, des routes de contrôle comme /pause ou /abort_requests, et /health. Ne comptez donc jamais sur --api-key seule.
- Reverse proxy
- Placez nginx, Envoy ou une passerelle Kubernetes devant vLLM, avec une liste blanche des seules routes à exposer, et bloquez toutes les autres.
- Réseau
- Un VPN ou un réseau isolé : la communication entre les nœuds d'un déploiement distribué n'est pas sécurisée par défaut.
- Mode développement
- N'activez jamais VLLM_SERVER_DEV_MODE=1 en production : il expose des routes dangereuses.
- Limites
- Appliquez la limitation de débit et la validation des requêtes au niveau du proxy, comme le recommande la documentation.
- Journaux
- Consignez qui envoie quoi, pour le débogage et l'audit.
- Source : démarrage rapide de vLLM
- Source : sécurité de vLLM
- Source : vLLM avec Docker
- Source : annonce de vLLM et PagedAttention
vLLM est-il meilleur qu'Ollama en production ?+
Comment lancer un serveur vLLM avec une API compatible OpenAI ?+
Combien de VRAM faut-il pour vLLM ?+
L'option --api-key suffit-elle pour sécuriser vLLM ?+
vLLM fonctionne-t-il sur Mac ou avec une carte AMD ?+
Un retour, une erreur, une précision ? Faites-nous signe, ça améliore le guide pour tout le monde.