Start / Cheat Sheets

Cheat Sheet

Kubernetes im Betrieb — Cheat Sheet

Stand: · Docker, Podman und Kubernetes für Entwickler

KubernetesGitOpsObservabilityKI-Inferenz

Der Spickzettel zur zweiten Hälfte des Seminars Docker, Podman und Kubernetes für Entwickler: die Objekte und ihre Zuständigkeiten, Probes und Ressourcen, Skalierung und Auslieferung, Rechte und Netzregeln — bis hin zum Betrieb von Sprachmodellen auf GPU-Knoten. Was davor beim Bauen und Ausliefern der Images passiert, steht auf dem ersten Blatt: Container, Images und Lieferkette.

Maßgeblich für API-Fassungen und Feldnamen ist die Kubernetes-Dokumentation; dieses Blatt trifft eine Auswahl — die Entscheidungsraster, die einen Versionssprung überleben.

Die Bauteile eines Clusters

BauteilAufgabe
kube-apiservernimmt alle Anfragen an, prüft Rechte, schreibt sie fort
etcdverwahrt den gesamten Zustand des Clusters
kube-schedulerwählt für jeden neuen Pod einen passenden Knoten
kube-controller-managerbetreibt die Regler, die den Soll-Zustand herstellen
cloud-controller-managerspricht mit der Umgebung, etwa für Lastverteiler

Auf jedem Arbeitsknoten laufen zusätzlich kubelet, kube-proxy und die Container-Laufzeit. Die Beschreibung ist die Wahrheit, nicht der Ist-Zustand: Fehlersuche heißt, den Unterschied zwischen beiden zu erklären.

kubectl get nodes -o wide
kubectl get pods -A
kubectl api-resources | head -20
kubectl cluster-info

Modul: Kubernetes-Grundlagen

Pod, ReplicaSet und Deployment

EbeneZuständig für
Poddie laufenden Container, ihr Netz und ihre Ablage
ReplicaSetdie Anzahl gleichartiger Pods
Deploymentden Übergang zwischen Fassungen, also das Ausrollen

Ein gelöschter Pod kehrt zurück, ein gelöschtes Deployment nimmt alles darunter mit. Die Auswahl (selector.matchLabels) greift auf die Labels der Vorlage — passen sie nicht zusammen, wird nichts verwaltet.

kubectl rollout status deploy/beispiel-api
kubectl rollout history deploy/beispiel-api
kubectl rollout undo deploy/beispiel-api

Zurückrollen wechselt auf das vorige ReplicaSet — die alten Pods sind noch beschrieben, nur auf null gesetzt.

Modul: Kubernetes-Grundlagen

Label oder Annotation

EigenschaftLabelAnnotation
Auswählbarjanein
Länge des Wertskurz begrenztpraktisch beliebig
Typischer InhaltRolle, Stufe, FassungKontakt, Werkzeugdaten
Wirkt auf Reglerja, unmittelbarnur wenn ein Werkzeug sie liest
kubectl get pods -l app=beispiel-api
kubectl get pods -l 'stufe in (test, abnahme)'
kubectl get pods --show-labels

Dieselben Ausdrücke stehen im Manifest unter matchLabels und matchExpressions. Ein Label mit der Fassung darin, das gleichzeitig zur Dienstauswahl gehört, lässt Pods bei jedem Ausrollen aus ihrem Dienst fallen.

Modul: Kubernetes-Grundlagen

Services und Erreichbarkeit

ArtBedeutung
ClusterIPnur im Cluster erreichbar, die Voreinstellung
NodePortzusätzlich über einen hohen Port jedes Knotens
LoadBalancerverlangt einen Lastverteiler von der Umgebung
ExternalNameverweist auf einen fremden Namen, ohne eigene Ziele
ohne Adressegibt die Pod-Adressen direkt heraus, für Datenbanken

Die Portspanne für NodePort liegt voreingestellt zwischen 30000 und 32767. Für den Weg von außen ist die Richtung eindeutig:

FrageIngressGateway API
Weiterentwicklungeingefrorenlaufend
Rollen getrenntneinja, Tor und Weg
Anbieterbesonderheitenüber Annotationenüber eigene Objekte
Andere Protokollenur über Umwegeeigene Objektarten

