Déploiement d'une Stack vLLM d'Entreprise sur GKE


Exécuter des modèles open-source ou open-weight localement est devenu incroyablement accessible. Des outils comme Ollama et LM Studio sur macOS permettent aux utilisateurs de faire tourner des modèles d'IA directement sur leur propre matériel. À mesure que les modèles open-weight gagnent en puissance et se rapprochent des modèles commerciaux de pointe, cette capacité change véritablement la donne.

Par conséquent, nous observons une transition logique vers l'utilisation de modèles open-weight en entreprise. Les exécuter en parallèle avec des modèles commerciaux de pointe permet d'optimiser considérablement les coûts. Pour des cas d'usage spécifiques — tels que la transcription, la traduction, la génération de texte et l'assistance au code simple les modèles open-weight peuvent même être utilisés de manière exclusive.

Bien qu'Ollama soit fantastique pour le prototypage local, il n'est pas adapté à une architecture de production pour servir des modèles d'IA à grande échelle. Il manque d'options de personnalisation avancées, et le marché propose des outils plus robustes conçus spécifiquement pour l'inférence à haute performance. Aujourd'hui, le choix le plus populaire pour l'inférence en production est vLLM.

vLLM brille comme un moteur d'inférence prêt pour la production, capable de :

  • Continuous batching (traitement par lots continu) : Traite les requêtes au niveau du token au lieu d'attendre des lots statiques, ce qui réduit considérablement les temps d'attente et optimise le débit.
  • Efficacité GPU avec PagedAttention : Alloue dynamiquement la VRAM en divisant le cache KV en petites pages de mémoire non contiguës.
  • Inférence distribuée : Prend en charge le parallélisme de tenseurs (tensor parallelism) et de pipeline, une fonctionnalité cruciale pour distribuer des modèles massifs sur plusieurs nœuds ou GPUs.
  • Large compatibilité : Prend en charge nativement la grande majorité des architectures modernes de modèles open-weight.

Bien que vLLM gère magnifiquement l'inférence à haut débit, une véritable architecture de production nécessite également un accès sécurisé, une gestion réseau, une haute disponibilité, une scalabilité et une infrastructure maintenable. C'est ici que Kubernetes (K8s) complète l'équation. En déployant vLLM sur Kubernetes, nous traitons les modèles d'IA comme des charges de travail standard qui peuvent être automatiquement réparées, mises à l'échelle dynamiquement et exposées de manière sécurisée.

Aujourd'hui, la stack vLLM sur Kubernetes devient le standard pour déployer des modèles d'entreprise sur des clouds publics ou privés.

Pour explorer cette architecture, j'ai décidé de la construire de manière itérative, en commençant par un cas d'usage simple : un cluster GKE (Google Kubernetes Engine) à nœud unique servant un petit modèle capable d'assistance au code (agentic coding). Vous pouvez trouver le code source complet et l'architecture détaillée sur mon dépôt : iheb24/vllm-gke.

Aperçu de l'Architecture

J'ai choisi GCP (Google Cloud Platform) pour monter rapidement un cluster GKE. Étant donné la disponibilité limitée des GPUs pour les petits projets, j'ai opté pour un seul GPU NVIDIA L4.

