☸ Kubernetes im Heimlabor

Kurs › Folge 26

Autoscaling: HPA und der metrics-server

Mehr Pods bei Last — und warum `kubectl top` erst einmal gar nicht funktioniert.

Das Video zu dieser Folge ist noch nicht veröffentlicht. Die Notizen stehen trotzdem schon hier.

Was du danach kannst

  • erklaeren, warum Kubernetes von sich aus keine Messwerte sammelt
  • den metrics-server installieren und den Zertifikatsfehler beheben
  • einen HorizontalPodAutoscaler einrichten und seine Rechnung nachvollziehen
  • Last erzeugen und das Hoch- und Runterskalieren beobachten

kubectl top nodes funktioniert nicht — und das ist richtig

error: Metrics API not available

Das ist keine kaputte Installation. Kubernetes sammelt von sich aus keine Messwerte. kubectl top fragt eine API namens metrics.k8s.io ab, und die gehört nicht zum Kern — sie wird von einer Zusatzkomponente nachgereicht.

Das überrascht fast jeden, weil kubectl top aussieht, als gehöre es dazu. Genauso wenig gehören Dashboard, Prometheus oder ein Ingress-Controller zum Kern. Kubernetes liefert die Mechanik, nicht die Ausstattung.

Angehängte APIs

Der metrics-server registriert sich als APIService und erweitert damit die Kubernetes-API um einen Pfad. Danach fühlt sich metrics.k8s.io an wie ein eingebauter Teil:

kubectl get apiservices | grep metrics

Das ist ein Muster, das dir wieder begegnet — genau so binden sich später auch andere Erweiterungen ein.

Installieren

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl -n kube-system get deploy metrics-server -w

Und jetzt bleibt er auf 0/1 stehen.

Der Zertifikatsfehler

kubectl -n kube-system logs deploy/metrics-server | tail -20
x509: cannot validate certificate ... because it doesn't contain any IP SANs

Warum das passiert: metrics-server holt die Werte direkt beim kubelet jedes Knotens ab, über HTTPS. Die Zertifikate, mit denen sich die kubelets ausweisen, sind bei kubeadm selbstsigniert und tragen die Knoten-IP nicht als gültigen Namen. metrics-server prüft das — und weigert sich zu Recht.

Der schnelle Weg (Labor)

kubectl -n kube-system patch deployment metrics-server --type=json \
  -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'

Nach etwa einer Minute:

kubectl top nodes
kubectl top pods -A

Was du damit abschaltest: metrics-server prüft die Zertifikate der kubelets nicht mehr. Im Labor unkritisch, im Produktivbetrieb nicht akzeptabel — wer sich dazwischenschaltet, könnte falsche Messwerte liefern und damit Skalierungsentscheidungen beeinflussen.

Der saubere Weg

In der kubelet-Konfiguration serverTLSBootstrap: true setzen. Dann stellen die kubelets Zertifikatsanträge, die von der Cluster-CA unterschrieben werden:

kubectl get csr
kubectl certificate approve <name>

Danach stimmt die Vertrauenskette und der unsichere Schalter kann weg.

Was metrics-server ist — und was nicht

Ist: aktuelle Werte für kubectl top und Skalierungsentscheidungen
Ist nicht: ein Überwachungssystem

Er hält nur ein kurzes Fenster im Speicher, schreibt nichts weg und kennt keine Vergangenheit. Wer wissen will, wie die Auslastung gestern um drei war, braucht Prometheus — Folge 25.

Der HPA und seine Rechnung

kubectl autoscale deployment web --cpu-percent=50 --min=2 --max=10
kubectl get hpa

Die Formel dahinter:

gewünschte Repliken = aufgerundet( aktuelle Repliken × ( aktueller Wert / Zielwert ) )

Bei 4 Pods mit im Schnitt 80 % gegen ein Ziel von 50 %: 4 × (80/50) = 6,4 → 7 Repliken.

Der Punkt, an dem die meisten scheitern

--cpu-percent=50 heißt nicht „50 Prozent eines Kerns". Es heißt 50 Prozent der angeforderten CPU — also von resources.requests.cpu.

Ohne Requests gibt es keine Bezugsgröße, und der HPA meldet:

unable to get metrics for resource cpu: missing request for cpu

Deshalb hängt diese Folge direkt an Folge 20. Requests sind nicht nur eine Reservierung für den Scheduler — sie sind die Grundlage jeder prozentualen Skalierung.

Warum das Runterfahren so lange dauert

Hochskaliert wird sofort. Heruntergefahren erst nach dem Stabilisierungsfenster — voreingestellt 300 Sekunden.

Der Grund ist Erfahrung: Ohne diese Bremse würde die Zahl der Pods bei schwankender Last ständig hin und her springen, und jeder Wechsel kostet Startzeit und Verbindungen. Einstellbar ist es:

behavior:
  scaleDown:
    stabilizationWindowSeconds: 60

Zum Nachlesen

Eine geordnete Übersicht über die offizielle Dokumentation steht unter Nachlesen.

Befehle aus dieser Folge

  • kubectl top nodes
  • kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
  • kubectl -n kube-system logs deploy/metrics-server
  • kubectl autoscale deployment web --cpu-percent=50 --min=2 --max=10
  • kubectl get hpa -w
  • kubectl describe hpa web

Begriffe

metrics.k8s.io
eine angehaengte API (API-Aggregation) — im Kern von Kubernetes nicht enthalten
metrics-server
liefert aktuelle CPU- und Speicherwerte fuer kubectl top und den HPA — ohne Verlauf
HPA
erhoeht und senkt die Zahl der Repliken anhand von Messwerten
Stabilisierungsfenster
verhindert, dass die Zahl der Pods staendig hin und her springt
--kubelet-insecure-tls
Notausgang im Labor, im Produktivbetrieb nicht akzeptabel

Übung — mach es selbst

Erst kaputt, dann heil, dann skaliert.

  1. kubectl top nodes — die Fehlermeldung ansehen, bevor du etwas installierst. Verstehen, was sie sagt.
  2. metrics-server installieren, nicht gleich reparieren. Warte, bis der Pod auf 0/1 steht, und lies die Logs. Die Zeile mit x509 ist die Antwort.
  3. Reparieren, kubectl top nodes erneut.

Dann der HPA:

  1. Deployment web mit resources.requests.cpu: 100m versehen — ohne Requests kann der HPA nichts berechnen. Warum? Siehe unten.
  2. kubectl autoscale deployment web --cpu-percent=50 --min=2 --max=10
  3. Last erzeugen: kubectl run last --rm -it --image=busybox -- /bin/sh -c "while true; do wget -q -O- http://web; done"
  4. In einem zweiten Fenster kubectl get hpa -w mitlaufen lassen.
  5. Last beenden — und die Zeit stoppen, bis wieder heruntergefahren wird. Es sind rund fuenf Minuten. Woher kommt dieser Wert?