Für bestehende Cluster bleibt Ingress vertretbar — für Neues ist die Empfehlung eindeutig. Das Tor beschreibt der Betrieb einmal, Teams hängen nur ihre HTTPRoute daran.

Modul: Kubernetes-Grundlagen

ConfigMap oder Secret

FrageConfigMapSecret
InhaltEinstellungen, GrenzwerteKennwörter, Schlüssel
Ablage im Clusterim Klartextkodiert, nicht verschlüsselt
Verschlüsselung ruhendnicht nötigam Cluster einzurichten
Als Datei einhängbarjaja, und dann bevorzugt

Als Datei eingehängt landen Geheimnisse nicht in der Prozessumgebung, wo sie leicht ausgelesen werden — und wo sie in Protokolle und Absturzberichte wandern. Ganze Blöcke kommen über envFrom, einzelne Werte über valueFrom; beides ist mischbar.

Modul: Kubernetes-Grundlagen

Die drei Probes

PrüfungFrageFolge bei Fehlschlag
Lebendigkeitarbeitet der Prozess noch?Neustart des Containers
Bereitschaftkann er Anfragen annehmen?fällt aus der Verteilung
Startist er fertig angelaufen?Neustart, blockiert bis dahin

Nur die Bereitschaftsprüfung darf von Abhängigkeiten abhängen — die anderen nie. Prüft die Lebendigkeit die Datenbank mit, startet der Dienst bei jeder Datenbankstörung neu.

startupProbe:
  httpGet: { path: /start, port: 3000 }
  failureThreshold: 30
  periodSeconds: 2
livenessProbe:
  httpGet: { path: /lebt, port: 3000 }
readinessProbe:
  httpGet: { path: /bereit, port: 3000 }

Die Startprüfung darf großzügig zählen — sie läuft nur einmal und blockiert die anderen. Sie ersetzt die lange Anfangsverzögerung.

Modul: Kubernetes-Grundlagen

Ressourcen und QoS-Klassen

KlasseBedingungBei Knappheit
GuaranteedGrenze gleich Anforderung, überall gesetztweicht zuletzt
Burstableirgendein Wert gesetzt, aber nicht deckungsgleichweicht danach
BestEffortweder Anforderung noch Grenze gesetztweicht zuerst

Die Klasse wird berechnet, nicht gesetzt — sie ergibt sich aus den Werten aller Container des Pods. Der Unterschied zwischen den beiden Grenzen ist entscheidend: Eine Speichergrenze wird hart durchgesetzt, Überschreiten beendet den Prozess; eine Rechenzeitgrenze bremst nur — der Dienst wird langsam, nicht beendet.

Modul: Kubernetes-Grundlagen

Fehlersuche: Symptom und erster Griff

SymptomErster Griff
Pod bleibt ausstehendEreignisse: kein Knoten passt zur Anforderung
NeustartschleifeAusgaben des Vorgängers und die Lebendigkeitsprüfung
Image kann nicht geholt werdenBeschreibung: Name, Digest, Zugangsdaten
Dienst antwortet nichtEndpunkte prüfen, dann die Label-Auswahl
Sofort beendetSpeichergrenze: der Prozess wurde hart beendet
kubectl describe pod beispiel-api-7f9
kubectl logs beispiel-api-7f9 --previous
kubectl exec -it beispiel-api-7f9 -- sh
kubectl get events --sort-by=.lastTimestamp

--previous zeigt die Ausgaben des abgestürzten Vorgängers — ohne sie fehlt bei einem Neustart der Grund. Bei einem gehärteten Image ohne Shell hilft der Blick hinein nicht; dann ein Nebencontainer zum Untersuchen. Behoben wird im Manifest, nicht am laufenden Objekt.

Modul: Kubernetes-Grundlagen

Helm oder Kustomize

FrageHelm-ChartKustomize
GrundprinzipPlatzhalter füllenSchichten überlagern
Manifest lesbarerst nach dem Rendernimmer
Weitergabe an Dritteals Paket üblicheher intern
Eingebaut in kubectlneinja, über apply -k

