- Authors

- Name
- Phillip Pham
- @ddppham
GPU Workloads auf Kubernetes: NVIDIA Device Plugin und Scheduling
TL;DR
- GPU-Workloads auf Kubernetes erfordern das NVIDIA Device Plugin (oder den GPU Operator) auf jedem GPU-Node
- GPUs werden als Extended Resources (
nvidia.com/gpu) angefordert -- sie sind nicht teilbar (1 GPU = 1 Container, ohne MIG/Time-Slicing) - Node Affinity und Taints/Tolerations sorgen dafuer, dass GPU-Pods nur auf GPU-Nodes laufen
- Monitoring ueber DCGM Exporter + Prometheus zeigt GPU-Auslastung, Temperatur und Memory
- Fuer Multi-GPU-Training brauchen Sie spezielle Frameworks (PyTorch DDP, Horovod) -- Kubernetes allein verteilt kein Training
Warum GPUs auf Kubernetes?
Wer ML-Modelle trainiert oder GPU-beschleunigte Inferenz betreibt, steht vor der Frage: Bare-Metal-Server mit manueller Verwaltung oder Kubernetes als Orchestrator? Kubernetes bietet hier klare Vorteile:
- Scheduling: Automatische Zuweisung von GPU-Ressourcen an Jobs
- Multi-Tenancy: Mehrere Teams teilen sich einen GPU-Pool mit ResourceQuotas
- Reproducibility: GPU-Jobs als deklarative YAML-Specs versionierbar
- Integration: GPU-Training laesst sich in CI/CD-Pipelines (Argo Workflows, Kubeflow) einbinden
Die Herausforderung: GPUs sind keine Standard-Kubernetes-Ressourcen wie CPU oder Memory. Sie benoetigen einen Device Plugin, der die GPUs dem Kubelet bekannt macht.
Weitere Hintergruende zu Kubernetes fuer ML finden Sie in unserem Artikel zu MLOps auf Kubernetes.
Architektur: Wie Kubernetes GPUs verwaltet
Die Kette ist: NVIDIA-Treiber auf dem Host */} NVIDIA Container Toolkit (frueher nvidia-docker) */} NVIDIA Device Plugin als DaemonSet */} kubelet erkennt GPUs als Extended Resources */} Scheduler kann Pods auf GPU-Nodes zuweisen.
Option 1: NVIDIA Device Plugin direkt installieren
Das Device Plugin ist ein DaemonSet, das auf jedem GPU-Node laeuft und die verfuegbaren GPUs als Extended Resources registriert.
Voraussetzungen
- NVIDIA-Treiber auf den Nodes installiert (z.B. 535.x oder neuer)
- NVIDIA Container Toolkit installiert und als Default-Runtime konfiguriert
- Kubernetes 1.26+
DaemonSet deployen
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nvidia-device-plugin-daemonset
namespace: kube-system
spec:
selector:
matchLabels:
name: nvidia-device-plugin-ds
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
name: nvidia-device-plugin-ds
spec:
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
priorityClassName: system-node-critical
containers:
- name: nvidia-device-plugin-ctr
image: nvcr.io/nvidia/k8s-device-plugin:v0.17.0
env:
- name: FAIL_ON_INIT_ERROR
value: "false"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
# Oder direkt via kubectl:
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.17.0/deployments/static/nvidia-device-plugin.yml
# Pruefen, ob GPUs erkannt werden:
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, gpus: .status.allocatable["nvidia.com/gpu"]}'
Option 2: NVIDIA GPU Operator (empfohlen)
Der GPU Operator automatisiert die gesamte Kette: Treiber-Installation, Container Toolkit, Device Plugin, DCGM Exporter und optional MIG-Konfiguration. Das ist der empfohlene Weg, wenn Sie nicht jeden Node manuell vorbereiten moechten.
# Helm Repository hinzufuegen
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
# GPU Operator installieren
helm install gpu-operator nvidia/gpu-operator \
--namespace gpu-operator \
--create-namespace \
--set driver.enabled=true \
--set toolkit.enabled=true \
--set devicePlugin.enabled=true \
--set dcgmExporter.enabled=true
# Status pruefen
kubectl get pods -n gpu-operator
# Erwartete Pods:
# nvidia-driver-daemonset-*
# nvidia-container-toolkit-daemonset-*
# nvidia-device-plugin-daemonset-*
# nvidia-dcgm-exporter-*
# gpu-feature-discovery-*
Der GPU Operator eignet sich besonders fuer Cloud-Umgebungen (EKS, AKS, GKE), wo Nodes dynamisch hinzukommen.
GPU-Pods deployen
Einfacher GPU-Pod
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
restartPolicy: Never
containers:
- name: cuda-test
image: nvcr.io/nvidia/cuda:12.3.1-base-ubuntu22.04
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1
kubectl apply -f gpu-test.yaml
kubectl logs gpu-test
# Sollte die GPU-Informationen anzeigen (Modell, Memory, Treiber-Version)
Wichtig: nvidia.com/gpu wird nur unter limits angegeben. Kubernetes setzt requests automatisch gleich limits fuer Extended Resources. GPUs sind nicht ueberbuchbar.
ML-Training Job mit PyTorch
apiVersion: batch/v1
kind: Job
metadata:
name: pytorch-training
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: trainer
image: nvcr.io/nvidia/pytorch:24.01-py3
command:
- python
- -c
- |
import torch
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"GPU: {torch.cuda.get_device_name(0)}")
# Ihr Training-Script hier
resources:
limits:
nvidia.com/gpu: 1
memory: 16Gi
cpu: "4"
requests:
memory: 8Gi
cpu: "2"
volumeMounts:
- name: data
mountPath: /data
- name: models
mountPath: /models
volumes:
- name: data
persistentVolumeClaim:
claimName: training-data
- name: models
persistentVolumeClaim:
claimName: model-storage
GPU-Scheduling mit Node Affinity und Taints
In einem gemischten Cluster (CPU- und GPU-Nodes) wollen Sie sicherstellen, dass GPU-Pods nur auf GPU-Nodes landen und CPU-Pods nicht versehentlich GPU-Nodes blockieren.
Taints auf GPU-Nodes setzen
# GPU-Nodes mit Taint versehen
kubectl taint nodes gpu-node-1 nvidia.com/gpu=present:NoSchedule
kubectl taint nodes gpu-node-2 nvidia.com/gpu=present:NoSchedule
# Labels setzen fuer Node Affinity
kubectl label nodes gpu-node-1 gpu-type=a100
kubectl label nodes gpu-node-2 gpu-type=t4
Pod mit Toleration und Node Affinity
apiVersion: v1
kind: Pod
metadata:
name: gpu-inference
spec:
tolerations:
- key: nvidia.com/gpu
operator: Equal
value: present
effect: NoSchedule
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: gpu-type
operator: In
values:
- a100
containers:
- name: inference
image: your-inference-image:latest
resources:
limits:
nvidia.com/gpu: 1
GPU-Typen: Wann welche GPU?
| GPU | VRAM | Typischer Einsatz | Preis (Cloud, ca.) |
|---|---|---|---|
| T4 | 16 GB | Inference, leichtes Training | $0.35/h |
| A10G | 24 GB | Mittleres Training, Inference | $1.00/h |
| A100 40GB | 40 GB | Grosses Training, Multi-GPU | $3.00/h |
| A100 80GB | 80 GB | LLM-Training, grosse Modelle | $4.50/h |
| H100 | 80 GB | State-of-the-Art Training | $8.00/h |
ResourceQuotas fuer GPU-Fair-Sharing
Wenn mehrere Teams GPUs teilen, verhindern ResourceQuotas, dass ein Team alle GPUs belegt:
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota-team-ml
namespace: team-ml
spec:
hard:
requests.nvidia.com/gpu: "4"
limits.nvidia.com/gpu: "4"
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota-team-cv
namespace: team-cv
spec:
hard:
requests.nvidia.com/gpu: "2"
limits.nvidia.com/gpu: "2"
Mehr zu Multi-Tenancy und Resource Management: Kubernetes Multi-Tenancy und Kubernetes Resource Management.
GPU-Monitoring mit DCGM Exporter
Der DCGM (Data Center GPU Manager) Exporter stellt GPU-Metriken fuer Prometheus bereit. Der GPU Operator installiert ihn automatisch; bei manueller Installation:
helm install dcgm-exporter nvidia/dcgm-exporter \
--namespace monitoring \
--create-namespace \
--set serviceMonitor.enabled=true
Wichtige Prometheus-Metriken
| Metrik | Beschreibung |
|---|---|
DCGM_FI_DEV_GPU_UTIL | GPU-Auslastung in Prozent |
DCGM_FI_DEV_MEM_COPY_UTIL | Memory-Auslastung in Prozent |
DCGM_FI_DEV_GPU_TEMP | GPU-Temperatur in Grad Celsius |
DCGM_FI_DEV_POWER_USAGE | Stromverbrauch in Watt |
DCGM_FI_DEV_FB_FREE | Freier GPU-Speicher in MiB |
DCGM_FI_DEV_FB_USED | Belegter GPU-Speicher in MiB |
Fuer ein umfassendes Monitoring-Setup: GPU Monitoring auf Kubernetes und Kubernetes Monitoring und Observability.
Troubleshooting
# GPU nicht erkannt? Drei Checks:
# 1. Device Plugin laeuft?
kubectl get pods -n kube-system -l name=nvidia-device-plugin-ds
# 2. Node hat GPU-Kapazitaet?
kubectl describe node <gpu-node> | grep -A5 "Allocatable"
# 3. Pod haengt in Pending?
kubectl describe pod <gpu-pod> | tail -20
# Haeufige Ursachen: Insufficient nvidia.com/gpu, fehlende Toleration, ResourceQuota
Bei "CUDA out of memory": Kubernetes kann GPU-Memory nicht limitieren -- nvidia.com/gpu: 1 reserviert die gesamte GPU. Loesungen: Batch-Size reduzieren, Gradient Accumulation nutzen, oder auf eine GPU mit mehr VRAM wechseln.
Kostenoptimierung
- Spot/Preemptible Nodes fuer Training-Jobs nutzen (bis 70% guenstiger)
- GPU Time-Slicing aktivieren, wenn mehrere leichte Inferenz-Workloads eine GPU teilen sollen
- Cluster Autoscaler konfigurieren, damit GPU-Nodes nur bei Bedarf hochgefahren werden
- PriorityClasses nutzen, damit wichtige Jobs weniger wichtige verdraengen koennen
Weitere Tipps zur Kostenoptimierung: Kubernetes Autoscaling und Kosten sparen.
Fazit
GPU-Workloads auf Kubernetes zu betreiben ist kein Hexenwerk, erfordert aber ein sauberes Setup: NVIDIA Device Plugin oder GPU Operator, korrekte Taints und Tolerations, ResourceQuotas fuer Fair-Sharing und Monitoring mit DCGM Exporter. Der groesste Fehler ist, GPUs ohne Monitoring laufen zu lassen -- eine ungenutzte A100 bei 4 EUR/Stunde summiert sich schnell.
Sie planen GPU-Workloads auf Kubernetes oder moechten Ihre bestehende GPU-Infrastruktur optimieren? Erfahren Sie mehr ueber unsere Kubernetes Consulting-Angebote fuer ML/AI-Workloads.
Kubernetes-Beratung gesucht?
Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
Kubernetes GPU-Auslastung optimieren: MIG und Time-Slicing
GPU-Auslastung in Kubernetes von 30% auf über 75% steigern mit MIG und Time-Slicing. NVIDIA GPU Operator Setup und DCGM Monitoring Anleitung.
GPU-Workloads in Kubernetes: Scheduling, Sharing und Kosten
GPU-Auslastung in Kubernetes von 30% auf über 70% steigern mit NVIDIA Device Plugin, MIG, Time-Slicing und Volcano Scheduler.
CUDA Cores Vergleich: GPU-Auswahl für ML auf Kubernetes
NVIDIA A100 vs H100 vs T4 im Vergleich: Welche GPU für welchen ML-Workload auf Kubernetes und wie ein AI-Startup damit 180.000 Euro jährlich spart.
Kubernetes GPU Cluster aufbauen: Setup und Betrieb
Kubernetes GPU Cluster für AI/ML-Workloads einrichten: NVIDIA GPU Operator, GPU Sharing mit MIG und Kostenoptimierung für deutsche Unternehmen.
KI-Qualitätskontrolle auf Kubernetes mit YOLO
KI-gestützte Qualitätskontrolle auf Kubernetes: Kamera-zu-Inference-Pipeline mit YOLO und Triton Inference Server für automatisierte Defekterkennung.