- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Cluster Autoscaler: Setup, Tuning und Kostenoptimierung
TL;DR
- Der Cluster Autoscaler ueberwacht Pending Pods und leere Nodes -- er skaliert Nodes hoch wenn Pods nicht schedulbar sind und runter wenn Nodes unterausgelastet sind
- Expander-Strategie waehlen:
least-wastefuer heterogene Workloads,prioritywenn bestimmte Node-Gruppen bevorzugt werden sollen - Scale-Down ist der kritische Teil: zu aggressiv fuehrt zu Flapping, zu konservativ zu Kostenverschwendung
- Spot/Preemptible Instances mit dem Autoscaler kombinieren spart 50-70% -- erfordert aber PodDisruptionBudgets und korrekte Tolerations
- Immer Resource Requests setzen -- ohne sie kann der Autoscaler den Bedarf nicht berechnen
Was der Cluster Autoscaler tut (und was nicht)
Der Cluster Autoscaler ist ein Controller, der als Deployment im Cluster laeuft. Seine Logik ist ueberraschend einfach:
Scale-Up: Alle 10 Sekunden (default) prueft er, ob es Pods im Status Pending gibt, die wegen fehlender Ressourcen nicht gescheduled werden koennen. Wenn ja, simuliert er, welche Node-Gruppe den Pod aufnehmen koennte, und fordert beim Cloud Provider einen neuen Node an.
Scale-Down: Alle 10 Sekunden prueft er, ob es Nodes gibt, deren Auslastung unter einem Schwellwert liegt (default: 50%). Wenn alle Pods auf diesem Node auf andere Nodes umziehen koennten, markiert er den Node zum Entfernen. Nach einer Wartezeit (default: 10 Minuten) wird der Node tatsaechlich entfernt.
Was der Cluster Autoscaler nicht tut:
- Er skaliert keine Pods (dafuer ist der HPA zustaendig)
- Er optimiert keine Pod-Platzierung (das macht der Scheduler)
- Er kuemmert sich nicht um Node-Sicherheit oder Updates
- Er reagiert nicht auf CPU/Memory-Auslastung direkt -- nur auf unschedulbare Pods
Installation auf EKS, AKS und GKE
Jeder Cloud Provider hat seine eigene Integration. Hier die Kurzversion fuer die drei grossen:
AWS EKS
# IAM Policy fuer den Autoscaler (als JSON)
cat > cluster-autoscaler-policy.json << 'POLICY'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeScalingActivities",
"autoscaling:DescribeTags",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"ec2:DescribeLaunchTemplateVersions",
"ec2:DescribeInstanceTypes",
"ec2:DescribeImages",
"ec2:GetInstanceTypesFromInstanceRequirements",
"eks:DescribeNodegroup"
],
"Resource": "*"
}
]
}
POLICY
# Policy erstellen und mit Service Account verknuepfen
aws iam create-policy \
--policy-name ClusterAutoscalerPolicy \
--policy-document file://cluster-autoscaler-policy.json
# Helm Installation
helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm install cluster-autoscaler autoscaler/cluster-autoscaler \
--namespace kube-system \
--set autoDiscovery.clusterName=my-cluster \
--set awsRegion=eu-central-1 \
--set rbac.serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::ACCOUNT_ID:role/ClusterAutoscalerRole
Azure AKS
AKS hat den Cluster Autoscaler nativ integriert. Aktivierung per CLI:
az aks update \
--resource-group my-rg \
--name my-aks-cluster \
--enable-cluster-autoscaler \
--min-count 2 \
--max-count 10
# Fuer eine zusaetzliche Node Pool:
az aks nodepool update \
--resource-group my-rg \
--cluster-name my-aks-cluster \
--name gpupool \
--enable-cluster-autoscaler \
--min-count 0 \
--max-count 4
GKE
Auch GKE hat native Integration:
gcloud container clusters update my-cluster \
--enable-autoscaling \
--min-nodes=2 \
--max-nodes=10 \
--zone=europe-west3-a
Fuer Details zu Managed Kubernetes Services und deren Kostenstruktur, siehe unseren Hosting-Kostenvergleich.
Node-Gruppen-Strategie
Ein einzelner Node Pool ist selten optimal. Unterschiedliche Workloads brauchen unterschiedliche Node-Typen. Eine bewaehlte Aufteilung:
| Node-Gruppe | Instanztyp (AWS) | Einsatzzweck | Min | Max |
|---|---|---|---|---|
| system | m6i.large | CoreDNS, Monitoring, Ingress | 2 | 3 |
| general | m6i.xlarge | Standard-Workloads, APIs | 2 | 15 |
| compute | c6i.2xlarge | CPU-intensive Jobs, Batch | 0 | 8 |
| memory | r6i.xlarge | Caches, Datenbanken, Vector Search | 1 | 6 |
| spot | m6i.xlarge (Spot) | Unkritische Workloads, CI/CD | 0 | 10 |
Entscheidende Regeln:
- System-Nodes immer On-Demand: Cluster-kritische Komponenten duerfen nicht auf Spot Instances laufen
- Min-Count fuer Stateful Workloads: Wenn Qdrant oder Redis auf Memory-Nodes laufen, darf die Gruppe nicht auf 0 skalieren
- Spot-Nodes mit Taints versehen: Nur Workloads mit passender Toleration landen auf Spot-Nodes
# Spot-Node Taint (beim Node Pool Setup)
taints:
- key: "kubernetes.io/spot"
value: "true"
effect: "PreferNoSchedule"
# Pod-Spec fuer Spot-faehige Workloads
tolerations:
- key: "kubernetes.io/spot"
operator: "Equal"
value: "true"
effect: "PreferNoSchedule"
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: "kubernetes.io/spot"
operator: "In"
values: ["true"]
Expander: Welche Node-Gruppe gewaehlt wird
Wenn der Autoscaler skalieren muss und mehrere Node-Gruppen in Frage kommen, entscheidet der Expander. Die wichtigsten:
| Expander | Verhalten | Wann sinnvoll |
|---|---|---|
random | Zufaellige Auswahl | Testing, einfache Setups |
least-waste | Waehlt die Gruppe mit geringstem Ressourcen-Ueberschuss | Heterogene Workloads, Kostenoptimierung |
most-pods | Waehlt die Gruppe die am meisten Pending Pods aufnimmt | Viele kleine Pods |
priority | Waehlt nach definierter Prioritaetsliste | Spot-First-Strategie |
Fuer eine Spot-First-Strategie mit Fallback auf On-Demand:
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-autoscaler-priority-expander
namespace: kube-system
data:
priorities: |-
50:
- .*spot.*
30:
- .*general.*
10:
- .*compute.*
- .*memory.*
Der Autoscaler versucht zuerst Spot-Nodes (Prioritaet 50). Wenn die Node-Gruppe am Limit ist oder keine Spot-Kapazitaet verfuegbar, faellt er auf General (30) zurueck.
Scale-Down Tuning
Scale-Down ist der Teil, der in der Praxis die meisten Probleme macht. Die relevanten Flags:
# Cluster Autoscaler Deployment Args
--scale-down-enabled=true
--scale-down-delay-after-add=10m # Nach Scale-Up: 10min warten vor Scale-Down
--scale-down-delay-after-delete=0s # Nach Node-Delete: sofort wieder pruefen
--scale-down-delay-after-failure=3m # Nach Fehler: 3min warten
--scale-down-unneeded-time=10m # Node muss 10min unterausgelastet sein
--scale-down-utilization-threshold=0.5 # Unter 50% Auslastung = unterausgelastet
--max-graceful-termination-sec=600 # Max 10min fuer Pod-Eviction
--skip-nodes-with-local-storage=true # Nodes mit emptyDir nicht herunterskalieren
--skip-nodes-with-system-pods=true # Nodes mit kube-system Pods schuetzen
Typisches Problem: Der Autoscaler will einen Node entfernen, kann es aber nicht weil:
- Ein Pod ohne Controller (bare Pod) darauf laeuft
- Ein Pod ein PodDisruptionBudget hat, das nicht erfuellt werden kann
- Ein Pod Annotation
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"hat - Der Node Local Storage (emptyDir mit Daten) hat
Debugging:
# Autoscaler Status pruefen
kubectl -n kube-system get configmap cluster-autoscaler-status -o yaml
# Autoscaler Logs anschauen
kubectl -n kube-system logs -l app.kubernetes.io/name=cluster-autoscaler --tail=100
PodDisruptionBudgets: Pflicht bei Autoscaling
Ohne PDBs kann der Autoscaler beim Scale-Down alle Replicas eines Services gleichzeitig evicten. Das fuehrt zu Downtime.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-pdb
spec:
minAvailable: 2 # Oder: maxUnavailable: 1
selector:
matchLabels:
app: api-service
Faustregeln:
- Services mit 3+ Replicas:
maxUnavailable: 1 - Services mit 2 Replicas:
minAvailable: 1 - Stateful Workloads (Datenbanken):
minAvailable: N-1wobei N die Cluster-Groesse ist
Mehr zu Resilience Patterns in unserem Kubernetes Resilienz-Artikel.
Kostenvergleich: Mit und ohne Autoscaler
Realistisches Szenario fuer einen Cluster mit variablem Workload:
| Zeitraum | Ohne Autoscaler (statisch 8 Nodes) | Mit Autoscaler (2-12 Nodes) |
|---|---|---|
| Tagesgeschaeft (8-18 Uhr) | 8 Nodes | 6-8 Nodes |
| Nacht / Wochenende | 8 Nodes | 2-3 Nodes |
| Batch-Jobs (Nacht) | 8 Nodes | 4-6 Nodes (temporaer) |
| Peak (Monatsabschluss) | 8 Nodes, Pods Pending | 10-12 Nodes |
| Monatliche Kosten | ~3.200 EUR | ~1.800 EUR |
| Jaehrliche Kosten | ~38.400 EUR | ~21.600 EUR |
Die Ersparnis von ca. 44% kommt hauptsaechlich aus den Nacht- und Wochenendstunden. Fuer Workloads die 24/7 gleichmaessig laufen ist der Effekt deutlich geringer.
Wenn ihr zusaetzlich Spot Instances fuer unkritische Workloads nutzt, kommen nochmal 30-50% Ersparnis oben drauf. Details zu Autoscaling-Kostenstrategien in unserem Autoscaling-Kostenoptimierungs-Guide.
Monitoring des Autoscalers
Der Cluster Autoscaler exponiert Prometheus-Metriken. Die wichtigsten:
# Anzahl Scale-Up/Down Events
cluster_autoscaler_scaled_up_nodes_total
cluster_autoscaler_scaled_down_nodes_total
# Aktuelle Cluster-Groesse
cluster_autoscaler_nodes_count
# Unschedulable Pods (sollte moeglichst 0 sein)
cluster_autoscaler_unschedulable_pods_count
# Fehlgeschlagene Scale-Ups
cluster_autoscaler_failed_scale_ups_total
# Dauer bis Node ready
cluster_autoscaler_node_ready_duration_seconds
Ein Alert bei cluster_autoscaler_unschedulable_pods_count > 0 fuer mehr als 5 Minuten ist ein guter Einstieg. Das bedeutet, der Autoscaler kann nicht skalieren (Limit erreicht oder Cloud-Provider-Problem).
Fuer den gesamten Monitoring-Stack siehe unseren Kubernetes Monitoring Leitfaden.
Haeufige Fehler
Keine Resource Requests gesetzt: Der Autoscaler berechnet den Bedarf anhand von Requests, nicht anhand der tatsaechlichen Nutzung. Pods ohne Requests werden als "verbraucht 0 Ressourcen" betrachtet -- der Autoscaler skaliert nie hoch.
Max-Nodes zu niedrig: Wenn das Limit erreicht ist, bleiben Pods im Pending-Status. Setzt das Limit grosszuegig und kontrolliert Kosten ueber Budget-Alerts statt ueber harte Node-Limits.
Scale-Down blockiert durch DaemonSets: DaemonSet-Pods laufen auf jedem Node. Sie verhindern nicht das Scale-Down, aber manche Custom-DaemonSets haben safe-to-evict: false gesetzt. Das blockiert den Autoscaler.
Kein Over-Provisioning fuer schnelle Scale-Ups: Einen neuen Node zu provisionieren dauert 2-5 Minuten. Wenn eure Workloads sofortige Skalierung brauchen, hilft ein Pause-Pod (ein niedriger-Prioritaets-Pod der nur Platz reserviert und bei Bedarf verdraengt wird):
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: overprovisioning
value: -1
globalDefault: false
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: overprovisioning
spec:
replicas: 2
selector:
matchLabels:
app: overprovisioning
template:
metadata:
labels:
app: overprovisioning
spec:
priorityClassName: overprovisioning
containers:
- name: pause
image: registry.k8s.io/pause:3.9
resources:
requests:
cpu: "2"
memory: "4Gi"
Diese Pause-Pods reservieren Ressourcen. Wenn ein echter Workload-Pod kommt, verdraengt der Scheduler den Pause-Pod (weil er niedrigere Prioritaet hat). Der Pause-Pod wird Pending, und der Autoscaler provisioniert einen neuen Node. Der Effekt: Euer Workload-Pod startet sofort statt nach 3 Minuten.
Zusammenfassung
Der Cluster Autoscaler ist eines der wirkungsvollsten Tools fuer Kostenoptimierung auf Kubernetes. Die Grundinstallation ist einfach -- die Kunst liegt im Tuning: Node-Gruppen richtig schneiden, Expander passend waehlen, Scale-Down-Verhalten abstimmen und PDBs nicht vergessen.
Startet mit konservativen Einstellungen und beobachtet 2-3 Wochen. Die Autoscaler-Logs und Prometheus-Metriken zeigen euch schnell, wo nachgestellt werden muss.
Bei Fragen zur optimalen Konfiguration fuer euren spezifischen Workload, stehen wir gerne fuer ein Beratungsgespraech zur Verfuegung.
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
Cluster Autoscaler: Kubernetes-Nodes optimal skalieren
Cluster Autoscaler optimieren mit Expander-Strategien, Scale-Down-Tuning und Priority-Konfiguration für kosteneffiziente Node-Skalierung.
Capacity Planning: Kubernetes-Autoscaling richtig nutzen
HPA, VPA, Cluster Autoscaler und KEDA kombinieren für Capacity Planning in Kubernetes. Mit Praxisbeispielen und Entscheidungshilfe.
Kubernetes Cloud-Kosten senken: FinOps und Right-Sizing
Kubernetes Cloud-Kosten um 45% senken: Right-Sizing, Spot Instances, Autoscaling und FinOps-Prozesse mit Kubecost für nachhaltige Einsparungen.
Cluster Autoscaler einrichten: Nodes automatisch skalieren
Kubernetes Cluster Autoscaler installieren und konfigurieren für automatische Node-Skalierung mit Helm, Karpenter-Vergleich und Spot-Instance-Strategien.
Kubernetes E-Commerce: Black Friday Autoscaling richtig
Kubernetes für Black Friday konfigurieren: HPA mit Custom Metrics, Scheduled Scaling vor Peak-Events und Kostenoptimierung in der Nebensaison.