Beides ist kombinierbar — ein gerendertes Chart lässt sich als Basis weiter überlagern. Die Chart-Fassung zählt das Paket, appVersion nur die enthaltene Anwendung; sie wirkt nirgends mit.

helm lint ./beispiel
helm template test ./beispiel -f werte-test.yaml
helm upgrade --install test ./beispiel --namespace beispiel --atomic --wait

helm template rendert ohne den Cluster anzufassen — die billigste Fehlersuche.

Modul: Produktive Skalierung

GitOps mit Argo CD

SchalterWirkung
enabledschaltet das automatische Angleichen ganz ab
prunelöscht, was im Repository nicht mehr beschrieben ist
selfHealnimmt Änderungen am Cluster zurück, die nicht im Git stehen

Die beiden letzten stehen voreingestellt auf falsch — als Sicherung gegen unbeabsichtigtes Löschen. Die Einführungsreihenfolge ist damit vorgegeben: erst nur anzeigen, dann Abweichungen abarbeiten, dann Selbstheilung, und Löschen zuletzt. Zurückgerollt wird über das Repository, nicht im Cluster.

Modul: Produktive Skalierung

Drei Arten zu skalieren

WegÄndertPasst bei
HPAZahl der Podsgleichmäßiger Last am Dienst
KEDAZahl der PodsAufträgen, Ereignissen, Warteschlangen
VPAAnforderungen je Podfalsch geschätzten Ressourcen

HPA und VPA auf derselben Messgröße arbeiten gegeneinander — diese Kombination bleibt außen vor. Das Verhalten des HPA in seinen Voreinstellungen:

EinstellungVoreinstellung und Wirkung
Beruhigung nach obennull Sekunden, reagiert unmittelbar
Beruhigung nach unten300 Sekunden, verhindert Pendeln
Toleranz0,1 — kleine Abweichungen lösen nichts aus
Nur bereite Podszählen in die Rechnung ein

Die lange Beruhigung nach unten ist Absicht: Abwärts pendeln kostet mehr als ein paar Pods zu viel. Ohne gesetzte Anforderungen ist die Auslastung überhaupt nicht berechenbar. KEDA darf bis auf null herunter — für Rechenarbeit sehr sinnvoll, für Dienste an der Web-Schnittstelle nicht.

Modul: Produktive Skalierung

Messgrößen und die vier Signale

ArtBedeutung
Zählerwächst nur, wird über Zeitfenster abgeleitet
Messwertsteigt und fällt, etwa belegter Speicher
HistogrammVerteilung, Grundlage für Perzentile
Zusammenfassungvorberechnete Perzentile je Dienst
rate(anfragen_gesamt[5m])
rate(anfragen_gesamt{code=~"5.."}[5m]) / rate(anfragen_gesamt[5m])
histogram_quantile(0.95, rate(dauer_sekunden_bucket[5m]))

Die vier Signale, mit denen man anfängt: Verkehr, Fehler, Dauer (als Perzentil, nie als Mittelwert) und Sättigung. Das Zeitfenster gehört zur Abfrage, nicht zur Messgröße — es bestimmt, wie träge die Kurve reagiert.

SichtBeantwortetKosten
Messwertist es gerade schlimm?gering, verdichtet
Protokollwas genau ist passiert?hoch, wächst mit der Last
Tracewo geht die Zeit hin?mittel, meist stichprobenweise

Verknüpft werden die drei über gemeinsame Kennungen — ohne sie bleibt jede Sicht für sich.

Modul: Produktive Skalierung

Canary, Blau/Grün und Störungsbudget

FrageCanaryBlau/Grün
Verkehranteilig verschobenauf einmal umgeschaltet
Ressourcenwenige zusätzliche Podsdoppelter Satz
RücknahmeAnteil auf nullzurückschalten
Messung nötigja, sonst sinnlosfür die Freigabe

Ohne automatische Auswertung der Messwerte ist beides nur ein langsameres Ausrollen. Ein PodDisruptionBudget schützt dabei weniger, als sein Name nahelegt:

