KubeAI : un opérateur Kubernetes pour servir des modèles, avec un proxy qui tient compte du cache KV
AI Inference Operator for Kubernetes. The easiest way to serve ML models in production. Supports VLMs, LLMs, embeddings, and speech-to-text.
En bref
- De quoi s’agit-il ?
- KubeAI est un opérateur d'inférence en Go, sous licence Apache-2.0, qui pilote directement les Pods vLLM, Ollama, FasterWhisper et Infinity, et place devant eux un proxy compatible OpenAI. Son argument central n'est pas le catalogue de modèles mais la répartition des requêtes selon le préfixe, pensée pour le cache KV de vLLM.
- À qui s’adresse-t-il ?
- KubeAI convient aux équipes qui font déjà tourner vLLM ou Ollama sur Kubernetes et qui veulent un chemin compatible OpenAI sans installer Istio, Knative ni l'adaptateur Prometheus. Il ne convient pas si vous voulez seulement exposer un service existant : le projet remplace votre déploiement, il ne s'y greffe pas.
- Puis-je l’utiliser commercialement ?
- Oui. Apache-2.0 est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
- Est-il encore maintenu ?
- Oui. Les derniers commits datent d’il y a 12 jours.
- En quel langage est-il écrit ?
- Principalement Go, d’après les statistiques de langage de GitHub.
Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.
ANALYSE OPEN SOURCE APPROFONDIE
Le problème n'est pas de lancer vLLM, c'est de le répartir
Déployer vLLM sur Kubernetes est facile. Le rendre efficace à plusieurs réplicas l'est beaucoup moins. Le README explique pourquoi : kube-proxy répartit les requêtes de façon aléatoire derrière un Service, or vLLM n'est pas sans état, ses performances dépendent fortement de l'état de son cache KV. Deux requêtes qui partagent un long préfixe et qui atterrissent sur des réplicas différents recalculent le même préfixe deux fois. Le coût se voit sur le time to first token et sur le débit global. KubeAI attaque ce point précis avec un proxy dont la stratégie d'équilibrage tient compte du préfixe, et le dépôt renvoie à un article détaillé sur l'équilibrage de charge à l'échelle. Le public visé est donc une équipe plateforme qui exploite déjà des moteurs d'inférence sur Kubernetes et qui a constaté ce gaspillage, pas un développeur qui veut tester un modèle sur son portable. Le projet couvre quatre familles de charges : génération de texte, embeddings, reranking et transcription audio, via vLLM, Ollama, Infinity et FasterWhisper.
Deux composants, un seul déploiement
L'architecture tient en deux blocs que le README décrit séparément. Le proxy expose une API compatible OpenAI et implémente derrière cette façade l'équilibrage selon le préfixe, la mise en file des requêtes pendant qu'un modèle passe de zéro à une réplica, et les tentatives de réessai quand un backend se comporte mal. L'opérateur, lui, gère directement les Pods des serveurs backend : téléchargement des modèles, montage des volumes, chargement d'adaptateurs LoRA dynamiques, le tout décrit par une CRD Model. Les deux composants vivent dans le même déploiement, et le README précise qu'ils pourraient être séparés, en renvoyant à un ticket. Ce détail a son importance : la séparation est envisagée, pas disponible. La file d'attente du proxy est ce qui rend le scale-from-zero acceptable du point de vue de l'appelant, puisque la requête attend au lieu d'échouer pendant le démarrage du Pod. Le point de conception à retenir est que KubeAI ne s'appuie pas sur un maillage de services pour router : c'est le proxy lui-même qui décide, ce qui supprime une couche mais concentre la logique de routage dans un composant unique.
Installer KubeAI et activer des modèles du catalogue
Le quickstart du README passe par Helm. On crée d'abord un cluster local avec kind ou minikube, puis on ajoute le dépôt et on installe le chart en attendant que tout soit prêt :
helm repo add kubeai https://www.kubeai.org helm repo update helm install kubeai kubeai/kubeai --wait --timeout 10m
Le second chart, kubeai/models, porte la configuration des modèles. Le README donne un fichier de valeurs avec une clé racine catalog, où chaque entrée porte un enabled, une liste features, une url au format ollama://deepseek-r1:1.5b, un engine valant OLlama, un minReplicas et un resourceProfile comme cpu:1. Les entrées déjà connues du catalogue peuvent se contenter d'un enabled, comme qwen2-500m-cpu ou nomic-embed-text-cpu. L'installation se fait ensuite avec helm install kubeai-models kubeai/models -f ./kubeai-models.yaml. Deux contraintes pratiques figurent dans le README : si vous utilisez Podman avec kind, la machine virtuelle est plafonnée à 2 Go par défaut, et il faut la recréer avec podman machine init --memory 6144 --disk-size 120. Le README indique aussi que l'installation peut prendre une minute.
L'API compatible OpenAI, et ce qu'elle implique vraiment
Le projet expose /v1/chat/completions, /v1/completions, /v1/embeddings, /v1/rerank, /v1/models et /v1/audio/transcriptions. L'intérêt est de ne pas réécrire les clients, mais il faut lire la liste telle qu'elle est : ce sont les routes prises en charge, et rien dans le matériel fourni ne décrit le comportement des paramètres optionnels de l'API OpenAI au-delà de ces chemins. Un champ comme response_format ou les appels d'outils ne sont pas documentés ici. C'est un point à vérifier avant de migrer une application qui dépend finement du format des réponses. Autre remarque : la compatibilité porte sur le protocole, pas sur la sémantique de facturation ou de quotas, qui n'apparaît nulle part dans le README. Le proxy ajoute en revanche deux comportements qui n'existent pas dans l'API d'origine, la mise en file pendant le scale-from-zero et les réessais sur backend défaillant, ce qui déplace une partie de la gestion d'erreur du client vers l'infrastructure.
Ce que le projet ne fait pas, et quand il est le mauvais outil
La limite la plus nette est structurelle : l'opérateur gère les Pods backend directement. Cela veut dire que KubeAI remplace votre déploiement, il ne se pose pas au-dessus. Si vous avez déjà des déploiements vLLM maison avec vos propres sondes, vos propres init containers et votre propre logique de préchargement, l'adoption implique de les convertir en ressources Model ou de renoncer à l'opérateur et de n'utiliser que le proxy, ce que le README n'explique pas comme un chemin supporté. Deuxième point : l'équilibrage selon le préfixe est présenté comme un gain pour vLLM, dont le cache KV justifie l'approche. Pour un moteur sans état ou pour des modèles à contexte court et à préfixes peu partagés, l'avantage est bien moins évident, et le README ne fournit pas de chiffres pour ces cas. Troisième point : le catalogue est décrit comme préconfiguré pour les types de GPU courants, ce qui sous-entend que les modèles hors catalogue demandent de mettre les mains dans les drapeaux spécifiques à vLLM, exactement ce que le projet veut éviter. Enfin, rien dans le matériel fourni ne couvre la gestion des secrets de registry, la limitation de débit par locataire ou l'isolation réseau entre modèles, des sujets qu'une plateforme multi-équipes finit par rencontrer.
Face à KServe, la différence n'est pas la liste de fonctionnalités
L'alternative la plus proche est KServe, qui sert aussi des modèles sur Kubernetes. La différence d'approche est visible dans les dépendances : KServe s'appuie sur Knative pour le scale-from-zero et sur Istio pour le routage, tandis que le README de KubeAI revendique explicitement l'absence d'Istio, de Knative et de l'adaptateur de métriques Prometheus. Concrètement, cela change la surface d'exploitation : avec KServe, une montée de version de Knative ou d'Istio fait partie du travail de maintenance, et les désaccords de version entre projets deviennent votre problème. Avec KubeAI, le routage et le scale-from-zero sont dans le binaire. Le revers est symétrique : KServe est un standard d'inférence avec un écosystème de runtimes plus large, là où KubeAI se concentre sur quelques moteurs et sur un type de charge, la génération de texte avec cache KV. Si votre besoin est de servir un classifieur scikit-learn et un modèle PyTorch à côté d'un LLM, KubeAI n'est pas l'outil. Si votre besoin est un LLM à plusieurs réplicas avec des préfixes partagés, la logique de routage de KServe ne traite pas ce cas de la même manière.
Maintenance, versions et licence
Le rythme de publication est soutenu et les charts sont versionnés séparément du binaire : helm-chart-kubeai-0.23.4 et helm-chart-models-0.23.4 sont sortis le même jour, la veille d'une version v0.23.3. Cette séparation signifie qu'une montée de version du chart et une montée de version de l'image ne sont pas le même geste, et qu'il faut lire les deux jeux de notes. Le dépôt n'est pas archivé et la dernière poussée est récente, ce qui indique un projet actif, mais le matériel fourni ne dit rien de la politique de support des versions ni de la compatibilité entre versions de CRD, un point à vérifier dans les notes de version avant de mettre à jour un cluster en production. Sur la licence, KubeAI est publié sous Apache-2.0, une licence permissive qui autorise l'usage commercial et la modification, avec les obligations habituelles de conservation des mentions et de l'avis de licence. Le README ne signale pas de composant sous licence différente, mais je n'ai pas de moyen de le confirmer à partir du matériel fourni, et une vérification fichier par fichier reste nécessaire si votre service juridique l'exige. Je ne donne pas d'avis juridique ici.
Conclusion éditoriale
KubeAI convient aux équipes qui font déjà tourner vLLM ou Ollama sur Kubernetes et qui veulent un chemin compatible OpenAI sans installer Istio, Knative ni l'adaptateur Prometheus. Il ne convient pas si vous voulez seulement exposer un service existant : le projet remplace votre déploiement, il ne s'y greffe pas. Avant d'adopter, vérifiez deux choses concrètes : que votre cluster accepte le contrôleur d'admission des CRD et que votre stockage supporte le montage en lecture seule utilisé pour le cache de modèles, car c'est de ce montage que dépend le redémarrage des backends.
Notes de la communauté