Cloud Intelligence™
Das GKE-Feature, das die meisten Cluster noch nicht nutzen: Custom ComputeClasses
Diese Seite ist auch in English, Español, Français, Italiano, 日本語 und Português verfügbar.
About Chimbu Chinnadurai
Senior Cloud Architect II
I've probably debugged a Kubernetes issue in more time zones than I care to count. Based in London, I help engineering teams across EMEA get their clusters to behave — and actually understand why they misbehaved in the first place.
I write, speak, and guest on podcasts about all things cloud-native. Away from the terminal: I enjoy cooking almost as much as simplifying overly complex systems.
My personal pageIch sehe bei fast jedem GKE-Cluster-Review dasselbe Muster: eine lange Liste statischer Node-Pools, jeder an einen einzelnen Maschinentyp gebunden. Ein n2-standard-8-Pool für allgemeine Workloads, ein n2-highmem-16-Pool für die speicherhungrigen Services, ein Spot-Pool, den jemand letztes Jahr während einer Kostensenkungsinitiative angelegt hat, und vielleicht noch ein GPU-Pool. Workloads werden über nodeSelector, Taints, Tolerations und über Jahre gewachsene Node-Affinity-Regeln auf die Nodes verteilt.
Das funktioniert, bis sich etwas ändert – und meistens ist es eines von drei Dingen.
Zonale Stockouts: In einer Zone wird Ihre gewählte Maschinenserie knapp. Der Cluster Autoscaler kann nur die konkreten Pools skalieren, die Sie ihm gegeben haben – Pods bleiben in
Pendinghängen, während benachbarte Maschinenfamilien in derselben Zone ungenutzt bereitstehen.Spot-Preemption-Fallen: Massive Spot-Preemptions verdrängen Workloads auf On-Demand-Fallback-Pools. Sobald die Kapazität zurückkehrt, migriert nichts die Workloads aktiv zurück – die geplanten Einsparungen tauchen auf der Rechnung nie auf.
Generationswechsel: Der Umstieg von N2 auf N4 oder C4 wird zum wochenlangen operativen Kraftakt: neue Pools provisionieren, Helm-Values in Dutzenden Repositories aktualisieren, alte Nodes drainen und hoffen, dass kein Manifest alte Labels hartkodiert hat.
GKE hat auf alle drei Probleme schon länger eine Antwort: Custom ComputeClasses. Die Kunden, mit denen ich spreche, haben entweder noch nie davon gehört oder gehen davon aus, dass es sie nur in Autopilot gibt. Das stimmt nicht. Custom ComputeClasses stehen ab GKE 1.30.3-gke.1451000 sowohl im Autopilot- als auch im Standard-Modus zur Verfügung und sind in allen geeigneten Clustern standardmäßig aktiviert.
Was ist eine Custom ComputeClass?
Eine ComputeClass ist eine Kubernetes Custom Resource (computeclasses.cloud.google.com), die festlegt, welche Node-Profile Workloads bevorzugen – nach Priorität geordnet. Wie Googles Dokumentation erklärt, erhält GKE damit ein Profil von Node-Attributen, das bei Autoscaling-Ereignissen zum Einsatz kommt.
Klassische Node-Pools: Sie deklarieren zuerst die Infrastruktur und steuern die Workloads dann darauf.
ComputeClasses: Sie deklarieren, was Sie erreichen wollen ("Versuche zuerst N4 Spot; falls nicht verfügbar, C4 Spot; andernfalls Fallback auf N4 On-Demand"), und der Autoscaler stellt automatisch die richtigen Nodes bereit.
Das hält die Verantwortlichkeiten sauber getrennt: Plattform-Teams definieren Hardware-Profile, und Anwendungsentwickler wählen ein Profil einfach per Name aus.
Was sich damit in der Praxis löst
- Stockouts werden zu automatischen Fallbacks: Scheitert eine Regel mit hoher Priorität an Quota oder zonaler Verfügbarkeit, versucht GKE sofort die nächste Regel in der Liste.
- Fallback-Kapazität bleibt nicht dauerhaft bestehen: Mit aktivierter aktiver Migration verschiebt GKE Workloads zurück auf höher priorisierte Nodes, sobald die bevorzugte Kapazität zurückkehrt – und holt die Kosteneinsparungen automatisch wieder rein.
- Upgrades bleiben Sache der Plattform: Workloads von N2 auf N4 umzuziehen oder C4 zu testen heißt: ein einziges ComputeClass-Manifest aktualisieren. Die Anwendungsteams fassen ihre Selektoren nie an.
Ein paar kleinere Dinge helfen ebenfalls. Sie können zentral festlegen, welche Compute-Engine-Reservierungen zuerst verbraucht werden, pro Klasse steuern, wie aggressiv unterausgelastete Nodes konsolidiert werden, und eine Default-Klasse für einen Namespace oder den ganzen Cluster setzen, damit Teams sinnvolle Hardware bekommen, ohne einen Selektor schreiben zu müssen.
Die wichtigsten Konfigurations-Stellschrauben
Unter spec.priorities definiert jede Regel ein primäres Hardware-Ziel: machineFamily (z. B. n4), machineType (z. B. n4-standard-32), gpu oder tpu. In Standard-Clustern kann eine Regel über nodepools auf bestehende Node-Pools zeigen. Regeln akzeptieren Flags für spot, minCores, minMemoryGb, Boot-Disk-Einstellungen, lokale SSDs, sekundäre Boot-Disks, Reservierungen und Zonen.
whenUnsatisfiable: Steuert das Verhalten, wenn alle Prioritätsstufen scheitern.ScaleUpAnywayerstellt einen Node mit der Cluster-Standardkonfiguration, währendDoNotScaleUpPods im StatusPendingbelässt, bis ein passender Node erstellt werden kann.DoNotScaleUpist seit GKE 1.33 der Default (davor war esScaleUpAnyway) – setzen Sie den Wert also explizit, um Überraschungen zu vermeiden, wenn Cluster auf unterschiedlichen Versionen dieselben Manifeste teilen.autoscalingPolicy: Konfiguriert die Scale-Down-Sensitivität überconsolidationDelayMinutes, einen CPU- und Speicher-consolidationThresholdsowie einen separatengpuConsolidationThreshold.activeMigration: Die aktive Migration hat zwei Schalter.optimizeRulePriority: trueverschiebt Pods aktiv zurück auf höher priorisierte Nodes, sobald Kapazität frei wird.ensureAllDaemonSetPodsRunning: trueersetzt Nodes, die zu klein sind, um alle erforderlichen DaemonSet-Pods auszuführen, durch größere.
nodePoolAutoCreation.enabled: true: Erlaubt GKE, Node-Pools zu erstellen und zu löschen, um Ihre Prioritäten zu erfüllen. Ab GKE1.33.3-gke.1136000braucht es dafür kein Cluster-weites Node Auto-Provisioning mehr.
Ihre bestehenden Pools funktionieren weiterhin. Fügen Sie einem manuell erstellten Pool das Label cloud.google.com/compute-class und einen passenden NoSchedule-Taint hinzu, und er wird Teil der Klasse – so können Sie Klassen schrittweise einführen.
Sie können eine ComputeClass außerdem standardmäßig auf einen Namespace anwenden, indem Sie ihn labeln, oder auf den ganzen Cluster, indem Sie eine Klasse namens default deployen und das Feature auf dem Cluster aktivieren. GKE liefert zudem integrierte ComputeClasses mit, darunter autopilot, mit der Standard-Cluster ausgewählte Pods auf der container-optimierten Autopilot-Compute-Plattform ausführen können.
Zwei Patterns für den Einstieg
Pattern 1: Statische Spot-Pools durch eine resiliente Fallback-Kette ersetzen
Hier eine Allzweck-ComputeClass, die N4 Spot priorisiert, auf C4 Spot zurückfällt und N4 On-Demand als Sicherheitsventil nutzt. Sie konsolidiert unterausgelastete Nodes nach 5 Minuten und migriert Pods in der Kette wieder nach oben, sobald sich die Spot-Kapazität erholt:
apiVersion: cloud.google.com/v1kind: ComputeClassmetadata: name: general-cost-optimizedspec: nodePoolAutoCreation: enabled: true priorities: - machineFamily: n4 spot: true minCores: 4 - machineFamily: c4 spot: true minCores: 4 - machineFamily: n4 spot: false activeMigration: optimizeRulePriority: true autoscalingPolicy: consolidationDelayMinutes: 5 consolidationThreshold: 70 whenUnsatisfiable: DoNotScaleUpMit optimizeRulePriority: true verschiebt GKE die Pods zurück auf die bevorzugte Spot-Regel, sobald wieder Kapazität verfügbar ist, und entfernt anschließend den Fallback-Node.
Workloads nutzen diese Klasse über einen einzigen Node-Selektor:
apiVersion: apps/v1kind: Deploymentmetadata: name: checkout-apispec: replicas: 3 selector: matchLabels: app: checkout-api template: metadata: labels: app: checkout-api spec: nodeSelector: cloud.google.com/compute-class: general-cost-optimized containers: - name: api image: registry.k8s.io/pause resources: requests: cpu: "1" memory: "2Gi"Es gibt keinen cloud.google.com/gke-spot-Selektor, keine Tolerations und keine Maschinenfamilien-Affinity – und das ist Absicht. GKE lehnt Pods ab, die eine ComputeClass selektieren und zusätzlich System-Labels selektieren, für die es ein passendes ComputeClass-Feld gibt, etwa cloud.google.com/gke-spot, cloud.google.com/machine-family oder node.kubernetes.io/instance-type. Diese Entscheidungen gehören in die Klasse. Wenn Sie bestehende Workloads migrieren, durchsuchen Sie zuerst Ihre Manifeste und Helm-Charts nach diesen Labels.
Pattern 2: Klassen über bestehende Custom-Pools legen
Wenn Sie Standard-Cluster mit spezialisierten, vorgewärmten oder reservierungsgestützten Pools betreiben, müssen Sie diese nicht löschen. Konfigurieren Sie die Klasse so, dass sie zuerst bestehende Pools nutzt und neue nur dann erstellt, wenn diese nicht weiter skalieren können:
apiVersion: cloud.google.com/v1kind: ComputeClassmetadata: name: hybrid-fallback-classspec: nodePoolAutoCreation: enabled: true priorities: - nodepools: [core-workload-pool] - machineFamily: n4 - machineFamily: c4Versehen Sie Ihren bestehenden Pool mit Label und Taint, damit die Klasse ihn erkennt:
gcloud container node-pools update core-workload-pool \ --cluster=example-cluster \ --node-labels="cloud.google.com/compute-class=hybrid-fallback-class"
gcloud container node-pools update core-workload-pool \ --cluster=example-cluster \ --node-taints="cloud.google.com/compute-class=hybrid-fallback-class:NoSchedule"Beachten Sie: --node-labels und --node-taints ersetzen sämtliche Labels und Taints des Pools – nehmen Sie also alle vorhandenen mit in die Befehle auf.
Der Best-Practices-Leitfaden empfiehlt dieselbe Reihenfolge: Manuell erstellte Pools erhalten die höchste Priorität, automatisch erstellte Pools dienen als Fallback.
Cloud bill shouldn't be a mystery
One platform for AI and Cloud optimization.
Nennenswerte Neuerungen
Das Feature hat sich über die letzten GKE-Minor-Versionen schnell weiterentwickelt. Diese Änderungen sollte jeder kennen, der sich ComputeClasses vor einem Jahr angesehen und wieder beiseitegelegt hat.
Gewichtete Prioritäts-Scores (ab 1.35.2-gke.1842000)
Statt sich nur auf die Listenreihenfolge zu verlassen, können Regeln einen expliziten priorityScore von 1 bis 1000 definieren. Dabei gilt: alles oder nichts – entweder hat jede Regel in der Klasse einen Score oder keine. Bis zu drei Regeln können sich einen Score teilen; GKE wertet gleichauf liegende Regeln gemeinsam aus und lässt den Cluster Autoscaler zwischen ihnen wählen.
apiVersion: cloud.google.com/v1kind: ComputeClassmetadata: name: priority-rule-score-classspec: nodePoolAutoCreation: enabled: true priorities: - machineFamily: e2 spot: true priorityScore: 30 - machineFamily: n2 spot: true priorityScore: 20 - machineFamily: t2d spot: true priorityScore: 20 - machineFamily: n1 spot: true priorityScore: 10 whenUnsatisfiable: ScaleUpAnywayHier gelten N2- und T2D-Spot als gleichwertige zweite Wahl. Gruppierte Regeln können die Autoscaling-Latenz erhöhen – bei breiten machineFamily-Regeln stärker als bei engen machineType-Regeln, weil GKE mehr Simulationen durchrechnen muss.
Automatische Storage-Auswahl (ab 1.35.3-gke.1290000)
Das Mischen von Maschinengenerationen barg bisher ein Storage-Risiko, weil jede Serie bestimmte Disk-Typen unterstützt (N4 unterstützt z. B. Hyperdisk, während N2 auf Standard-PDs setzt). Jetzt können Sie eine StorageClass mit automatischer Disk-Typ-Auswahl verwenden: GKE erstellt dann einen Disk-Typ, der zu dem Maschinentyp passt, auf dem der Pod landet. Das macht generationsübergreifende Fallback-Ketten für Workloads mit dynamischem Provisioning deutlich sicherer. Bereits vorhandene Disks brauchen weiterhin einen Disk-Typ, den jede Maschinenserie in der Klasse unterstützt.
Custom Machine Shapes (ab 1.33.2-gke.1111000)
Sie können benutzerdefinierte Shapes wie n4-custom-8-20480 direkt in machineType definieren – für Workloads, deren CPU-zu-Speicher-Verhältnis nicht in die vordefinierten Shapes passt.
Boot-Disk-Einstellungen auf machineFamily-Regeln (ab 1.34.1-gke.1431000)
Definieren Sie storage.bootDiskType und storage.bootDiskSize auf flexiblen machineFamily-Regeln statt nur auf spezifischen machineType-Regeln:
priorities:- machineFamily: n4 spot: true minCores: 16 minMemoryGb: 64 storage: bootDiskType: hyperdisk-balanced bootDiskSize: 100Labels und Taints in der Klasse (1.33.2 bis 1.34.1)
Deklarieren Sie nodeLabels und taints pro Prioritätsregel (Labels ab 1.33.2-gke.1111000, Taints ab 1.33.4-gke.1350000) oder global unter nodePoolConfig (ab 1.34.1-gke.3084002). Werte auf Regelebene und globale Werte dürfen sich nicht überschneiden. So bleiben Labelling und Isolation im selben Objekt wie die Hardware-Entscheidung.
Default-Klassen für System-Workloads (ab 1.33.1-gke.1788000)
Namespaces können über das Label cloud.google.com/default-compute-class-non-daemonset eine Default-Klasse erhalten, die nur für Nicht-DaemonSet-Pods gilt. GKE nutzt das, um System-Pods in Namespaces wie kube-system und gmp-system getrennt von Ihren Workloads auszuführen, während DaemonSet-Pods den Klassen-Selektor nicht erhalten.
Autopilot-Compute neben einem eigenen Default (ab 1.34.1-gke.1829001)
Wenn Sie in einem Autopilot-Cluster eine Custom-Klasse als Cluster-Default setzen, laufen Pods nicht mehr standardmäßig auf der container-optimierten Autopilot-Plattform. Sie können die Autopilot-Compute-Plattform jetzt gezielt für einzelne Pods aktivieren, indem Sie diesen Pods den Node-Selektor cloud.google.com/compute-class: autopilot hinzufügen.
Ein paar kleinere Neuerungen
priorityDefaults (1.32.1-gke.1729000) erlaubt es, gemeinsame Werte einmal zu setzen, statt sie in jeder Regel zu wiederholen. nodeSystemConfig bringt kubelet- und sysctl-Tuning in die Klasse. Compact Placement und Workload Policies stehen für Autopilot ab 1.33.2-gke.1335000 zur Verfügung.
Fallstricke und Grenzfälle in der Produktion
ComputeClasses haben Grenzen – und die sollten Sie im Design-Review entdecken, nicht in der Produktion.
kube-scheduler kennt die Prioritätsregeln nicht: ComputeClasses beeinflussen das Autoscaling, aber der kube-scheduler berücksichtigt sie nicht. Haben Fallback-Nodes bereits freie Kapazität, können neue Pods dort landen statt auf den bevorzugten Nodes. Mit aktiviertem
activeMigration.optimizeRulePrioritywerden diese Fallback-Nodes mit der Zeit ersetzt, und ein strengererconsolidationThresholdsorgt dafür, dass unterausgelastete Fallback-Nodes früher gedraint werden.Änderungen wirken nur nach vorn: Das Bearbeiten einer ComputeClass ändert laufende Nodes nicht. Cordonen und drainen Sie bestehende Nodes in einem Wartungsfenster, damit sie nach den neuen Regeln ersetzt werden.
Stateful Workloads von der aktiven Migration fernhalten: Die aktive Migration verdrängt Pods per Eviction und verschiebt keine Daten. Der Best-Practices-Leitfaden empfiehlt, sie für Klassen zu deaktivieren, die von Stateful Workloads genutzt werden. Packen Sie diese Workloads in eine eigene Klasse und nutzen Sie entweder die automatische Disk-Typ-Auswahl oder beschränken Sie die Klasse auf Maschinenserien, die Ihren Disk-Typ allesamt unterstützen.
Namespace-Defaults migrieren bestehende Pods nicht: GKE injiziert den Klassen-Selektor nur in Pods, die nach dem Labeln des Namespace erstellt werden – bereits laufende Pods bleiben unangetastet. Starten Sie die Workloads im Namespace nach dem Setzen eines Defaults neu, damit neu erstellte Pods den Selektor und die aktive Migration übernehmen. Ein Cluster-weiter Default kann bestehende Pods direkt migrieren.
Vorsicht bei hoher Pod-Fluktuation: In Clustern mit sehr hohen Pod-Erstellungs- und -Löschraten schafft es der Cluster Autoscaler unter Umständen nicht, niedrigere Regeln auszuwerten, bevor der Backoff der höheren Regeln abläuft – Pods bleiben in
Pending. Wenn Sie auf diesen Grenzfall stoßen, reduzieren Sie die Konsolidierungsfrequenz oder deaktivieren Sie die aktive Migration.Fallback-Verhalten bei Reservierungen: Mit
AnyBestEffortversucht GKE, wenn keine passende Reservierung Kapazität hat, zunächst einen On-Demand-Node für dieselbe Regel, bevor es zur nächsten Regel weitergeht. Soll bei voller reservierter Kapazität direkt die nächste Regel greifen, nutzen Sieaffinity: Specific(für benannte Reservierungen) oderaffinity: AnyThenFail.
Kleinere Einschränkungen
Ein Workload kann nur eine ComputeClass selektieren, und jeder manuell erstellte Node-Pool kann nur zu einer gehören. In Autopilot unterstützt bootDiskType nur pd-balanced. Klassennamen dürfen nicht mit gke oder autopilot beginnen. Viele der genannten Features setzen aktuelle Patch-Versionen voraus – prüfen Sie also Ihren Release-Channel, bevor Sie Ihr Design darauf aufbauen.
Fazit
Wenn Ihre Cluster noch auf festen, an Maschinentypen gebundenen Node-Pools laufen, starten Sie mit einem zustandslosen Namespace. Geben Sie ihm eine Spot-first-Fallback-Kette und beobachten Sie, wie oft Pods auf den Fallback-Regeln landen und ob die aktive Migration sie zurückholt.
Behalten Sie dabei im Kopf: Eine ComputeClass entscheidet, welche Art von Node erstellt wird – die Node-Größe hängt jedoch von den Resource-Requests Ihrer Pods ab. Bei machineFamily-Regeln wählt der Cluster Autoscaler die Maschinengröße anhand der aggregierten Requests der pending Pods. Überdimensionierte Requests bedeuten größere Maschinen, schlechteres Bin Packing und mehr Kapazität auf Fallback-Nodes.
Genau hier zahlt sich Right-Sizing aus. PerfectScale dimensioniert Workload-Requests kontinuierlich richtig, sodass die Nodes, die Ihre ComputeClasses erstellen, dem tatsächlichen Bedarf Ihrer Pods entsprechen. Das Feature Node Recommendations hilft Ihnen, die kosteneffizientesten Maschinenfamilien für Ihre Prioritätsregeln auszuwählen. Wenn Sie Ihre Cluster-Ausgaben prüfen und sehen möchten, wie sich solche Fallback-Setups in der Praxis schlagen, buchen Sie eine Demo mit dem Team.