FallWirkt das Budget?
Knoten wird geräumtja, das ist sein Zweck
Cluster verkleinert sich selbstja, über dieselbe Schnittstelle
Knoten fällt aus, Kernel stehtnein, unfreiwillige Störung
Pod von Hand gelöschtnein, umgeht das Budget
Ausrollen einer neuen Fassungnein, das regelt das Deployment

Ein Budget schützt gegen Eingriffe, die fragen — gegen Unglücke und gegen Löschen schützt es nicht.

Modul: Produktive Skalierung

Rechte vergeben mit RBAC

RolleUmfang
cluster-adminalles, überall, ohne Einschränkung
adminVerwaltung eines Namensraums samt Rechtevergabe
editSchreiben im Namensraum, aber keine Rechtevergabe
viewLesen im Namensraum, ohne Geheimnisse

Für zwei Teams im selben Cluster genügen meist admin und view, je über eine Bindung im Namensraum. Eine RoleBinding darf eine ClusterRole nennen — sie gilt dann nur in diesem Namensraum. Es gibt keine Verbotsregeln: Rechte addieren sich, entziehen lässt sich nur, was nicht vergeben wurde.

kubectl auth can-i delete pods -n beispiel
kubectl auth can-i --list -n beispiel
kubectl auth can-i get secrets \
  --as=system:serviceaccount:beispiel:auswertung

Die letzte Form fragt in fremdem Namen — der ehrlichste Weg, eine Rechtevergabe abzunehmen. Das Recht auf Geheimnisse ist das Recht auf alle Zugangsdaten des Namensraums.

Modul: Plattform- und Cluster-Security

NetworkPolicies

FrageAntwort
Wirkt sie ohne passenden Netz-Baustein?nein, sie bleibt wirkungslos
Gibt es Verbotsregeln?nein, Regeln addieren sich
Auf welcher Ebene wirkt sie?Adressen und Ports, nicht Inhalte
Muss beide Seiten passen?ja, Ausgang dort und Eingang hier
Antwortverkehr eigens erlauben?nein, er ist eingeschlossen

Ein Pod kann sich nie selbst aussperren, und der Verkehr zum eigenen Knoten bleibt immer erlaubt. Der Einstieg ist eine leere Auswahl — sie meint alle Pods:

spec:
  podSelector: {}
  policyTypes: [Ingress, Egress]

Keine Regelzeile darunter heißt: nichts erlaubt. Die Namensauflösung muss danach eigens freigegeben werden — sonst läuft jeder Aufruf in eine Zeitüberschreitung.

Modul: Plattform- und Cluster-Security

Eingangsprüfungen und Geheimnisse

ArtWirkung
Prüfenweist ab oder berichtet, ändert nichts
Ergänzensetzt fehlende Angaben, bevor das Objekt entsteht
Erzeugenlegt begleitende Objekte im Namensraum an

Ergänzen ist bequem und heikel: Was das Werkzeug einsetzt, steht in keinem Repository.

FrageKyvernoGatekeeper
Regeln geschrieben inYAML, wie Manifesteeigener Regelsprache
Einstiegflachsteiler, dafür mächtiger
Ergänzen und Erzeugeneingebautnur Prüfen und Ergänzen
Fertige Regelsammlungumfangreich gepflegtvorhanden

Für Geheimnisse im Repository stehen drei Wege zur Wahl:

WegIm Repository stehtVoraussetzung
Externer Bezugein VerweisTresor und Zugangsweg
Versiegeltder verschlüsselte WertSchlüsselpaar im Cluster
Klartextder Wert selbstkeine, und keine Sicherheit

Beim versiegelten Weg hängt alles am Schlüssel im Cluster — geht er verloren, ist nichts entschlüsselbar. Am Ende eines externen Bezugs entsteht ein gewöhnliches Secret; Leserechte darauf bleiben nötig.

Modul: Plattform- und Cluster-Security

Sichern, Updates und Prüfprotokoll

BestandteilAnmerkung
Objekte des Namensraumsals Archiv im Objektspeicher
Abbilder der Datenträgerüber die Schnittstelle des Speichers
Dateiweise SicherungAusweg, wenn keine Abbilder möglich sind
Zeitplan und Aufbewahrungeigene Objekte, nicht Skripte

