Blog · 7. September 2026 · 8 Min. Lesezeit

Kubernetes für KI: LLMs auf GPU-Nodes

Mehrere baugleiche Server-Gehäuse mit blauer Beleuchtung nebeneinander in einem Rechenzentrum
Foto: panumas nikhomkhai / Pexels

Kubernetes für KI heißt vor allem: ein LLM auf GPU-Nodes betreiben, ohne dass der Cluster die GPU ignoriert. Das gelingt, indem du GPUs über das Device-Plugin-Framework als schedulierbare Ressource nvidia.com/gpu bekannt machst, sie im Pod mit Requests und Limits anforderst und den Inference-Server als ganz normales Deployment mit Probes und Autoscaling betreibst. Kubernetes-LLM-Inferenz unterscheidet sich damit weniger von anderen Workloads, als es zunächst wirkt, nur die Ressource ist neu und die Fehlermodi sind andere.

Ich betreibe produktionsreife Kubernetes-Cluster auf Hetzner und bin Kubestronaut der CNCF, alle fünf Zertifizierungen. GPUs stecken in diesen Clustern bisher nicht: Mein Qwen3.8-Modell läuft auf einem eigenen Nvidia DGX Spark außerhalb von Kubernetes. Genau dieser Kontrast, produktionsreifer Cluster hier, Einzelserver dort, zeigt gut, wann welches Setup passt. Alle meine Beiträge zu Kubernetes findest du auf der Seite Kubernetes.

GPU-Nodes im Cluster: Device Plugin und Node Feature Discovery

Für Kubernetes ist eine GPU zunächst unsichtbar. CPU und Arbeitsspeicher kennt der Scheduler von Haus aus, eine Grafikkarte nicht. Sichtbar wird sie erst über das Device-Plugin-Framework: Ein herstellerspezifisches Device Plugin läuft auf jeder Node, meldet sich beim Kubelet an und veröffentlicht die vorhandenen GPUs als eigene Ressource, bei Nvidia als nvidia.com/gpu. Ohne dieses Plugin sieht der Scheduler die GPU nicht, ganz unabhängig davon, wie viele physisch verbaut sind.

In einem Cluster mit mehreren GPU-Typen kommt Node Feature Discovery dazu. Sie erkennt Hardwaremerkmale automatisch und setzt sie als Labels auf jede Node; die GPU-spezifischen Angaben wie Speichergröße und Kartenmodell steuert die darauf aufbauende GPU Feature Discovery bei, die der GPU Operator gleich mitbringt. Darauf kannst du im Pod mit Node-Affinity zielen, etwa wenn ein großes Modell nur auf Nodes mit ausreichend Speicher laufen darf. Details zum Zusammenspiel von Device Plugin, Labels und Scheduler stehen in der Kubernetes-Dokumentation zum GPU-Scheduling.

Der GPU Operator: Nvidia-Software ohne Handarbeit

Treiber, Container-Runtime, Device Plugin und Monitoring auf jeder GPU-Node einzeln zu installieren, ist mühsam und fehleranfällig, vor allem wenn Nodes durch Autoscaling laufend entstehen und verschwinden. Genau dafür gibt es den Nvidia GPU Operator: Er installiert und pflegt Treiber, Device Plugin, Container-Toolkit, automatische Node-Kennzeichnung und ein DCGM-basiertes Monitoring, sobald du ihn im Cluster ausrollst. Neue GPU-Nodes werden dadurch weitgehend wie CPU-Nodes behandelt, ohne dass du ein eigenes GPU-Image bauen musst.

Für einen einzelnen, stabilen GPU-Server lohnt sich dieser Aufwand oft nicht, dort reicht eine manuelle Treiberinstallation. Sobald aber mehrere GPU-Nodes im selben Cluster laufen und sich verändern, spart der Operator spürbar Handarbeit. Details und die Installationswege stehen im Repository des GPU Operators.

GPUs anfordern: nvidia.com/gpu in Requests und Limits

Sobald der Scheduler GPUs sieht, forderst du sie im Pod wie jede andere Ressource an, nur mit einer Einschränkung: GPUs gehören in limits, nicht zwingend zusätzlich in requests. Setzt du nur ein Limit, übernimmt Kubernetes diesen Wert automatisch als Request. Gibst du beides an, müssen beide Zahlen identisch sein, ein Request ohne passendes Limit ist nicht erlaubt. Anders als bei CPU sind GPU-Anforderungen außerdem immer ganze Zahlen, eine halbe GPU gibt es ohne Zusatzmechanismus nicht.

apiVersion: v1
kind: Pod
metadata:
  name: qwen-inference
  labels:
    app: qwen-inference