Le GPU L4 offre 24 Go de VRAM, ce qui est parfait pour accueillir des modèles comme Qwen2.5-Coder-14B-AWQ. (J'ai également testé Qwen2.5-Coder-7B-Instruct, qui était encore plus léger en ressources). Le modèle 14B AWQ possède de solides compétences en génération de code — excellent pour les petites tâches non complexes et très efficace pour une intégration IDE locale.

Pour garantir la sécurité, l'infrastructure est hébergée sur un réseau privé GCP. Mon agent n'est pas exposé sur l'internet public ; j'ai plutôt mis mon adresse IP sur liste blanche pour un accès direct. De plus, les appels API sont sécurisés en injectant une clé API dans le serveur vLLM après le déploiement.

Mon objectif ici est de démontrer une preuve de concept (PoC) pour l'hébergement de modèles directement sur GKE.

Au niveau du VPC, l'infrastructure comprend :

  • Un sous-réseau avec une plage IP principale pour les nœuds, et deux plages IP secondaires (une pour les pods, une pour les services K8s).
  • Une passerelle Cloud NAT pour l'accès sortant à internet.
  • Un Cloud Router pour gérer le trafic réseau.

Sur le cluster GKE privé, la configuration inclut :

  • Un Control Plane géré par Google.
  • Un pool de nœuds standard pour les pods système (CPUs traditionnels).
  • Un pool de nœuds GPU dédié contenant une machine NVIDIA L4 pour le pod vLLM.
  • Workload Identity configuré sur le compte de service K8s pour une interaction sécurisée avec d'autres services GCP.

De plus, le déploiement utilise un Persistent Volume Claim (PVC) pour mettre en cache les poids du modèle téléchargé. Si le pod est recréé sur le même nœud, il n'aura pas besoin de retélécharger les fichiers massifs du modèle depuis Hugging Face, ce qui réduit considérablement les temps de démarrage à froid. (Remarque : si le cluster lui-même est détruit, ce volume de cache est également perdu). Consultez 02-pvc.yaml dans le dépôt pour plus de détails.

Tarification

Voici une rapide comparaison de prix entre les instances Spot (Préemptibles) et Standard (Réservées) pour un nœud g2-standard-8 (1x L4 GPU, 8 vCPUs, 32 Go de RAM) dans les régions europe-west4 et us-central1 :

Modèle de FacturationTaux HoraireCoût Mensuel (24/7)Fiabilité
Spot (Préemptible)~0,25 $ / h~182 $ / moisPeut être supprimé à tout moment sans préavis.
Standard (À la demande)~0,83 $ / h~605 $ / moisVous est dédié, ne sera jamais préempté.

J'ai testé l'ensemble de l'architecture tout au long de la semaine en la créant et la détruisant à la demande (sans laisser les ressources tourner inutilement). Le coût total a été inférieur à 5 $.

Provisionnement de l'Infrastructure

Pour déployer cela vous-même, suivez ces étapes :

  1. Vérifiez les Quotas GCP : Assurez-vous d'avoir les quotas GPU et CPU nécessaires.
    • L'utilisation du GPU est désactivée par défaut. Vous avez besoin d'au moins 1 pour la métrique GPUs (all regions).
    • Comme la stack peut utiliser des instances Spot, j'ai également demandé une augmentation du quota Preemptible CPUs dans ma région cible.
    • J'avais le quota de GPU L4 par défaut, mais des machines plus puissantes nécessitent des demandes manuelles d'augmentation de quota avec des justifications.
  2. Configurez l'Environnement : Récupérez votre adresse IP publique en utilisant curl ifconfig.me et créez un fichier .tfvars référençant l'ID de votre projet GCP et votre adresse IP.
  3. Déployez l'Infrastructure : Authentifiez-vous sur GCP et exécutez terraform apply.
  4. Configurez Kubernetes : Une fois Terraform terminé, authentifiez-vous sur le nouveau cluster : gcloud container clusters get-credentials vllm-cluster --region us-central1 --project <id-projet-gcp>
  5. Configurez le Namespace et l'Identité : kubectl apply -f k8s/vllm/01-namespace-and-sa.yaml
  6. Injectez la Clé API : kubectl create secret generic vllm-api-key --from-literal=api-key="<votre-cle-api>" -n vllm
  7. Déployez vLLM : kubectl apply -f k8s/vllm/
  8. Surveillez le Déploiement : Observez les événements du namespace pour vous assurer que tout démarre correctement.

Note sur les instances : L'utilisation d'instances Spot offre un avantage tarifaire massif, mais les ressources peuvent être préemptées ou simplement indisponibles lorsque vous les demandez, ce qui entraîne des temps d'attente plus longs pour qu'un GPU se libère.

Si votre quota est insuffisant, Terraform ou GKE renverra une erreur, et les instances ne seront pas provisionnées :

quota_exceed

Lors de la demande de GPUs — même des Standard — vous pourriez rencontrer des problèmes de disponibilité car ils sont très demandés. Soyez patient ; une machine finira par être provisionnée.

succes_on_machine

Une fois que le conteneur vLLM commence à télécharger le modèle et à allouer la VRAM, vous pouvez suivre les logs : kubectl logs -l app=vllm-server -n vllm -f

container_started

Recherchez la ligne INFO: Uvicorn running on http://0.0.0.0:8000. Cela confirme que le modèle est chargé et que le serveur est prêt à accepter des requêtes.

Utilisation

Pour accéder au modèle de manière sécurisée depuis votre machine locale, utilisez une commande de port-forward Kubernetes : kubectl port-forward -n vllm svc/vllm-service 8000:8000

Gardez ce terminal ouvert ; il agit comme le tunnel sécurisé entre votre ordinateur et le cluster GKE.

Vous pouvez maintenant tester le modèle directement via curl :

curl_example

Alternativement, vous pouvez connecter un agent IA ou un assistant de code capable d'utiliser des points de terminaison compatibles avec OpenAI. Pour cet exemple, j'ai configuré Cline dans VS Code.

cline_conf

L'agent interagit directement avec le modèle, générant des réponses dans un délai très raisonnable.

cline_response

Comme le montre la configuration de Cline, la fenêtre de contexte est un paramètre critique. Vous pouvez facilement configurer et ajuster la longueur maximale de la fenêtre de contexte directement dans le manifeste Kubernetes 03-deployment.yaml en utilisant l'argument --max-model-len pour vLLM.

Destruction

Pour détruire l'infrastructure et arrêter de générer des frais, retournez dans le dossier de votre environnement Terraform et exécutez terraform destroy. Cela supprimera proprement toutes les ressources provisionnées.

Considérations Finales

Dans les captures d'écran de démo, vous remarquerez peut-être que je testais initialement avec Qwen/Qwen2.5-Coder-7B-Instruct. Plus tard, je suis passé au modèle plus lourd Qwen/Qwen2.5-Coder-14B-AWQ pour mieux exploiter la machine L4 pour l'assistance au code.

Ce changement a simplement nécessité de mettre à jour le nom du modèle dans le manifeste Kubernetes et d'appliquer la modification. Cette flexibilité rend cette architecture incroyablement puissante — vous pouvez facilement échanger des modèles, ajuster les paramètres ou changer de type de machine une fois le cluster de base établi. Cette adaptabilité justifie parfaitement l'utilisation de Kubernetes, à condition de garder l'architecture simple au début pour éviter la sur-ingénierie.

Une note sur la disponibilité : Rencontrer des limites de quotas, des ruptures de stock et de longs temps d'attente pour les GPUs est tout à fait normal sur un compte GCP personnel en ce moment. La moitié du monde de la tech expérimente avec les GPUs du cloud public. Les environnements d'entreprise contournent cette misère en utilisant des engagements d'utilisation pour les GPUs sur un an ou plus, garantissant une disponibilité immédiate et des économies importantes.

Améliorations Futures pour la Production

Bien que cette stack serve de solide expérience d'apprentissage fondamentale, elle nécessite quelques améliorations avant de pouvoir être considérée comme véritablement prête pour la production :

  • Automatisation du Déploiement : Envelopper les manifestes Kubernetes dans un Chart Helm ou utiliser ArgoCD pour un déploiement piloté par GitOps.
  • Ingress et TLS : Remplacer la solution de contournement kubectl port-forward. Une véritable stack de production utilise un Contrôleur Ingress (comme NGINX ou Gateway API) combiné avec cert-manager pour provisionner automatiquement des certificats SSL Let's Encrypt gratuits.
  • Observabilité : Faire tourner un LLM en production à l'aveugle est dangereux. L'intégration de Prometheus et Grafana pour scraper le point de terminaison /metrics de vLLM est essentielle pour surveiller l'utilisation de la mémoire GPU, les longueurs de file d'attente et le nombre de tokens par seconde.
  • Autoscaling Intelligent : Mon autoscaler actuel est "basique" — il ne provisionne un nouveau nœud que si un pod ne parvient pas à être planifié. La norme d'excellence actuelle est la mise à l'échelle en utilisant KEDA (Kubernetes Event-driven Autoscaling) pour augmenter ou diminuer dynamiquement le nombre de GPUs en fonction de la longueur réelle de la file d'attente des requêtes API entrantes.

Type to start searching...