Blog
GPU-FinOps auf Kubernetes: Autoscaling, Quotas und Kosten pro Job
Was eine ungenutzte GPU kostet: Node-Group-Autoscaling, Batch-Scheduling, Quotas und FinOps-Tracking. Die fünf Fehler, die die Auslastung deckeln.
Hidora-Artikel vom 13. Mai 2026. Zahlen, Preise und Vergleiche gelten zu diesem Datum.
Intelligentes Autoscaling, Batch Scheduling und Quoten: den GPU-ROI maximieren
GPU-Kubernetes-Cluster verursachen erhebliche Kosten und zeigen dabei häufig suboptimale Auslastung. Laut Sedai arbeiten klassische Autoscaler (HPA, VPA, Cluster Autoscaler) reaktiv: Sie warten, bis Auslastungsschwellen überschritten sind, bevor sie Ressourcen anpassen. Diese inhärente Verzögerung erzeugt zwei teure Fehlbilder: vorbeugendes Overprovisioning, um Spitzen aufzufangen (laut Kedify 30 bis 50 % des GPU-Budgets verschwendet), und chronisches Underprovisioning, das SLAs verschlechtert und Nutzende frustriert.
GPU-Optimierung in Kubernetes verlangt einen systemischen Ansatz aus vier technischen Hebeln, intelligentes Autoscaling mit Karpenter, um optimale GPU-Knoten dynamisch bereitzustellen, Batch Scheduling über Volcano oder Kueue, um Bin-Packing zu maximieren und Fragmentierung zu beseitigen, hierarchische Quoten, die verhindern, dass ein Team die Ressourcen monopolisiert, und granulare Observability über DCGM, um Ineffizienz zu erkennen. Dieser Beitrag beschreibt die vier Hebel, zeigt die in Produktion beobachteten operativen Fallen und schlägt ein schrittweises Vorgehen vor, validiert auf Multi-Tenant-Clustern mit Trainings- und Inferenzlasten.
Was von Hikube kommt und was aus dem Ökosystem. Auf Hikube betreibt Hidora SA die Control Plane, das CNI ist Cilium, und die Worker, GPUs eingeschlossen, werden als Node-Gruppen dimensioniert, die der Last folgen. Alles Weitere, was dieser Artikel nennt (Karpenter, Volcano, KEDA, Kyverno, Autoscaler von Dritten), gehört zum Kubernetes-Ökosystem: Komponenten, die Sie selbst in Ihrem Cluster installieren und betreiben, keine Katalogfunktionen, und nichts hier macht daraus eine Produktzusage. Ein Punkt lässt sich gar nicht übertragen: Hikube bietet keine Spot- oder Preemptible-Instanzen, die dort beschriebenen Einsparungen gelten hier also nicht. Verwalteter Umfang: Managed Kubernetes, GPU-Preise, GPU.
Der Blickwinkel dieses Artikels: was ein GPU-Job kostet und wie man ihn senkt, Autoscaling, Quoten, Kosten je Job. Es geht um die Kosten: das technische Teilen zwischen Teams steht in MIG, Time-Slicing und Quoten.
Die vier Hebel der GPU-Optimierung in Kubernetes
Die wirksame Optimierung von GPU-Ressourcen in Kubernetes ruht auf vier sich ergänzenden technischen Säulen, von denen jede eine eigene Quelle der Verschwendung angeht.
1. Dynamisches Autoscaling: Karpenter gegen Cluster Autoscaler
Cluster Autoscaler (CA), das historische System, arbeitet über AWS Auto Scaling Groups (ASG) oder deren Cloud-Entsprechungen. CA erkennt nicht planbare Pods, ermittelt die zu ihren Bedingungen passende Node Group und fordert die ASG auf, Knoten hinzuzufügen. Diese indirekte Architektur bringt drei kritische Grenzen: eine Bereitstellungszeit von 3 bis 5 Minuten (Pod-Erkennung plus ASG-Scaling plus Instanz-Boot), eine auf vordefinierte Node Groups begrenzte Granularität (eine m5.8xlarge lässt sich nicht dynamisch anfordern, wenn nur m5.4xlarge konfiguriert ist) und Ressourcenfragmentierung (Pods, die 6 vCPU anfordern, auf Knoten mit 8 vCPU lassen 2 vCPU ungenutzt).
Karpenter, seit August 2024 in stabiler v1.0.0, verändert das Kubernetes-Autoscaling, indem es direkt mit der EC2-API spricht. Wird ein Pod nicht planbar, wertet Karpenter seine Bedingungen aus (CPU, RAM, GPU, Zone, Architektur), fragt die EC2-API nach den passenden Instanztypen, sortiert nach Kosten (price-capacity-optimized), und stellt die optimale Instanz in 45 bis 60 Sekunden bereit. Daraus folgen drei messbare Vorteile: dreifache Geschwindigkeit gegenüber CA (45 s statt 3 bis 5 min gemäss Medium-Benchmarks 2025), nahezu unbegrenzte Granularität (Karpenter wählt aus über 800 EC2-Instanztypen ohne Vorkonfiguration) und bessere Wirtschaftlichkeit (die automatische Konsolidierung ersetzt untergenutzte Knoten durch günstigere Instanzen).
Karpenter-Konfiguration für GPU:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-pool
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-gpu-count
operator: Gt
values: ["0"] # Jede Instanz mit GPU
- key: karpenter.k8s.aws/instance-gpu-name
operator: In
values: ["a100", "h100"] # Nur A100 oder H100
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"] # Mix Spot/On-Demand
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-class
limits:
cpu: "1000"
memory: 4000Gi
nvidia.com/gpu: "32" # Max. 32 GPUs in diesem Pool
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30m # Konsolidierung nach 30 min Unternutzung
Karpenter bringt automatische Konsolidierung, Fällt ein GPU-Knoten während 30 Minuten (konfigurierbar) unter 50 % Auslastung, verschiebt Karpenter seine Pods auf andere Knoten und beendet die Instanz. Diese im Standard-Cluster-Autoscaler fehlende Funktion senkt die Kosten laut nOps um 20 bis 35 %, bei weniger als 1 % Spot-Terminierungen dank eingebauter guter Praxis (Diversifizierung der Instanzen über mehrere AZ, laufende Neubewertung der Lasten).
2. Batch Scheduling: Volcano und Kueue für Trainingslasten
Der Standard-Scheduler von Kubernetes arbeitet auf Pod-Ebene, Jeder Pod wird einzeln bewertet und platziert, sobald ein Knoten seine Bedingungen erfüllt. Bei verteilten Lasten, in denen alle Pods gleichzeitig starten müssen, scheitert dieser Ansatz. Ein PyTorchJob mit 16 Pods (16 GPUs) kann mit 12 geplanten Pods und 4 dauerhaft in Pending enden und blockiert damit die bereits zugeteilten 12 GPUs, ohne dass das Training vorankommt.
Volcano, ein CNCF-Projekt mit wachsender Verbreitung im Jahr 2025, setzt Gang Scheduling über PodGroups um: Entweder werden alle Pods der Gruppe gleichzeitig geplant oder keiner. Volcano hält die Pods in Pending, bis genug Ressourcen für die ganze Gruppe verfügbar sind, und plant sie dann atomar. Diese Garantie beseitigt Deadlocks und GPUs, die auf fehlende Pods warten. Die InfraCloud-Benchmarks 2025 zeigen, dass Volcano die GPU-Fragmentierung bei verteilten Trainingslasten gegenüber dem Standard-Scheduler um 40 % senkt.
Beispiel einer Volcano-PodGroup:
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: llama-training
spec:
minAvailable: 16 # Gang Scheduling: 16 Pods oder nichts
schedulerName: volcano
plugins:
env: []
svc: []
policies:
- event: PodEvicted
action: RestartJob
tasks:
- replicas: 16
name: worker
template:
spec:
containers:
- name: pytorch
image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
resources:
limits:
nvidia.com/gpu: 1
cpu: "8"
memory: 32Gi
Kueue, von der Kubernetes SIG Scheduling entwickelt und seit 2024 produktionsreif, setzt eine Warteschlangenschicht vor den Scheduler. Workloads (Jobs, PyTorchJobs, RayJobs) werden in LocalQueues eingereicht, die an ClusterQueues mit konfigurierten Quoten gebunden sind. Kueue simuliert das Scheduling und lässt den Workload nur zu, wenn Ressourcen verfügbar sind und die Quoten eingehalten werden. Cohorts erlauben mehreren ClusterQueues, ungenutzte Quoten mit gewichteter Fairness zu teilen: Nutzt Team A nur 50 % seiner Quote, kann Team B den Überschuss vorübergehend ausleihen.
Yunikorn, ein Apache-Projekt aus dem Hadoop-Umfeld, bietet einen universellen Scheduler mit hierarchischen Queues und Fairness-Policies (DRF, Dominant Resource Fairness). Anders als Volcano, das Custom Resources verlangt (VolcanoJob), fügt sich Yunikorn als Ersatz-Scheduler ein und behandelt Standard-Kubernetes-Lasten nativ. Die PEARC-Benchmarks 2024 zeigen, dass Yunikorn die Ausführungszeiten von Workflows um das 4,6-Fache senkt und die Cluster-Auslastung bei wissenschaftlichen Multi-Tenant-Lasten gegenüber dem Standard-Scheduler verdreifacht.
| Scheduler | Gang Scheduling | Hierarchische Quoten | Fairness | Optimaler Anwendungsfall |
|---|---|---|---|---|
| Kubernetes-Standard | Nein | ResourceQuota (flach) | Priority FIFO | Single-Pod-Lasten, Inferenz |
| Volcano | Ja (PodGroup) | Über Queues | DRF, Proportion | Verteiltes Training, HPC |
| Kueue | Über Admission | ClusterQueue + Cohorts | Borrowing mit Gewichten | Mehrere Teams, strikte Quoten |
| Yunikorn | Ja | Ja (YARN-artig) | Natives DRF | Hybrid K8s/Hadoop, wissenschaftliche Lasten |
3. Resource Quotas und Policies: Monopolisierung verhindern
Kubernetes-ResourceQuotas begrenzen den Gesamtverbrauch je Namespace. Eine typische GPU-Quote wie requests.nvidia.com/gpu: "16" hindert einen Namespace daran, mehr als 16 GPUs gleichzeitig zu belegen. LimitRanges definieren ein Minimum und Maximum je Pod: Pods blockieren, die 0 GPUs anfordern (Konfigurationsfehler) oder mehr als 8 (Monopolisierungsrisiko).
Diese nativen Mechanismen haben zwei Grenzen. Erstens wirken sie auf Namespace-Ebene, nicht auf Team- oder Projektebene: Eine Organisation mit 10 Teams braucht 10 getrennte Namespaces, was RBAC und Networking verkompliziert. Zweitens sind sie statisch: Die ungenutzte Quote eines Teams lässt sich bei einer Lastspitze nicht dynamisch einem anderen zuweisen.
Kueue löst beides über hierarchische ClusterQueues und Cohorts. Eine ClusterQueue steht für einen Ressourcenpool mit einer Nominalquote. Cohorts ermöglichen Borrowing: Mehrere ClusterQueues bilden ein Cohort und teilen ihre ungenutzten Quoten nach konfigurierten Gewichten. Beispiel: Team A mit 20 GPUs Quote, Team B mit 10, gemeinsames Cohort. Nutzt Team A nur 10 GPUs, kann Team B bis zu 10 weitere ausleihen (total 20), die automatisch freigegeben werden, sobald Team A seine Nominalkapazität wieder braucht.
Kueue-Konfiguration mit Cohorts:
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: a100-80gb
spec:
nodeLabels:
nvidia.com/gpu.product: A100-SXM4-80GB
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: team-research
spec:
cohort: shared-gpu # Cohort-Mitglied, für Borrowing
namespaceSelector: {}
resourceGroups:
- coveredResources: ["nvidia.com/gpu"]
flavors:
- name: a100-80gb
resources:
- name: nvidia.com/gpu
nominalQuota: 20 # Garantierte Quote
borrowingLimit: 10 # Kann bis zu 10 GPUs leihen
Preemption-Policies erlauben Lasten hoher Priorität, Ressourcen zurückzuholen, indem sie Lasten niedriger Priorität verdrängen (beenden). Volcano setzt konfigurierbare Preemption um: Produktionslasten (hohe Priorität) können Dev-/Test-Lasten (niedrige Priorität) verdrängen, wenn der Cluster gesättigt ist. Die Preemption folgt festen Regeln (den Yunikorn-Gesetzen): Verdrängen darf nur, wessen Priorität strikt höher ist, die Preemption respektiert PodDisruptionBudgets, und verdrängte Lasten werden automatisch neu eingereiht.
4. Observability und FinOps: messen, um zu optimieren
Ohne Messung zu optimieren heisst, ohne Instrumente zu navigieren. GPU-Observability in Kubernetes verbindet drei Schichten: Low-Level-Metriken (DCGM), Kubernetes-Metriken (kube-state-metrics) und geschäftliche Metriken (Kosten je Job, Kosten je Team).
Der vom GPU Operator automatisch ausgerollte DCGM Exporter stellt Prometheus-Metriken auf Port 9400 bereit. Kritisch für die Optimierung sind: DCGM_FI_DEV_GPU_UTIL (Auslastung in %, Ziel 60 bis 80 %), DCGM_FI_DEV_FB_USED und DCGM_FI_DEV_FB_FREE (VRAM, um überdimensionierte GPUs zu erkennen), DCGM_FI_DEV_POWER_USAGE (Leistungsaufnahme, um energetische Ineffizienz zu erkennen) und DCGM_FI_DEV_XID_ERRORS (Hardwarefehler, um Ausfälle vorwegzunehmen).
Die Kubernetes-Metriken (über kube-state-metrics) zeigen, die Zahl der GPU-Pods in Pending (Indikator für Cluster-Sättigung), das Verhältnis angeforderter zu zuteilbaren GPUs je Knoten (Fragmentierung) und die GPU-Pods nach Priorität (Lastverteilung). Die Korrelation von DCGM und Kubernetes legt die Fehlbilder offen: Knoten mit zuteilbaren GPUs über 0, aber 100 % GPU-Auslastung weisen auf Fragmentierung hin (Pods, die 2 GPUs auf einem Knoten mit 4 GPUs anfordern, blockieren die übrigen 2, die für spätere Pods nicht reichen).
FinOps-Metriken machen aus technischen Daten geschäftliche Erkenntnisse. Karpenter stellt karpenter_nodes_total_pod_requests und karpenter_nodes_allocatable bereit, womit sich die reale Bin-Packing-Rate berechnen lässt. In Verbindung mit EC2-Preisdaten ergibt sich daraus die Kostenkennzahl je tatsächlich genutzter GPU-Stunde, nicht bloss je zugeteilter. Kubecost, ein 2024 von AWS übernommenes Open-Source-Werkzeug, aggregiert diese Metriken und erzeugt Berichte: Kosten je Namespace, je Workload, je Team, mit Optimierungsempfehlungen aus den beobachteten Mustern.
Fortgeschrittene Optimierungsstrategien
Intelligentes GPU-Sharing, wann und wie
GPU-Sharing (MIG, Time-Slicing) verbessert die Auslastung, bringt aber Kompromisse. MIG liefert Hardware-Isolation und damit planbare Leistung, ideal für Multi-Tenant-Produktion. Time-Slicing bietet feinere Granularität, aber keine Isolation, was es eher für Dev/Test eignet. Eine hybride Strategie verbindet beide Vorteile: MIG für Produktionsinferenz (strikte SLAs), Time-Slicing für interaktive Notebooks und Experimente, exklusive GPUs für intensives Training.
Die AWS EKS Best Practices 2024 empfehlen für ML-/KI-Lasten, Time-Slicing für sprunghafte Lasten mit Auslastung unter 30 %, MIG für Steady-State-Inferenz mit Isolationsbedarf, exklusive GPUs über Karpenter für verteiltes Training. Die Karpenter-Konfiguration erlaubt karpenter.k8s.aws/instance-gpu-name: "a100", um ein bestimmtes GPU-Modell zu erzwingen und die Platzierung auf ungeeigneten T4 zu vermeiden.
Spot-Instanzen, Trainingskosten um 70 % senken
AWS-Spot-Instanzen bieten bis zu 70 % Rabatt gegenüber On-Demand, im Tausch gegen ein Unterbrechungsrisiko mit zwei Minuten Vorlauf. Karpenter unterstützt Spot nativ über karpenter.sh/capacity-type: spot in den NodePool-Requirements. Karpenter nutzt eine price-capacity-optimized-Strategie: Spot-Pools bevorzugen, die den besten Kompromiss zwischen Preis und Unterbrechungswahrscheinlichkeit bieten.
Zur guten Spot-Praxis für ML zählt laut nOps, Instanzen über mehrere AZ diversifizieren (mehr Spot-Capacity-Pools senken die Wahrscheinlichkeit gleichzeitiger Unterbrechung), SpotToSpotConsolidation nutzen (ein Karpenter-Feature-Gate, das untergenutzte Spot-Instanzen ohne Disruption durch günstigere ersetzt) und für Trainingslasten regelmässig Checkpoints setzen (Zustand alle N Minuten sichern, um nach einer Unterbrechung fortzusetzen). nOps meldet auf gut konfigurierten Karpenter-Clustern eine Spot-Unterbrechungsrate unter 1 %, gegenüber 5 bis 15 % bei statischen ASG.
Für kritische Lasten ohne Unterbrechungstoleranz (Produktionsinferenz, Abschlusstraining von Modellen ab 70B) bleibt ein Spot-/On-Demand-Mix über NodePool-Prioritäten sinnvoll: 80 % Spot-Kapazität für die Ersparnis, 20 % On-Demand für die Verfügbarkeitsgarantie. Karpenter stellt bevorzugt Spot bereit und weicht auf On-Demand aus, wenn Spot nicht verfügbar ist.
Prädiktives Autoscaling: vorwegnehmen statt reagieren
Reaktives Autoscaling (HPA, Karpenter) wartet, bis Metriken Schwellen überschreiten, und erzeugt so 30 bis 90 Sekunden Verzögerung (Metrikerfassung plus Auswertung plus Scaling). Prädiktives Autoscaling nutzt Zeitreihenmodelle (ARIMA, Prophet), um die künftige Last zu prognostizieren und Kapazität 5 bis 10 Minuten im Voraus vorzuwärmen.
Kedify, eine kommerzielle Plattform auf Basis von KEDA, bringt prädiktives Autoscaling, gesteuert über Error Budgets: Prognosen schätzen die Last der nächsten 15 Minuten, das System wärmt gerade so viel Kapazität vor, dass die erwartete Spitze ohne Überschreiten des SLO-Budgets aufgefangen wird, und reaktive Scaler übernehmen, wenn die Prognose danebenliegt. Kedify empfiehlt kurze Prognosehorizonte (10 bis 30 Minuten, darüber hinaus explodiert die Unsicherheit), Quantile statt Mittelwerte (P95-Prognose statt Durchschnitt) und strikte Obergrenzen (maximales Prewarm-Budget, um bei falscher Prognose Verschwendung zu vermeiden).
Prädiktives Autoscaling senkt laut Kedify die P95-Latenz um 15 bis 25 %, verlangt aber Aufwand: genügend historische Daten (mindestens zwei Wochen), regelmässig neu trainierte Modelle (wöchentlich) und enges Monitoring (Prognose gegen Realität, Anpassung bei Drift). Der ROI rechtfertigt sich vor allem bei Anwendungen mit sehr niedriger Latenzanforderung (unter 50 ms P99) oder mit planbaren Spitzen (Batch-Publikationen, ausgeprägter Tagesverkehr).
Die fünf Fehler, welche die GPU-Auslastung deckeln
1. Cluster Autoscaler und Karpenter gleichzeitig betreiben
Symptom: Karpenter installieren, ohne den Cluster Autoscaler abzuschalten, in der Hoffnung, beide ergänzten sich.
Auswirkung: CA und Karpenter beobachten beide die nicht planbaren Pods und versuchen jeweils, Knoten bereitzustellen. Die Folge: Race Conditions mit doppelten Knoten, Thrashing (fortwährendes Hoch- und Runterskalieren durch den Konflikt der beiden Systeme) und vorübergehend doppelte Kosten. Die AWS-Karpenter-Dokumentation ist eindeutig: «We recommend not using Kubernetes Cluster Autoscaler at the same time as Karpenter because both systems scale up nodes in response to unschedulable pods.» Organisationen, die diese Warnung übergehen, berichten von 30 bis 50 % Mehrkosten während der Koexistenz.
Lösung: schrittweise migrieren, die von CA verwalteten Node Pools erfassen, gleichwertige Karpenter-NodePools anlegen, in Staging testen, die Produktion in Wellen umstellen (20 % → 50 % → 100 %) und CA abschalten, sobald der Cluster vollständig auf Karpenter läuft. Während des Übergangs Node Taints nutzen, um CA- und Karpenter-Knoten strikt zu trennen und Überschneidungen zu vermeiden. Das Rollback-Vorgehen im Runbook dokumentieren (CA reaktivieren, falls Karpenter Probleme macht). Typischer Zeitrahmen: 2 bis 4 Wochen für eine vollständige Migration auf einem Cluster mit über 50 Knoten.
2. Disruption Budgets und Karpenter-Konsolidierung ignorieren
Symptom: die Karpenter-Konsolidierung aktivieren (consolidationPolicy, WhenUnderutilized), ohne PodDisruptionBudgets (PDB) für kritische Lasten zu konfigurieren.
Auswirkung: Karpenter konsolidiert aggressiv, Sobald ein Knoten während 30 Minuten unter 50 % Auslastung fällt, werden die Pods verschoben und der Knoten beendet. Ohne PDB kann Karpenter alle Replicas eines Dienstes gleichzeitig verschieben und so Ausfallzeit verursachen. Bei zustandsbehafteten Lasten (Datenbanken, Queues) erzwingt die Konsolidierung einen Neustart von mehreren Minuten, was SLAs verschlechtert. Organisationen berichten von Produktionsvorfällen (P1/P2) durch Karpenter-Konsolidierung bei Diensten ohne PDB in den ersten Wochen nach der Einführung.
Lösung: alle kritischen Deployments und StatefulSets prüfen und passende PDB anlegen, minAvailable, 1 für Dienste mit 2 oder mehr Replicas (mindestens ein Replica läuft immer), maxUnavailable, 1 für Dienste mit mehreren Replicas (begrenzt gleichzeitige Disruption). Bei zustandsbehafteten Lasten die Annotation karpenter.sh/do-not-disrupt: "true" auf den Pods setzen, um die Konsolidierung zu blockieren. Die Konsolidierung in Staging mit synthetischem Verkehr testen, prüfen, dass die PDB Ausfälle wirklich verhindern, und karpenter_disruption_pods_disrupted_total im Abgleich mit Produktionsvorfällen überwachen.
3. Node Pools nicht mit Limits dimensionieren
Symptom: Karpenter-NodePools oder Kueue-ClusterQueues ohne Limits anlegen und auf Cloud-Budgets oder den guten Willen der Teams vertrauen.
Auswirkung: Ein Anwendungsfehler mit einer Endlosschleife von Pods (CrashLoopBackOff, der laufend neue Pods erzeugt) kann Karpenter auslösen, das dann unbegrenzt GPU-Knoten bereitstellt. In zwei Stunden kann ein Cluster von 10 auf 200 H100-Knoten wachsen und die AWS-Rechnung auf 1400 CHF/h steigen (200 × 7 CHF/h). Ohne Limits stoppt nichts die Eskalation, bis die AWS-Billing-Limits erschöpft sind (sofern konfiguriert) oder jemand hektisch eingreift. Reale Vorfälle dokumentieren überraschende Rechnungen von 50 000 bis 100 000 CHF über 48 Stunden.
Lösung: in NodePools grundsätzlich Limits setzen, etwa limits, nvidia.com/gpu, "32" (höchstens 32 GPUs in diesem Pool), dies mit AWS Service Quotas kombinieren (Zahl der GPU-Instanzen je Region begrenzen), CloudWatch-Alarme auf die geschätzten Kosten einrichten (Alarm, wenn die projizierten Monatskosten eine Schwelle überschreiten) und Admission Controller einsetzen (OPA, Kyverno), die prüfen, dass jeder Pod vernünftige Resource Limits angibt. Für Kueue nominalQuota plus borrowingLimit konfigurieren, damit kein Team den ganzen Cluster monopolisiert, auch nicht im Fehlerfall.
4. Die Netzwirkung auf das GPU-Autoscaling unterschätzen
Symptom: Karpenter stellt GPU-Knoten schnell bereit (45 bis 60 s), die Pods bleiben aber weitere 5 bis 10 Minuten in ContainerCreating.
Auswirkung: Der Engpass ist nicht Karpenter, sondern das Laden grosser Docker-Images. ML-/KI-Images (PyTorch, TensorFlow mit CUDA) wiegen 5 bis 15 GB. In einem Standardnetz dauert der Image-Pull je nach Bandbreite und Registry-Cache 3 bis 8 Minuten. Schnelles Autoscaling wird dadurch zur Illusion: Pods stehen erst nach insgesamt 6 bis 11 Minuten bereit (45 s Karpenter plus 5 bis 10 min Image-Pull), gegenüber 3 bis 5 Minuten mit CA. Karpenters Geschwindigkeitsversprechen löst sich nicht ein, und Nutzende sind über die wahrgenommene Verzögerung frustriert.
Lösung: mehrgleisig vorgehen, Images auf eigenen AMIs vorab cachen (ein AMI mit bereits geladenen Images senkt den Cold Start unter eine Minute), optimierte Image-Pull-Policies nutzen (imagePullPolicy, IfNotPresent vermeidet unnötige Repulls), einen internen Registry-Cache (Harbor, Dragonfly) im selben VPC wie der Cluster betreiben und die Images verkleinern (Multi-Stage-Builds, Dev-Abhängigkeiten entfernen). Für kritische Produktion vermeidet ein Warm Pool vorab bereitgestellter GPU-Knoten (Karpenter --reserved-eni oder ein minimaler statischer Node Pool) den Cold Start vollständig.
5. Kostenmonitoring in Echtzeit vernachlässigen
Symptom: Karpenter, Kueue und diverse Optimierungen ausrollen und dann auf die monatliche Cloud-Rechnung warten, um die Ersparnis zu messen.
Auswirkung: Schlecht kalibrierte Optimierungen können unsichtbare Mehrkosten erzeugen, bis zum Billing-Schock am Monatsende. Häufige Beispiele: zu aggressive Karpenter-Konsolidierung erzeugt Thrashing (fortwährendes Hoch- und Runterskalieren) und erhöht die Kosten um 15 bis 25 %, schlecht konfigurierte Kueue-Quoten lassen GPUs stundenlang ungenutzt (zugeteilt, aber nicht verwendet), oder Spot-Instanzen mit häufigen Unterbrechungen (über 10 %) verschwenden Trainingszeit mangels passendem Checkpointing. Ohne Echtzeitsicht lassen sich diese Fehlbilder nicht erkennen und beheben, bevor sie finanziell wirken.
Lösung: eine vollständige FinOps-Kette aufbauen, Kubecost oder Gleichwertiges für Echtzeitkosten je Namespace und Workload, Grafana-Dashboards mit Kennzahlen wie Kosten je genutzter (nicht zugeteilter) GPU-Stunde, Auslastung je Node Pool, Kosten je Team mit 7- und 30-Tage-Trends, dazu Alerts bei Anomalien (Kosten mehr als 20 % über dem Wochenmittel). Wöchentliche Reviews von Engineering und Finance werten die Dashboards aus und passen die Konfiguration an. Typischer ROI des Monitorings: 1 bis 2 Tage Einrichtung plus 2 Stunden Review pro Woche für 10 bis 20 % Ersparnis am GPU-Budget durch die erkannten Optimierungen.
Illustratives Szenario, Optimierung eines ML-Clusters auf AWS EKS
Dieses Szenario ist eine Illustration, kein Hikube-Kunde und kein Hikube-Deployment. Es läuft auf AWS EKS, die Instanzfamilien (p3, g4dn, m5), die Spot-Instanzen und CloudWatch zeigen es, und die genannten Zahlen beschreiben diesen konkreten Fall, kein von Hikube gemessenes oder reproduziertes Ergebnis. Übertragbar ist die Überlegung zu GPU-Fragmentierung, Gang Scheduling, Team-Quoten und Kostentransparenz. Nicht übertragbar sind die AWS-Instanzfamilien und alles, was auf Spot-Instanzen beruht, die Hikube nicht anbietet.
Der Fall in einem Satz: ein Fintech-Start-up mit 40 Data Scientists und ML Engineers betreibt einen EKS-Cluster mit Trainingslasten (Fraud-Detection-Modelle) und Inferenz (Echtzeit-Scoring), bei einem GPU-Budget von 35 000 CHF/Monat, das regelmässig überschritten wurde (Überschreitungen von 45 000 bis 50 000 CHF). Die Ausgangsinfrastruktur nutzte Cluster Autoscaler mit drei festen Node Groups (p3.8xlarge fürs Training, g4dn.xlarge für Inferenz, m5.2xlarge fürs System), ResourceQuotas je Team und einfaches Monitoring über CloudWatch.
Im Audit erkannte Probleme:
- GPU-Fragmentierung, feste Node Groups (4 GPUs je p3.8xlarge-Knoten) mit Jobs, die 2 bis 3 GPUs anforderten, liessen 1 bis 2 GPUs ungenutzt, bei einer Gesamtauslastung von 42 %.
- Trainingsjobs scheiterten in 25 % der Fälle (kein Gang Scheduling, Teil-Pods blockierten GPUs).
- Defensives Overprovisioning, 8 p3.8xlarge-Knoten (32 GPUs) liefen rund um die Uhr, um gelegentliche Spitzen von 2 Stunden pro Tag aufzufangen.
- Keine Sicht auf die Kosten je Team oder Projekt, wodurch Verschwendung nicht erkennbar war.
Umgesetzte Optimierungen (Zeitrahmen, sechs Wochen)
Woche 1-2, Migration von Cluster Autoscaler zu Karpenter
- Karpenter v1.0.2 über Helm installiert.
- NodePools angelegt, gpu-training (p3-, p4d-Instanzen, Spot-Priorität), gpu-inference (g4dn, g5, On-Demand), system (m5).
- CA schrittweise abgeschaltet, 25 % des Verkehrs auf Karpenter (eine Woche Monitoring), dann 100 %.
- Ergebnis, Bereitstellungszeit der GPU-Knoten von 4,5 min auf 55 s (-80 %), besseres Bin-Packing (Karpenter wählt p3.2xlarge für Jobs mit 2 GPUs statt p3.8xlarge).
Woche 3-4, Volcano und Gang Scheduling einführen
- Volcano v1.9 ausgerollt.
- PyTorchJobs auf VolcanoJob mit PodGroups migriert.
- Queues konfiguriert, production (hohe Priorität, Quote 16 GPUs), research (mittlere Priorität, Quote 24 GPUs), dev (niedrige Priorität, Quote 8 GPUs, verdrängbar).
- Ergebnis, Erfolgsquote der Trainingsjobs von 75 % auf 96 %, mittlere Jobdauer -22 % durch den Wegfall von Teilzuteilungen und Retries.
Woche 5, Kubecost und FinOps-Dashboards ausrollen
- Kubecost v2.1 installiert.
- Allocation-Tags je Team und Projekt konfiguriert.
- Grafana-Dashboards erstellt, Echtzeitkosten je Team mit Aufteilung GPU/CPU/Netz, Efficiency Scores (genutzte gegen zugeteilte GPU), automatische Empfehlungen.
- Erkenntnisse, Team A beanspruchte 45 % des Budgets bei 28 % Auslastung (nie geschlossene interaktive Notebooks), während Team B 82 % Effizienz zeigte, aber eine zu knappe Quote hatte.
Woche 6, letzte Optimierungen
- Karpenter-Konsolidierung mit PDB auf den kritischen Diensten aktiviert.
- 80 % der Trainingsjobs auf Spot verlagert (70 % Ersparnis).
- Quoten anhand der gemessenen Effizienz neu verteilt.
Nach drei Monaten gemessene Ergebnisse:
| Kennzahl | Vorher | Nachher | Verbesserung |
|---|---|---|---|
| Mittlere GPU-Auslastung | 42 % | 74 % | +76 % |
| Monatliche GPU-Kosten | 47 000 CHF (mittlere Überschreitung) | 26 500 CHF | -44 % |
| Erfolgsquote der Trainingsjobs | 75 % | 96 % | +28 % |
| Mittlere Bereitstellungszeit | 4,5 min | 55 s | -80 % |
| Kosten je Trainingsjob | 38 CHF | 14 CHF | -63 % |
Projizierte Jahresersparnis: (47 000 - 26 500) × 12 = 246 000 CHF, ein ROI unter drei Monaten auf den Engineering-Aufwand (6 Wochen × 1 FTE Senior DevOps ≈ 25 000 CHF).
Zusammengefasst, drei Kernpunkte
Karpenter macht GPU-Autoscaling deutlich wirksamer
Cluster Autoscaler erzeugt 3 bis 5 Minuten Verzögerung und Fragmentierung durch statische Node Groups. Karpenter v1.0 (stabil seit August 2024) stellt in 45 bis 60 Sekunden dynamisch die optimale Instanz aus über 800 EC2-Typen bereit, senkt die Kosten über automatische Konsolidierung um 20 bis 35 % und unterstützt Spot nativ mit unter 1 % Unterbrechungen, dank Multi-AZ-Diversifizierung und price-capacity-optimized-Ansatz. Das illustrative AWS-EKS-Szenario zeigt in diesem konkreten Fall gemessene Gewinne: Bereitstellungszeit -80 %, GPU-Auslastung +76 %, Monatskosten -44 %. Karpenter verlangt allerdings Sorgfalt: strikte Limits setzen, PDB vor der Konsolidierung konfigurieren und Images vorab cachen, um den Netzengpass zu vermeiden. Eine schrittweise Migration von CA zu Karpenter über 2 bis 4 Wochen senkt das Risiko.
Gang Scheduling über Volcano oder Kueue beseitigt die meisten Fehlschläge im verteilten Training
Der Standard-Scheduler von Kubernetes platziert Pods einzeln, was bei verteilten Lasten Deadlocks erzeugt: Ein PyTorchJob mit 16 Pods kann mit 12 geplanten und 4 wartenden Pods enden und blockiert dabei 12 GPUs ohne Fortschritt. Volcano garantiert Atomarität: alle Pods gemeinsam geplant oder keiner, womit Teilzuteilungen entfallen. Die Benchmarks zeigen eine deutlich höhere Erfolgsquote der Jobs und eine kürzere mittlere Dauer, weil Retries wegfallen. Kueue ergänzt hierarchische Quoten mit Borrowing, sodass Teams ungenutzte Quoten dynamisch teilen und Monopolisierung vermieden wird. Yunikorn wiederum ist eine solide Alternative für hybride K8s-/Hadoop-Umgebungen und wissenschaftliche Lasten.
FinOps in Echtzeit macht aus Optimierung statt einer Einzelaktion eine laufende Praxis
Auf die Monatsrechnung zu warten, um Optimierungen zu beurteilen, führt zu wiederkehrenden Billing-Schocks. Die teuren Fehlbilder, zu aggressive Konsolidierung, schlecht kalibrierte Quoten, schlecht geführtes Spot, bleiben ohne Echtzeit-Monitoring unsichtbar. Kubecost und Grafana zeigen Kosten je Namespace, Team und Workload in Echtzeit, mit Trends und Alerts. Das Szenario zeigte ein Team, das 45 % des Budgets bei nur 28 % Auslastung beanspruchte, was eine Neuverteilung erlaubte. Wöchentliche Reviews von Engineering und Finance finden laufend weitere 10 bis 20 % Ersparnis. Die Investition ins Monitoring amortisiert sich daher rasch.
Bereit für 100 % Schweizer Infrastruktur?
14-Tage-Trial, keine Karte. GPUs inklusive.