La plupart des services d'inférence n'utilisent qu'une partie d'un GPU, et une carte entière dépasse souvent ce dont a besoin un notebook, un traitement de scoring par lots ou un petit modèle. Partager une carte entre plusieurs charges de travail semble simple, mais Kubernetes ne le fait pas par défaut, et les différentes façons de le faire n'offrent pas du tout les mêmes garanties. Cet article explique ces garanties, ce qu'une tranche partagée sur Kube-DC garantit et ne garantit pas, et ce que nous avons appris en exécutant un vrai LLM sur l'une d'elles.

Kubernetes distribue des GPU entiers par défaut

Le modèle standard de device plugin de Kubernetes signale les GPU au planificateur sous forme de nombres entiers. Une demande de nvidia.com/gpu: 1 signifie la carte entière, et tous les autres pods attendent. Le planificateur n'a aucune notion de quota de mémoire : partager une carte nécessite donc des mécanismes supplémentaires, et il existe trois approches courantes.

Approche Limite de mémoire Isolation Fonctionne sur un V100 ?
MIG (partitionnement matériel) Appliquée par le matériel Isolation de la mémoire et des pannes au niveau matériel Non : il nécessite Ampere ou plus récent (A100, H100, A30, H200), et le V100 est une carte plus ancienne, de génération Volta
Time-slicing Aucune : les répliques partagent la mémoire de la carte Pas d'isolation de la mémoire ni des pannes entre les répliques, selon la documentation de NVIDIA Oui
Découpage logiciel (HAMi) Appliquée par logiciel : les allocations au-delà de la tranche sont refusées Isolation logicielle par interception de l'API CUDA ; pas d'isolation matérielle, et le calcul est limité au mieux des efforts Oui

HAMi, un projet de la Cloud Native Computing Foundation, fonctionne en chargeant dans chaque conteneur une bibliothèque qui intercepte les appels CUDA. Le conteneur ne voit que sa tranche de mémoire, une allocation qui dépasserait la tranche renvoie une erreur de mémoire insuffisante, et les lancements de kernels sont limités vers la part de calcul demandée. La documentation de HAMi est elle-même prudente sur les limites : les applications qui contournent la bibliothèque CUDA, comme Docker-in-Docker ou les appels directs au pilote, ne sont pas couvertes, et l'isolation est au mieux des efforts par rapport à MIG.

Ce que garantit une tranche partagée sur Kube-DC

Les forfaits GPU de Kube-DC utilisent le découpage logiciel sur des cartes NVIDIA V100, et la documentation de la plateforme énonce précisément les garanties. Une tranche est une fraction fixe d'un modèle de GPU ; vous demandez le produit plutôt que d'ajuster librement la mémoire et le calcul. Sur un V100 de 32 Go, nos forfaits proposent 25 % (8 Gio), 50 % (16 Gio) et 100 % (32 Gio).

  • La tranche de mémoire est appliquée. Dans le conteneur, nvidia-smi indique la taille de la tranche, et non celle de la carte physique, et la tranche est un plafond strict.
  • La part de calcul est coopérative. La plateforme oriente chaque charge de travail vers sa part en régime établi, mais le démarrage et certains chemins des bibliothèques CUDA peuvent la dépasser brièvement. Ce n'est pas une performance garantie.
  • Le quota est un droit, pas une réservation. Détenir un quota ne réserve pas de tranche physique. Lorsque tous les GPU compatibles sont occupés, une charge de travail valide attend à l'état Pending jusqu'à ce qu'une tranche se libère.
  • Les tranches sont destinées aux conteneurs. La capacité partagée ne peut pas être attachée à une machine virtuelle.
Une tranche partagée est une garantie de planification et de comptabilisation avec application à l'exécution. Ce n'est pas une frontière de sécurité. Une charge de travail qui ne doit pas partager le silicium avec un autre tenant a besoin d'un GPU dédié.

À quoi ressemble l'utilisation

Depuis Kubernetes 1.34, les API de Dynamic Resource Allocation (DRA) dans resource.k8s.io/v1 sont en disponibilité générale, et Kube-DC les utilise : une charge de travail référence un ResourceClaimTemplate qui pointe vers la DeviceClass de votre produit, et la plateforme valide la demande lorsque vous l'appliquez. Le quota de votre projet indique combien de tranches de chaque produit vous pouvez détenir simultanément :

kubectl get resourcequota -n <project-namespace> -o yaml | grep deviceclass

Une fois votre pod en cours d'exécution, vérifiez la tranche depuis le conteneur. Sur le produit de 8 Gio, la mémoire totale est de 8192 MiB alors que la carte dispose de 32 Go :

nvidia-smi --query-gpu=name,memory.total --format=csv,noheader
# Tesla V100-PCIE-32GB, 8192 MiB

Le manifeste complet à copier et adapter se trouve dans la documentation de Kube-DC, et nous ne le reproduisons volontairement pas ici, car il doit correspondre exactement au contrat publié de la plateforme. Lors de notre propre test, deux tentatives ont échoué pour cette raison avant que la troisième réussisse :

  • Une simple demande nvidia.com/gpu sur un pod brut a été rejetée par une politique d'admission, car la capacité GPU partagée n'est proposée que via le modèle basé sur les claims.
  • Un modèle de claim DRA écrit à la main a été rejeté par une seconde politique d'admission, car les labels, les noms et les valeurs de capacité fixes doivent respecter la forme documentée.
  • Le manifeste documenté a été accepté, puis le pod n'a pas démarré pour une raison sans rapport : le quota de CPU mutualisé du projet était presque entièrement utilisé par un cluster géré et une machine virtuelle. Un pod GPU a tout de même besoin de CPU et de mémoire pris sur votre forfait : vérifiez donc cette marge avant de déployer.