Eine Sicherung ist ausdrücklich nicht atomar — was während des Laufs entsteht, kann fehlen. Läuft die Aufbewahrung ab, verschwinden Sicherung, Dateien und Datenträgerabbilder zusammen.

BauteilAbstand zum Schnittstellendienst
kubeletbis zu drei Nebenversionen älter
kube-proxybis zu drei Nebenversionen älter
Regler und Planerhöchstens eine Nebenversion älter
kubectleine darüber oder darunter
zweiter Schnittstellendiensthöchstens eine Nebenversion Abstand

Gepflegt werden drei Nebenversionen gleichzeitig, jede rund ein Jahr. Die Steuerungsebene wird zuerst aktualisiert, die Knoten danach — eine Nebenversion je Schritt.

StufeHält fest
Nonenichts, die Anfrage fällt heraus
Metadatawer, wann, welches Objekt, welcher Vorgang
Requestdazu den Inhalt der Anfrage
RequestResponsedazu auch die Antwort im Wortlaut

Im Prüfprotokoll gewinnt die erste passende Regel. Die höchste Stufe auf Geheimnisse angewandt schreibt deren Werte mit — bewusst wählen.

Modul: Plattform- und Cluster-Security

GPUs im Cluster

BestandteilAufgabe
Treiberspricht die Karte an, passend zum Kern
Laufzeitschichtreicht die Karte in den Container hinein
Geräte-Pluginmeldet die Karte an den Knotendienst
Kennzeichnungsetzt Labels, nach denen Pods auswählen
Messwerteliefert Auslastung und Speicherbelegung

Bei der Ressource nvidia.com/gpu sind Anforderung und Grenze stets gleich — Bruchteile gibt es nicht. Ohne Kennzeichnung der Knoten landen Pods ohne GPU-Bedarf auf den teuersten Maschinen. Die Dynamic Resource Allocation beschreibt dasselbe feiner:

ObjektBedeutung
DeviceClassfasst gleichartige Geräte zusammen
ResourceClaimverlangt ein Gerät für einen Pod
ResourceClaimTemplateerzeugt je Pod eine eigene Anforderung
ResourceSlicemeldet, welche Geräte ein Knoten hat

Die Anforderung gehört zum Pod, nicht zum Container. Verdrängung gibt es auch hier nicht: Ein wichtiger Pod bleibt ausstehend, bis ein Gerät frei wird.

FrageZeitscheibenInstanzen
Speicher getrenntneinja, in der Hardware
Fehler getrenntneinja
Einrichtungeine EinstellungKarte umkonfigurieren
Verfügbar aufallen Kartenneueren Modellen
Anteil zusicherbarnein, alle gleichja, je Profil

Die Dokumentation warnt ausdrücklich: Zeitscheiben trennen weder Speicher noch Fehler zwischen den Nutzern.

Modul: Kubernetes für KI-Inferenz

Modelle ausliefern mit KServe

FähigkeitAnmerkung
Schnittstelle nach OpenAI-Mustervorhandene Anwendungen sprechen sie schon
Herunterskalieren auf nullspart die teure Karte im Leerlauf
Schrittweises Ausrollenwie beim Deployment, nur je Modellfassung
Modellzwischenspeicher am Knotenverkürzt den Kaltstart

Quelle (uri) und Name (name) sind zweierlei: die eine sagt, woher das Modell kommt, der andere ist der, den Aufrufe später nennen. Das Projekt steht im Reifegrad Incubating — die generativen Objekte tragen noch eine Alpha-Fassung.

Gegenüber dem Geräte-Plugin bringt die dynamische Zuweisung dazu:

FähigkeitVorher und jetzt
Auswahl nach Eigenschaftenvorher Stückzahl, jetzt Ausdrücke
Gemeinsame Nutzungvorher gar nicht, jetzt beschreibbar
Herstellereinstellungenvorher je Knoten, jetzt je Arbeitslast
Verdrängungauch jetzt nicht — der Pod wartet

Modul: Kubernetes für KI-Inferenz

