How to: Kubernetes Cluster Autoscaler installieren, verwenden und debuggen
Erfahren Sie in dieser Dokumentation, wie Sie den Xelon Kubernetes Autoscaler installieren, verwenden und debuggen können.
Was ist der Kubernetes Cluster Autoscaler?
Der Kubernetes Cluster Autoscaler erweitert die üblichen Möglichkeiten des Autoscalings. Standardmässig unterstützt Kubernetes nur die Skalierung von Workloads, was dem Hinzufügen oder Entfernen von Pods entspricht. Damit lassen sich die vorhandenen Cluster-Ressourcen zwar neu verteilen, die Menge der Ressourcen in einem Cluster lässt sich so aber nicht verändern. Möchten Sie die Ressourcen anhand der aktuellen Auslastung erhöhen oder verringern, müssten Sie dies manuell durch das Hinzufügen oder Entfernen von Nodes tun.
Genau hier kommt der Cluster Autoscaler ins Spiel: Gibt es aufgrund von Ressourcenengpässen nicht planbare (unschedulable) Pods, kann er einen weiteren Node hinzufügen. Ist die durchschnittliche Node-Auslastung zu niedrig und lässt es Ihr Workload zu, kann man Nodes auch wieder entfernen. Das verbessert Ihre Kosteneffizienz, weil Compute-Leistung nur während der Spitzenzeiten hinzugefügt wird.
Quell-Repository: https://github.com/Xelon-AG/autoscaler
Wie wird der Xelon Kubernetes Cluster Autoscaler installiert und konfiguriert?
Bevor Sie den Xelon Kubernetes Cluster Autoscaler installieren können, müssen Sie Ihren Cluster auf die Kubernetes-Version 1.35 oder höher aktualisieren.
Wie erhalte ich die Pool-IDs?
Sie benötigen die ID des Node Pools, den Sie skalieren möchten. Um sie zu ermitteln, können Sie wie folgt einen temporären Debug-Pod erstellen:
kubectl -n kube-system run xelon-probe --rm -it --restart=Never \
--image=alpine:latest \
--overrides='{
"spec": {
"containers": [{
"name": "xelon-probe",
"image": "alpine:latest",
"stdin": true, "tty": true,
"env": [
{"name": "XELON_API_URL", "value": "https://hq.xelon.ch/api/v2"},
{"name": "XELON_CLIENT_ID", "valueFrom": {"secretKeyRef": {"name": "xelon-api-credentials", "key": "clientId"}}},
{"name": "XELON_CLUSTER_ID","valueFrom": {"secretKeyRef": {"name": "xelon-api-credentials", "key": "kubernetesClusterId"}}},
{"name": "XELON_TOKEN", "valueFrom": {"secretKeyRef": {"name": "xelon-api-credentials", "key": "token"}}}
]
}]
}
}' -- ash
Und anschliessend können Sie so die Liste der Worker Pools in Ihrem Cluster abrufen:
apk add curl jq
curl -fsS "${XELON_API_URL}/kubernetes/${XELON_CLUSTER_ID}/pools" \
-H "Authorization: Bearer ${XELON_TOKEN}" \
-H "X-User-Id: ${XELON_CLIENT_ID}" |
jq -r '.[] | [.identifier, .name, (.nodes | length)] | @tsv'
Wie erfolgt die Installation mit Kustomize?
Wir empfehlen die Installation mit Kustomize, damit Sie künftig durch einfaches Wechseln des Tags unkompliziert aktualisieren können. Verwenden Sie unbedingt das Autoscaler-Release, das Ihrer Kubernetes-Version am nächsten kommt.
kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://raw.githubusercontent.com/Xelon-AG/autoscaler/v1.35.2-xelon.2/cluster-autoscaler/cloudprovider/xelon/examples/cluster-autoscaler.yaml
patches:
- target:
group: apps
version: v1
kind: Deployment
name: xelon-cluster-autoscaler
namespace: kube-system
patch: |-
- op: replace
path: /spec/template/spec/containers/0/args/1
value: --nodes=3:5:pt3s8gen7g
- op: replace
path: /spec/template/spec/containers/0/env/0
value:
name: XELON_BASE_URL
value: https://hq.xelon.ch/api/v2/
Passen Sie unbedingt den ersten Patch an Ihre Bedürfnisse an: --nodes=<min nodes>:<max nodes>:<pool ID> Das Beispiel skaliert den Node Pool "pt3s8gen7g" zwischen 3 und 5 Nodes.
Was sind Skalierungsbedingungen?
Die Skalierungsbedingungen können an Ihre Bedürfnisse angepasst werden. Die folgenden beiden Abschnitte erläutern die aktuellen Standardwerte und das Verhalten.
Hochskalieren (Scale up)
Ein neuer Node wird hinzugefügt, wenn ein Pod nicht planbar ist – weil der kube-scheduler PodScheduled=False mit Reason=Unschedulable gesetzt hat – und der Pod unter keinen der unten aufgeführten Filter fällt:
| Filter | Verwirft |
|---|---|
| Expendable | Priorität unterhalb von --expendable-pods-priority-cutoff (Standard -10) |
| Bereits planbar | Pods, die per Bin-Packing auf bestehende oder in Kürze verfügbare Kapazität passen |
| DaemonSet | DS-Pods, ein neuer Node hilft ihnen nicht |
Der Filter "bereits planbar" ist der Grund, weshalb ein wartender Pod manchmal kein Hochskalieren auslöst: Der CA hat Kapazität auf einem Node mitgezählt, der noch bereitgestellt wird.
Herunterskalieren (Scale down)
Ein Node wird erst entfernt, nachdem er sechs aufeinanderfolgende Prüfungen (Gates) bestanden hat. Fällt er bei einer davon durch, wird die Uhr in Gate 5 zurückgesetzt.
Gate 1: Loop aktiviert und nicht in der Cooldown-Phase
| Bedingung | Flag | Standard |
|---|---|---|
| Scale-down aktiviert | --scale-down-enabled |
true |
| Kein kürzliches Scale-up | --scale-down-delay-after-add |
10m |
| Kein kürzlich fehlgeschlagenes Scale-down | --scale-down-delay-after-failure |
3m |
| Kein kürzliches Löschen | --scale-down-delay-after-delete |
0s |
Gate 2: Vorfilterung der Kandidaten
- Der Node gehört zu einer autoskalierten Node Group.
- Die Group liegt über ihrer
MinSize(). Mit--nodes=1:4ist der letzte Node nie ein Kandidat.
Gate 3: Eignung
- Wird nicht bereits gelöscht (kein
ToBeDeletedByClusterAutoscaler-Taint). - Keine Annotation
cluster-autoscaler.kubernetes.io/scale-down-disabled: "true". - Falls nicht bereit (unready):
--scale-down-unready-enabled(Standardtrue) muss aktiviert sein. - Auslastung auf oder unterhalb von
--scale-down-utilization-threshold(Standard0.5).
Auslastung bedeutet hier Ressourcen-Requests geteilt durch Allocatable – nicht die tatsächliche CPU-/Speichernutzung. Ein Node mit 5 % realer Speichernutzung, dessen Pods aber 90 % des Allocatable anfordern, wird nie heruntergesteuert. Das ist mit Abstand die häufigste Überraschung. Die entsprechende Logzeile bei -v=4 lautet:
Node prod-w-1-1 unremovable: memory requested (93.2809% of allocatable) is above the scale-down utilization threshold
DaemonSet- und Mirror-Pods können über --ignore-daemonsets-utilization und --ignore-mirror-pods-utilization von der Berechnung ausgeschlossen werden.
Gate 4: Simulation
Jeder Pod auf dem Node muss:
- Drainbar sein (kein blockierendes PodDisruptionBudget, kein kube-system-Pod ohne PDB, kein Pod ohne Controller, kein lokaler Speicher, ausser er ist mit
safe-to-evictannotiert) – andernfallsNode X cannot be removed: … - Anderswo Platz finden – andernfalls
Node X is not suitable for removal(GrundNoPlaceToMovePods)
Die Simulation ist durch --scale-down-simulation-timeout (30s) begrenzt.
Gate 5: Lange genug nicht benötigt
| Node-Status | Flag | Standard |
|---|---|---|
| Ready | --scale-down-unneeded-time |
10m |
| Unready | --scale-down-unready-time |
20m |
Die Uhr wird jedes Mal zurückgesetzt, wenn ein Node in einem Durchlauf bei einem Gate durchfällt. Ein Node, dessen Auslastung alle paar Minuten über den Schwellenwert springt, erreicht nie zehn zusammenhängende Minuten. Nachverfolgen können Sie das mit:
kubectl logs -n kube-system deploy/xelon-cluster-autoscaler | grep "was unneeded for"
Gate 6: Mindestgrösse und Ressourcenuntergrenze
- Die Grösse der Group abzüglich der bereits laufenden Löschvorgänge muss über
MinSize()bleiben. - Das Entfernen des Nodes darf den Cluster nicht unter die Mindestwerte von
--cores-total/--memory-totalfallen lassen.
Wie wird der Autoscaler debuggt?
Das Debugging des Autoscalers ist einfach: Verfolgen Sie einfach die Logs und prüfen Sie, was zwischen den "Starting main loop"-Meldungen passiert.
kubectl logs -f -n kube-system deploy/xelon-cluster-autoscaler
Tipp: Wenn Sie einen Pod haben, der gefahrlos evakuiert werden kann, obwohl er nicht zu einem redundanten ReplicaSet gehört, können Sie die folgende Annotation verwenden:
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"