Exécuter un LLM sur une tranche : ce que nous avons appris

Lors de notre test de bout en bout d'août 2026, nous avons exécuté Ollama sur une tranche de 8 Gio et servi llama3.2:3b, puis connecté un agent IA, d'abord depuis une machine virtuelle du même projet, puis depuis un serveur extérieur au datacenter. Les journaux d'Ollama affichaient la carte comme un Tesla V100 avec une compute capability de 7.0 et un total de 8,0 Gio, exactement la tranche. Quatre détails nous ont coûté du temps, et chacun concerne quiconque exécute un modèle sur une tranche.

1. Vérifiez que votre logiciel prend encore en charge la génération de GPU

Le V100 est une carte de génération Volta, et les logiciels GPU actuels ont commencé à passer à autre chose. Lors de notre test, la dernière image Ollama a ignoré le GPU, car sa version CUDA n'incluait pas la compute capability 7.0. Épingler ollama/ollama:0.24.0 a résolu le problème. Cela correspond aux signalements en amont : un ticket Ollama décrit la version v0.30.0 en échec sur un Tesla V100 avec l'erreur « device kernel image is invalid » alors que la v0.24.0 et les versions antérieures fonctionnaient, et un mainteneur a ensuite attribué un échec de ce type à des kernels CUDA compressés nécessitant le pilote NVIDIA 550 ou plus récent. Épinglez la version de votre image et testez les mises à niveau délibérément.

2. La limite de mémoire du pod est distincte de la tranche de GPU

Notre premier chargement de modèle a été tué avec le code de sortie 137 (OOMKilled). La cause était la limite de mémoire du conteneur lui-même, fixée à 512 MiB, bien trop faible pour la charge côté hôte d'Ollama, et sans rapport avec la mémoire du GPU. Dimensionnez la demande et la limite de RAM du conteneur indépendamment de la tranche fixe. Nous avons utilisé 2 Gio et 4 Gio :

containers:
- name: ollama
  image: ollama/ollama:0.24.0
  env:
  - name: OLLAMA_CONTEXT_LENGTH
    value: "16384"
  resources:
    requests:
      memory: 2Gi
    limits:
      memory: 4Gi

3. La fenêtre de contexte par défaut peut tronquer silencieusement le prompt d'un agent

L'agent que nous avons connecté envoie un prompt système et des définitions d'outils d'environ 14 700 tokens. Le journal du serveur Ollama montrait l'entrée coupée à sa limite de 4 096 tokens, ce qui produisait des réponses confuses et peu fiables qui ressemblaient à un problème de qualité du modèle. Augmenter la longueur de contexte avec la variable ci-dessus a corrigé la cause. Rappelez-vous qu'un contexte plus long consomme davantage de la mémoire de votre tranche : dimensionnez donc ensemble le modèle et le contexte.

4. Les modèles vivent dans le pod, sauf si vous leur donnez un volume

Avec le stockage temporaire par défaut, chaque redémarrage du pod, y compris celui provoqué par la modification d'une variable d'environnement, effaçait les modèles téléchargés. Placez le répertoire des modèles sur un volume persistant dès que vous dépassez la démonstration. Notez aussi que les rôles de tenant sur Kube-DC ne peuvent pas utiliser kubectl exec : nous avons donc téléchargé les modèles avec des Jobs à usage unique appelant l'API HTTP d'Ollama.

Quand une tranche partagée est le bon outil

La documentation de Kube-DC en définit l'usage : inférence de modèles, notebooks, petits entraînements et scoring par lots, lorsqu'un traitement a besoin de l'accélération GPU mais pas d'une carte entière. Elle convient mal lorsque vous avez besoin d'une frontière d'isolation stricte, d'un débit garanti ou d'un modèle plus grand que la tranche, et le travail sur carte entière relève d'un matériel dédié. Comme les tranches se mettent en file d'attente lorsque la carte est occupée, elle convient aussi mieux aux charges de travail qui peuvent attendre de la capacité qu'aux services sensibles à la latence avec des échéances strictes.

Comment évaluer une offre de GPU partagé

  • La limite de mémoire est-elle appliquée, ou n'est-ce qu'une suggestion ? Le time-slicing n'en applique aucune.
  • La part de calcul est-elle garantie, coopérative ou illimitée, et que se passe-t-il en cas de contention ?
  • Le quota est-il une réservation, ou votre charge de travail peut-elle rester en Pending lorsque la carte est occupée ?
  • De quel modèle de GPU s'agit-il, et le logiciel que vous prévoyez d'exécuter prend-il encore en charge cette génération ?
  • Pouvez-vous obtenir une carte entière ou une VM dédiée si une tranche ne suffit plus, et à quoi ressemble l'isolation dans ce cas ?
  • Quels CPU, quelle mémoire et quel stockage obtenez-vous en plus du GPU, et sont-ils mutualisés avec le reste de vos charges de travail ?

Sources

À lire aussi

Essayez-le sur Kube-DC

Nos forfaits GPU ajoutent à un pool Kube-DC une tranche d'un NVIDIA V100 partagé : 25 %, 50 % ou 100 % de la carte, avec la tranche de mémoire appliquée. Vous bénéficiez en plus de vCPU dédiés, d'un stockage NVMe reposant sur Ceph, d'une IPv4 publique dédiée, d'un stockage objet compatible S3 et de vos propres clusters Kubernetes administrés par le tenant, avec un support par e-mail et ticket 24h/24 et 7j/7 et un objectif de résolution de 4 heures. Nous avons exécuté un vrai LLM et un agent IA dessus de bout en bout, et chaque étape de cet article est reproductible.

Découvrir Kube-DC Kubernetes