spec:
  containers:
    - name: sglang-server
      image: my-registry/sglang-server:latest
      resources:
        limits:
          nvidia.com/gpu: "1"
          memory: "32Gi"
          cpu: "4"
      ports:
        - containerPort: 30000

Findet der Scheduler keine Node mit genug freier nvidia.com/gpu-Kapazität, bleibt der Pod in Pending, exakt wie bei fehlendem CPU- oder Speicherplatz. Wie Kubernetes Requests und Limits generell auswertet und welche Fallstricke dabei lauern, habe ich ausführlich in Kubernetes Requests und Limits erklärt beschrieben, das gilt für GPUs im Kern genauso.

Eine GPU für mehrere Pods: Time-Slicing und seine Grenzen

GPUs sind teuer, und nicht jeder Workload braucht eine ganze Karte für sich. Der GPU Operator bietet dafür Time-Slicing an: Über eine ConfigMap mit einem replicas-Feld meldet die Node mehr GPU-Ressourcen, als physisch vorhanden sind, etwa vier statt einer bei replicas: 4. Mehrere Pods teilen sich dann dieselbe physische GPU im Zeitscheiben-Verfahren.

Wichtig ist die Einschränkung dabei: Time-Slicing bietet keine Speicher- oder Fehlerisolation zwischen den Pods, und ein Pod mit einer höheren Anforderung bekommt dadurch keinen größeren Rechenanteil, alle Replicas teilen sich die Zeit zu gleichen Teilen. Für kurze, burst-artige Jobs oder Entwicklungsumgebungen ist das ein brauchbarer Kompromiss. Für ein einzelnes großes Sprachmodell, dessen Gewichte allein schon einen Großteil des GPU-Speichers belegen, etwa mein Qwen3.8-Modell mit seinem NVFP4-Checkpoint von rund 22 Gigabyte, ergibt Time-Slicing wenig Sinn: Der knappe Speicher ist dort der Engpass, nicht die Rechenzeit.

Der LLM-Server als Kubernetes-Deployment: Probes und Modell-Storage

Ein einzelner Pod wird bei einem Absturz nicht ersetzt. Für einen LLM-Server gehört deshalb ein Deployment darum, das die gewünschte Zahl an Replikaten hält und einen abgestürzten Pod automatisch ersetzt. Zwei Punkte unterscheiden LLM-Server dabei deutlich von einer typischen Web-Anwendung.

Erstens die Probes: Ein Sprachmodell braucht oft mehrere Minuten, bis die Gewichte geladen sind und der Server antwortet, deutlich länger als ein Webserver zum Starten braucht. Setzt du initialDelaySeconds oder failureThreshold zu knapp, killt Kubernetes den Container mitten im Ladevorgang, bevor er überhaupt eine Chance hatte. vLLM etwa bringt dafür einen eigenen /health-Endpunkt mit, den du als Readiness- und Liveness-Probe gegen den Serving-Port ansprichst, mit großzügigem Startverhalten.

Zweitens der Speicher: Modellgewichte sind mehrere Gigabyte groß, und niemand will sie bei jedem Pod-Neustart neu herunterladen. Ein Persistent Volume Claim für den Modell-Cache löst das: Der Pod bindet das PVC ein, statt bei jedem Start erneut zu laden. Läuft der Server auf mehreren Nodes gleichzeitig, braucht das Volume einen Access Mode, der gleichzeitiges Lesen von mehreren Nodes erlaubt, oder du hältst je Node eine lokale Kopie vor.

Skalieren nach Auslastung statt nach CPU

Standard-HPA misst CPU-Auslastung, und genau die sagt bei LLM-Inferenz wenig aus: Die GPU ist der Engpass, die CPU eines Inference-Pods dümpelt oft bei wenigen Prozent, egal wie voll die Warteschlange ist. Sinnvoller sind eigene Metriken, etwa Anfragen pro Sekunde, die Länge der internen Warteschlange oder die GPU-Auslastung über einen Exporter wie DCGM, angebunden über Prometheus-Adapter oder KEDA. Wie HPA grundsätzlich funktioniert, welche Metriken es unterstützt und wo die üblichen Stolperfallen liegen, steht in Kubernetes Autoscaling mit HPA.

Ein Server oder ein Cluster: wann ein DGX Spark reicht

Nicht jede LLM-Inferenz braucht Kubernetes. Mein Qwen3.8-27B läuft unter SGLang direkt als systemd-Dienst auf einem Nvidia DGX Spark, ohne Cluster, ohne Device Plugin, ohne HPA. Bei mir gemessen: rund 50,7 Tokens pro Sekunde beim Decodieren. Diese Zahl gilt genau für diesen Aufbau, den NVFP4-Checkpoint von Qwen3.8-27B unter SGLang auf dieser einen Maschine, mit einer einzelnen Anfrage ohne Batching. Auf ein anderes Modell, eine andere Quantisierung oder mehrere gleichzeitige Anfragen lässt sie sich nicht übertragen. Für dieses Szenario wäre ein Kubernetes-Cluster reiner Overhead, den niemand ausnutzt.

