Kubernetes wird weniger fremd, wenn man aufhört, es als großen Remote-Server zu behandeln. Es ist keine Maschine mit einem schöneren SSH-Prompt. Es ist ein System, dem man beschreibt, wie Workloads aussehen sollen — und das danach daran arbeitet, die Wirklichkeit an diese Beschreibung anzugleichen.
Das klingt einfach. Es hat eine Weile gedauert, bis ich das wirklich gespürt habe.
Am Anfang wirkt Kubernetes wie ein Haufen Substantive: Pod, Deployment, Service, Ingress, ConfigMap, Secret, Node, Namespace. Die Versuchung ist groß, Definitionen auswendig zu lernen und zu hoffen, dass sich das Bild später ergibt. Definitionen helfen, reichen aber nicht. Ein besserer Einstieg sind ein paar Denkmodelle, die die Begriffe miteinander verbinden.
Dieser Beitrag richtet sich an die Phase dazwischen: etwas technischer Hintergrund, vielleicht Docker-Grundlagen, vielleicht ein erster Cluster in kind, minikube oder bei einem Cloud-Anbieter — aber noch ohne das Gefühl dafür, was Kubernetes unter der Haube tut.
Denkmodell 1: gewünschter Zustand, nicht Fernsteuerung
Auf einem klassischen Server führt man oft direkte Aktionen aus:
- Paket installieren.
- Prozess starten.
- Konfigurationsdatei ändern.
- Dienst neu starten.
Kubernetes verlangt eine andere Gewohnheit. Man beschreibt einen gewünschten Zustand:
- Diese Anwendung soll mit drei Replikaten laufen.
- Dieses Container-Image soll verwendet werden.
- Dieser Port soll im Cluster erreichbar sein.
- Diese Konfiguration soll im Pod verfügbar sein.
Dann versucht Kubernetes, den tatsächlichen Zustand an diesen gewünschten Zustand anzunähern.
Das Wort konvergieren ist wichtig. Kubernetes ist kein magischer Sofort-Ausführer. Es ist ein Reconciliation-System. Man schickt ein Objekt an den API-Server. Controller bemerken es. Der Scheduler platziert Pods. Kubelets auf den Nodes starten Container. Statusinformationen fließen zurück. Wenn etwas ausfällt, versuchen Controller meist erneut.
Eine gute Anfängerfrage lautet deshalb:
Was habe ich Kubernetes beschrieben, und was meldet Kubernetes gerade als tatsächlichen Zustand?
Beides ist nicht automatisch identisch.
kubectl get deployment <name> -n <namespace>
kubectl describe deployment <name> -n <namespace>
kubectl get pods -n <namespace> -l app=<label>
kubectl get liefert den schnellen Cockpit-Überblick. kubectl describe erzählt die Geschichte: Events, Selektoren, Replikate, Rollout-Status — und oft den ersten Hinweis, warum etwas hängt.
Ein häufiger Irrtum: „Ich habe das YAML angewendet, also läuft es.“ Anwenden bedeutet, dass die API den gewünschten Zustand angenommen hat. Es bedeutet noch nicht, dass das Image gezogen wurde, der Pod geplant ist, die Anwendung startet oder die Readiness-Probe erfolgreich war.
Denkmodell 2: Kubernetes ist eine Regelkreis-Maschine
Viele Kubernetes-Komponenten arbeiten wie Regelkreise:
- Aktuellen Zustand beobachten.
- Mit gewünschtem Zustand vergleichen.
- Eine Aktion ausführen, um die Abweichung zu verringern.
- Wiederholen.
Dieses Muster erklärt erstaunlich viel.
Ein Deployment-Controller bemerkt, dass ein Deployment drei Replikate verlangt. Er erstellt oder aktualisiert ein ReplicaSet. Der ReplicaSet-Controller bemerkt, dass drei Pods existieren sollen. Verschwindet ein Pod, wird ein neuer erstellt. Der Scheduler bemerkt ungeplante Pods und wählt Nodes. Das Kubelet auf dem Node versucht, zugewiesene Container zu starten.
Deshalb verschwinden manuelle Änderungen oft wieder.
Löscht man einen Pod, der von einem ReplicaSet verwaltet wird, erstellt Kubernetes normalerweise Ersatz. Das ist kein Trotz. Der Regelkreis tut genau das, was auf der höheren Ebene beschrieben wurde.
kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A5 ownerReferences
kubectl get replicaset -n <namespace>
kubectl get deployment -n <namespace>
Wenn jemand sagt „Kubernetes erstellt meinen Pod immer wieder neu“, lautet die nächste Frage: Wer besitzt diesen Pod? Die Antwort steckt oft in ownerReferences. Die Korrektur gehört meist auf die Ebene des Besitzers — nicht in einen Kampf gegen den einzelnen Pod.
Ein häufiger Irrtum: „Der Pod ist meine Anwendung.“ Im Pod läuft vielleicht der Anwendungsprozess. In Produktion verwaltet man aber meist ein Deployment, das ein ReplicaSet verwaltet, das wiederum Pods verwaltet. Der Pod ist oft die austauschbare Einheit, nicht die Quelle der Wahrheit.
Denkmodell 3: Pods sind Vieh — aber nicht sorglos
Der alte Vergleich „pets versus cattle“ ist etwas abgegriffen, aber der Kern ist nützlich: Ein Pod ist ersetzbar. Kubernetes kann ihn neu starten, verschieben oder mit anderem Namen neu erstellen.
Das heißt nicht, dass Pods egal sind. Logs, Events, Exit Codes und Probe-Fehler sind wertvolle Spuren. Aber die Anwendung sollte nicht davon abhängen, dass genau ein bestimmter Pod-Name für immer lebt.
Das verändert den Blick auf Speicher, Konfiguration und Fehlersuche.
Schreibt ein Pod wichtige Daten nur in sein Container-Dateisystem, können diese mit dem Pod verschwinden. Ruft ein anderer Dienst direkt die Pod-IP auf, kann diese Adresse später falsch sein. Ändert man manuell etwas in einem laufenden Container, ist diese Änderung nach dem nächsten Neustart weg.
Sinnvolle Gewohnheiten am Anfang:
- Wiederholbare Konfiguration gehört in Manifeste, Helm Values oder GitOps.
- Stabiler Netzwerkzugriff läuft über Services.
- Dauerhafte Daten brauchen Persistent Volumes.
- Manuelle Pod-Änderungen sind temporäres Debugging, keine echte Lösung.
Nützliche Prüfungen:
kubectl get pods -n <namespace> -o wide
kubectl describe pod <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> --previous
--previous wird leicht vergessen. Es zeigt Logs der vorherigen Container-Instanz in einem Pod. Bei Neustarts steht genau dort oft der entscheidende Hinweis.
Denkmodell 4: Labels sind die Verdrahtung
Labels sehen zuerst wie harmlose Metadaten aus. Sobald etwas nicht erreichbar ist, merkt man: Labels sind die Verdrahtung.
Ein Deployment nutzt Selektoren, um zu erkennen, welche Pods zu ihm gehören. Ein Service nutzt Selektoren, um zu entscheiden, welche Pods Traffic erhalten. Viele kubectl-Befehle nutzen Label-Selektoren, damit aus einem lauten Cluster ein lesbarer Ausschnitt wird.
Wenn Labels nicht passen, kann Kubernetes vollkommen gesund sein — und die Anwendung trotzdem unerreichbar bleiben.
Ein Beispiel: Ein Service selektiert app: web, die Pods tragen aber app: frontend. Der Service existiert. Die Pods existieren. DNS kann sogar funktionieren. Trotzdem hat der Service keine passenden Endpoints, also landet Traffic nicht bei den Pods.
Das prüft man direkt:
kubectl get service <service-name> -n <namespace> -o wide
kubectl get endpoints <service-name> -n <namespace>
kubectl get pods -n <namespace> --show-labels
kubectl get pods -n <namespace> -l app=<label>
Ein häufiger Irrtum: „Der Service zeigt auf mein Deployment.“ Meistens stimmt das nicht. Ein Service zeigt über Label-Selektoren auf Pods. Das Deployment erstellt Pods mit Labels. Die Beziehung ist indirekt — flexibel, aber am Anfang leicht missverständlich.
Deswegen zeichne ich für neue Workloads gern ein kleines Kastendiagramm:
- Deployment erstellt Pods mit Labels.
- Service wählt Pods über passende Labels aus.
- Ingress oder Gateway leitet externen Traffic zum Service.
- ConfigMaps und Secrets liefern Konfiguration in die Pods.
Wenn die Skizze die Labels nicht erklären kann, sollte man das YAML noch einmal ansehen.
Denkmodell 5: Namespaces sind Räume, keine Cluster
Namespaces teilen einen Cluster in benannte Bereiche. Das ist nützlich für Teams, Umgebungen oder Systemkomponenten. Namespaces sind aber keine vollständigen Sicherheitsgrenzen und keine eigenen Cluster.
Die wichtigste Anfängerlektion ist langweilig, aber praktisch: Viele Fehler sind einfach Befehle im falschen Namespace.
kubectl config current-context
kubectl get namespaces
kubectl get pods -n <namespace>
kubectl config set-context --current --namespace=<namespace>
Beim Lernen und Debuggen bevorzuge ich explizites -n <namespace>. Den Standard-Namespace im Kontext zu setzen kann bequem sein, verschleiert aber manchmal, wohin Befehle wirklich gehen.
Ein häufiger Irrtum: „In einem Namespace funktioniert es, also ist der Cluster in Ordnung.“ Namespaces können unterschiedliche Resource Quotas, Network Policies, Secrets, Service Accounts und Image-Pull-Rechte haben. Gleiches YAML, anderer Namespace, anderes Ergebnis.
Denkmodell 6: Scheduling ist ein Problem mit Bedingungen
Bleibt ein Pod im Zustand Pending, ist Kubernetes nicht unbedingt langsam. Vielleicht gibt es einfach keinen gültigen Platz für diesen Pod.
Der Scheduler betrachtet CPU- und Speicher-Requests, Taints, Tolerations, Node Selectors, Affinity-Regeln, Volume-Bedingungen und manchmal das Verhalten des Cluster Autoscalers. Man muss am ersten Tag nicht jedes Detail kennen. Wichtig ist: Scheduling ist eine Entscheidung unter Bedingungen.
Der erste Blick geht in die Events:
kubectl describe pod <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
kubectl get nodes -o wide
kubectl describe node <node-name>
Steht dort Insufficient cpu, ist die hilfreiche Frage nicht „Warum mag Kubernetes meinen Pod nicht?“ Besser ist: „Welchen Resource Request habe ich gesetzt, und hat irgendein Node dafür Platz?“
Requests sind keine Dekoration. Sie sagen Kubernetes, was ein Workload für die Platzierung braucht. Limits sind etwas anderes: Sie begrenzen die Nutzung zur Laufzeit. Wenn man beides verwechselt, entstehen viele schwer verständliche Anfängerprobleme.
Denkmodell 7: Health Checks sind Teil des Vertrags
Ein Container-Prozess kann laufen, ohne dass die Anwendung nutzbar ist. Vielleicht lädt sie noch Konfiguration. Vielleicht erreicht sie die Datenbank nicht. Vielleicht lebt der Prozess, reagiert aber nicht sinnvoll.
Kubernetes bietet Probes, um diesen Zustand genauer zu beschreiben:
- Eine Startup-Probe gibt langsam startenden Anwendungen Zeit.
- Eine Readiness-Probe sagt, ob der Pod Traffic erhalten soll.
- Eine Liveness-Probe sagt, ob Kubernetes den Container neu starten soll.
Ein häufiger Anfängerfehler ist eine zu aggressive Liveness-Probe. Wenn sie während einer langsamen Dependency oder kurzer Überlast fehlschlägt, startet Kubernetes möglicherweise einen Prozess neu, der sich selbst erholt hätte. Readiness ist oft der bessere erste Schritt: keinen Traffic schicken, bis die Anwendung wieder bereit ist.
Probe-Fehler findet man in der Pod-Beschreibung:
kubectl describe pod <pod-name> -n <namespace>
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.status.containerStatuses[*].restartCount}'
kubectl logs <pod-name> -n <namespace> --previous
Eine kleine Debugging-Reihenfolge
Wenn etwas nicht funktioniert, versuche ich, nicht sofort hektisch zu reparieren. Eine ruhige erste Runde sieht so aus:
kubectl config current-context
kubectl get pods -n <namespace> -o wide
kubectl get deploy,rs,svc -n <namespace>
kubectl describe pod <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
kubectl logs <pod-name> -n <namespace>
Damit klärt man:
- Schaue ich auf den richtigen Cluster?
- Bin ich im richtigen Namespace?
- Sind die erwarteten Ressourcen vorhanden?
- Meldet Kubernetes Scheduling-, Image-, Probe- oder Berechtigungsprobleme?
- Stimmen Anwendungslogs und Kubernetes-Sicht zusammen?
Das ist nicht fortgeschritten. Genau deshalb ist es nützlich. Viele frühe Kubernetes-Probleme werden kleiner, wenn die ersten fünf Minuten strukturiert sind.
Was man auswendig lernen sollte — und was nicht
Ein paar Grundbefehle darf man ruhig auswendig kennen. Muskelgedächtnis hilft, wenn ein Cluster unübersichtlich wird.
Aber niemand muss jedes Feld in jedem Manifest im Kopf behalten. Die Werkzeuge sind dafür da.
kubectl explain deployment.spec
kubectl explain pod.spec.containers
kubectl explain service.spec
kubectl explain wirkt unspektakulär, hält einen aber nahe an der API. Das ist wichtig, weil Kubernetes nicht in erster Linie ein Kommandozeilenwerkzeug ist. Kubernetes ist eine API mit Controllern darum herum. kubectl ist nur ein Client.
Die tiefere Anfängerfähigkeit besteht darin, bessere Fragen zu stellen:
- Welches Objekt ist hier die Quelle der Wahrheit?
- Welcher Controller besitzt das Objekt, das ich gerade sehe?
- Welche Labels verbinden die Ressourcen?
- Was sagt der gewünschte Zustand?
- Was sagt der aktuelle Status?
- Welches Event wurde zuletzt aufgezeichnet?
Diese Fragen funktionieren in minikube, in einem verwalteten Cloud-Cluster und auch in OpenShift, wo zusätzliche Plattformregeln um dieselben Kubernetes-Konzepte liegen.
Schlussgedanke
Kubernetes ist komplex, aber nicht beliebig. Es folgt einer starken inneren Logik: gewünschter Zustand, Reconciliation, ersetzbare Pods, Verbindungen über Labels, Scheduling unter Bedingungen und explizite Health-Signale.
Viele Einsteiger fühlen sich überfordert, weil sie nicht alle Begriffe gleichzeitig im Kopf halten können. Ich denke, das bessere Ziel ist kleiner: Regelkreise verstehen, Besitzverhältnisse verfolgen, Events lesen und Labels prüfen. Wenn diese Denkmodelle sitzen, wirken die Begriffe weniger wie Karteikarten und mehr wie Teile eines Betriebssystems für verteilte Anwendungen.