Inferenz: Kennzahlen und Steuergrößen

KennzahlWas sie aussagt
Zeit bis zum ersten Wortwie schnell die Antwort anläuft
Zeit je weiterem Wortwie flüssig sie danach läuft
Wörter je Sekunde gesamtwie viel die Karte insgesamt schafft
Wartende Anfragenob die Engine noch annehmen kann
Belegung des Zwischenspeicherswie nah die Karte an ihrer Grenze ist

Die ersten beiden fühlt der Nutzer, die letzten beiden steuern die Skalierung:

GrößeEignung zum Skalieren
Auslastung der Karteuntauglich, liegt fast immer hoch
Wartende Anfragengut, zeigt fehlende Aufnahmefähigkeit
Belegung des Zwischenspeichersgut, zeigt die Grenze der Karte
Zeit bis zum ersten Wortals Ziel geeignet, als Regelgröße träge
Anfragen je Sekundenur bei gleichförmigen Anfragen

Zwei Ebenen skalieren hier: Abbilder je Karte und Karten je Cluster — die zweite dauert Minuten. Kontextlänge und Speicheranteil bestimmen zusammen, wie viele Anfragen gleichzeitig passen:

vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.90 \
  --tensor-parallel-size 1

Modul: Kubernetes für KI-Inferenz

Verteilte Inferenz und Kaltstart

ArtTeilt
Tensor-AufteilungSchichten des Modells über Karten eines Knotens
Fließband-AufteilungAbschnitte des Modells über Knoten
Daten-Aufteilungganze Abbilder für mehr Durchsatz
Experten-AufteilungExperten eines Mischmodells über Knoten

Die Tensor-Aufteilung kostet Bandbreite zwischen den Karten — deshalb bleibt sie meist innerhalb eines Knotens.

AbschnittGegenmittel
Abbild holenAbbild auf den Knoten vorziehen
Modell holenAblage im Cluster statt Bezug aus dem Netz
Modell in den Speicher ladenKarte warm halten, nicht auf null gehen
Treiber und LaufzeitKnoten vorhalten statt neu beschaffen

Die letzten beiden kosten Geld im Leerlauf — genau das ist die Abwägung. Eine Modellablage muss ReadWriteMany sein, sonst kann nur ein Abbild gleichzeitig starten. Bezahlt wird die Karte nach Zeit, nicht nach erzeugten Wörtern; die Kennzahl heißt deshalb Wörter je Kartenstunde.

Modul: Kubernetes für KI-Inferenz

Typische Fallen

  • Erwarten, dass eine Änderung sofort wirkt — Regler arbeiten in Schleifen, und der Ist-Zustand ist nie die Wahrheit.
  • Am laufenden Objekt ändern — die Ursache ist damit nur bis zum nächsten Ausrollen versteckt.
  • Die Datenbank in der Lebendigkeitsprüfung mitprüfen — jede Störung wird zur Neustartschleife.
  • Ein Secret für verschlüsselt halten — sein Inhalt ist kodiert, nicht geschützt.
  • Nur Grenzen setzen, keine Anforderungen — der Planer arbeitet dann blind, und der HPA kann nichts berechnen.
  • Die Replikatzahl im Manifest festschreiben — sie arbeitet gegen den Skalierer.
  • Einen Web-Dienst auf null skalieren — die erste Anfrage läuft in eine Zeitüberschreitung, solange der Kaltstart ungemessen ist.
  • Mittelwerte für Antwortzeiten anzeigen — die langsamen Fälle verstecken sich darin.
  • Löschen in Argo CD sofort einschalten — von Hand angelegte Hilfsobjekte verschwinden mit.
  • Alles zumachen und die Namensauflösung vergessen — der Klassiker bei NetworkPolicies.
  • Der voreingestellten Dienstkennung Rechte geben — sie sind damit jedem Pod geschenkt.
  • Sichern und nie wiederherstellen — eine ungeprüfte Sicherung ist keine.
  • Zeitscheiben für Trennung halten — zwei Modelle nebeneinander sprengen den Kartenspeicher ohne Warnung.

Zum Seminar Docker, Podman und Kubernetes für Entwickler