Ein Cluster mit GPU-Nodes lohnt sich, sobald mehrere Modelle oder Versionen parallel laufen sollen, die Last schwankt und automatisch mitwachsen soll, mehrere Teams oder Kunden denselben Server-Pool teilen, oder eine Node ausfallen darf, ohne dass der Dienst steht. Das ist dieselbe Abwägung, die ich aus meinen GPU-losen Produktionsclustern kenne, nur mit einer teureren Ressource in der Waagschale.

Kriterium Einzelner Server (z. B. DGX Spark) Kubernetes-Cluster mit GPU-Nodes
Modelle parallel eines, dauerhaft geladen mehrere, je Deployment oder Namespace
Skalierung bei Lastspitzen keine, feste Kapazität HPA verteilt zusätzliche Replikate
Ausfallsicherheit ein Server, ein Ausfallpunkt Node-Ausfall wird automatisch umverteilt
Administrationsaufwand ein systemd-Dienst GPU Operator, Monitoring, Storage, RBAC
Typischer Fall Einzelperson oder kleines Team, ein festes Modell mehrere Teams, wechselnde Workloads

Wo genau bei dir die Grenze liegt, hängt von der Zahl der Nutzer und davon ab, wie viel Ausfallzeit du akzeptierst. Wie SGLang, Qwen3.8 und der DGX Spark bei mir konkret laufen, inklusive Messwerten, beschreibe ich in Qwen 3.8 lokal: Erfahrung mit DGX Spark.

Häufige Fragen

Brauche ich zwingend den Nvidia GPU Operator für GPU-Nodes in Kubernetes?

Nein. Für einen einzelnen, stabilen GPU-Node reicht ein manuell installierter Treiber mit Device Plugin oft aus. Der GPU Operator lohnt sich, sobald Nodes automatisch entstehen oder ausgetauscht werden, etwa in Autoscaling-Clustern, weil er Treiber, Plugin und Monitoring bei jeder neuen Node automatisch einrichtet.

Kann ein Pod eine halbe GPU bekommen?

Standardmäßig nicht: nvidia.com/gpu wird immer als ganze Zahl angefordert. Geteilte Nutzung geht nur über Zusatzmechanismen wie Time-Slicing oder Multi-Instance GPU, beide mit eigenen Kompromissen bei Isolation und Leistung.

Skaliert HPA einen Inference-Server sinnvoll nach CPU-Auslastung?

Kaum. Bei LLM-Inferenz ist die GPU der Engpass, die CPU-Last bleibt oft niedrig, egal wie ausgelastet der Server tatsächlich ist. Aussagekräftiger sind eigene Metriken wie Anfragen pro Sekunde oder GPU-Auslastung über einen Exporter.

Muss das Modell bei jedem Pod-Neustart neu geladen werden?

Nur, wenn die Gewichte nicht in einem Persistent Volume liegen. Mit einem PVC für den Modell-Cache bindet ein neu gestarteter Pod die Datei nur noch ein, statt sie erneut herunterzuladen, was bei mehreren Gigabyte den Unterschied zwischen Sekunden und Minuten macht.

Wie du weitermachst

Requests, Limits, Probes und Autoscaling sind an sich keine GPU-Spezialität, sie gelten für jedes Deployment, GPU hin oder her. Ausführlich mit allen Beispielen steht das in Kapitel 8 meines Kubernetes-Praxisbuchs bei Rheinwerk. Alle Informationen zum Buch findest du auf meiner Kubernetes-Seite.

Mein Vorschlag für den nächsten Schritt: Wenn du schon einen Kubernetes-Cluster betreibst, prüfe zuerst, ob eine GPU-Node überhaupt nötig ist, bevor du den GPU Operator ausrollst, vielleicht reicht für den Anfang ein einzelner Server. Details zum Serving selbst liefert die vLLM-Dokumentation zum Kubernetes-Deployment.

Kevin Welter

Kevin Welter

Entwickler, IT-Architekt, Fachbuchautor (Kubernetes, Cloud-Infrastrukturen) und Speaker. Betreibt sein Business mit einer KI-Belegschaft aus acht KI-Mitarbeitern und zeigt Selbstständigen in seiner Community, wie sie ihren ersten KI-Mitarbeiter einstellen.

Mehr über KI-Mitarbeiter

Kubernetes von den Grundlagen bis zum produktionsreifen Cluster

Zum Buch