Zum Inhalt

Lab 25: Kubernetes navigieren und troubleshooten mit k9s

k9s ist ein Terminal-UI für Kubernetes. Es zeigt die Cluster-Ressourcen in einer Live-Tabelle, die ihr mit der Tastatur bedient. Statt für jede Frage ein separates kubectl get, describe oder logs abzusetzen, wechselt ihr zwischen den Ressourcen und lest ihre Details an einer Stelle.

Ziel dieser Übung: Am Ende könnt ihr einen Cluster in k9s navigieren, Ressourcen inspizieren, Logs lesen und eine Shell öffnen, einen Workload per Port-Forward erreichen und skalieren sowie ein kaputtes Deployment diagnostizieren und reparieren, ohne das TUI zu verlassen.

Shells: k9s ist ein Terminal-UI, daher ist jeder Tastendruck in diesem Lab unter Windows, macOS und Linux identisch. Nur eine Handvoll kubectl-/curl-Befehle laufen in eurer Shell. Wo sich PowerShell von Bash unterscheidet, sind beide Varianten angegeben.


Teil 0: Setup

k9s ist auf eurer Maschine bereits installiert. Prüft es und startet von einem laufenden minikube-Cluster aus.

k9s version

Deployt die Workloads, die ihr untersuchen werdet (eine gesunde App plus eine, die absichtlich kaputt ist). Speichert das folgende Manifest als setup.yaml:

# Lab 25 - k9s-Playground-Workloads.
# Zwei Deployments im default-Namespace:
#   * web    - ein gesundes nginx (2 Replicas) plus ein ClusterIP-Service.
#   * broken - ein nginx mit einem nicht existierenden Image-Tag (ImagePullBackOff),
#              das ihr aus k9s heraus diagnostiziert und repariert.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: nginx
          image: nginx:1.29.4
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 20
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "200m"
              memory: "256Mi"
---
apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    app: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: broken
  labels:
    app: broken
spec:
  replicas: 1
  selector:
    matchLabels:
      app: broken
  template:
    metadata:
      labels:
        app: broken
    spec:
      containers:
        - name: nginx
          image: nginx:1.29.4-doesnotexist
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 20
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "200m"
              memory: "256Mi"

Wendet es dann an (führt das aus dem Verzeichnis aus, in dem ihr die Datei gespeichert habt):

kubectl apply -f setup.yaml

Das erzeugt im default-Namespace:

  • web: ein gesundes nginx-Deployment mit 2 Replicas plus einen web-Service.
  • broken: ein nginx-Deployment, das nicht startet (warum, findet ihr in Teil 5 heraus).

Startet nun k9s:

k9s

Ihr landet auf einer Ressourcen-Tabelle. Der Header (oben links) zeigt euren Context und Namespace; oben rechts stehen die im aktuellen View verfügbaren Tasten. Zwei Tasten, die ihr euch von Anfang an merken solltet:

  • Esc: zurückgehen / einen Filter löschen.
  • :q dann Enter, oder Ctrl-C: k9s beenden.

Teil 1: Sich zurechtfinden

k9s nutzt einen Command-Prompt, ähnlich wie Vim. Drückt :, tippt eine Ressource, drückt Enter.

  1. Springt zwischen Ressourcen-Typen:
  2. :pods Enter: alle Pods
  3. :deployments Enter: Deployments
  4. :services Enter: Services
  5. :namespaces Enter: Namespaces

Kurznamen funktionieren ebenfalls: :po, :deploy, :svc, :ns. Die Aliase sind dieselben, die kubectl verwendet.

  1. Drückt ?, um den Hilfe-Screen mit allen Key-Bindings für den aktuellen View zu öffnen. Drückt Esc zum Schließen.

  2. Namespaces. Drückt 0, um Pods aus allen Namespaces anzuzeigen. Um euch auf einen einzelnen Namespace zu fokussieren, führt :ns Enter aus und wählt einen aus — das funktioniert immer. Der Header listet Namespaces zusätzlich mit einer vorangestellten Ziffer (z. B. <1>); diese Ziffer zu drücken ist eine Abkürzung für dasselbe. Setzt ihn für den Rest des Labs zurück auf default.

  3. Filter. Drückt im Pods-View /, tippt web und drückt Enter. Die Tabelle zeigt nun nur noch passende Pods. Drückt Esc, um den Filter zu löschen.

  4. Sortieren. Nutzt in einer Tabelle die im Header angezeigten Shortcut-Tasten (z. B. nach Name, CPU oder Alter sortieren). Spalten-Sortierung hilft, schnell die ausgelastetsten oder ältesten Pods zu erkennen.

Aufgabe: Beantwortet nur mit k9s: Wie viele web-Pods laufen, und welche Status haben sie?


Teil 2: Eine Ressource inspizieren

Navigiert zu :pods und markiert einen der web-Pods mit den Pfeiltasten.

  1. Drückt d, um ihn zu describen. Ihr bekommt dieselben Details wie bei kubectl describe, inklusive der Events ganz unten. Drückt Esc zum Zurückgehen.
  2. Drückt y, um das vollständige YAML der Ressource zu sehen. Drückt Esc zum Zurückgehen.
  3. Drill-down. Geht zu :deploy, markiert web und drückt Enter. k9s springt direkt zu den Pods des Deployments (es überspringt das ReplicaSet). Drückt Enter auf einem Pod, um zu seinen Containern zu gelangen. Mit Esc klettert ihr jede Ebene wieder nach oben.

    Wollt ihr die ReplicaSet-Ebene sehen? Drückt z auf dem Deployment statt Enter.

Aufgabe: Ausgehend vom web-Deployment, drillt bis ganz hinunter zum nginx-Container. Wie viele Enter-Drücke waren nötig (Deployment → ? → Container)?


Teil 3: Logs und Shell

Geht zu :pods und markiert einen web-Pod.

  1. Logs. Drückt l, um die Container-Logs live zu streamen (wie kubectl logs -f). Ein frisches nginx hat vorerst nur Startup-Zeilen. Echten Traffic erzeugt ihr in Teil 4. Drückt Esc, um den Log-View zu verlassen.

    Nützliche Log-View-Tasten (im Header angezeigt): Wrap umschalten, Timestamps umschalten und an den Anfang/das Ende springen.

  2. Shell. Bei einem markierten web-Pod drückt s, um eine Shell innerhalb des Containers zu öffnen (wie kubectl exec -it ... -- /bin/sh). Probiert ein paar Linux-Befehle:

ls -l /usr/share/nginx/html
printenv
cat /etc/nginx/conf.d/default.conf

Diese laufen innerhalb des Linux-Containers, verhalten sich also gleich, egal welches OS auf eurem Laptop läuft. Tippt exit, um zu k9s zurückzukehren.

Aufgabe: Wie heißt die HTML-Datei, die nginx standardmäßig ausliefert (schaut in /usr/share/nginx/html)?


Teil 4: Port-Forward und Skalieren

4.1 Port-Forward

Erreichen wir die web-App von eurem Laptop aus und beobachten, wie die Access-Logs aufleuchten.

  1. Geht zu :svc, markiert den web-Service und drückt Shift-F. Ein Dialog mit den Forward-Details öffnet sich. Setzt den lokalen Port auf 8080 (lasst den Service-/Container-Port auf 80) und bestätigt. k9s forwardet nun localhost:8080 zum Service.

    Aktive Forwards könnt ihr jederzeit mit :pf Enter einsehen.

  2. Fragt die App aus eurer Shell an (ein zweites Terminal, k9s bleibt laufen):

curl http://localhost:8080

Windows (PowerShell): curl ist ein Alias für Invoke-WebRequest. Für eine einfache Anfrage funktioniert es, aber um konsistent zu macOS/Linux zu bleiben, nutzt curl.exe:

curl.exe http://localhost:8080

Ihr solltet das nginx-Willkommens-HTML bekommen. Führt es ein paar Mal aus.

  1. Öffnet zurück in k9s erneut die Logs (l) eines web-Pods. Nun seht ihr eure GET /-Requests live im Access-Log auftauchen.

4.2 Skalieren

  1. Geht zu :deploy und markiert web.
  2. Drückt s (Scale). Setzt im Dialog die Replicas auf 4 und bestätigt.
  3. Wechselt zu :pods und beobachtet in Echtzeit, wie zwei neue web-Pods erscheinen und Running werden.
  4. Skaliert auf demselben Weg wieder auf 2 herunter.

Aufgabe: Wie verändert sich die Pod-Tabelle in dem Moment, in dem ihr die Hochskalierung bestätigt?


Teil 5: Den kaputten Workload troubleshooten

Das broken-Deployment ist nie hochgekommen. Diagnostizieren und reparieren wir es vollständig aus k9s heraus.

  1. Geht zu :pods. Der broken-...-Pod ist nicht Running. Er zeigt etwas wie ImagePullBackOff oder ErrImagePull (k9s färbt ihn rot).

  2. Lest die Events. Markiert den broken-Pod und drückt d (describe). Scrollt ganz nach unten zu den Events. Ihr seht eine Meldung wie "Failed to pull image ... not found". Der Image-Tag existiert nicht.

  3. Prüft die Logs. Drückt l. Es gibt keine Container-Logs, weil der Container nie gestartet ist. Genau dieses Fehlen ist der Hinweis: Wenn es keine Logs gibt, der Pod aber ungesund ist, schaut auf die Events und das Image, nicht auf die App.

Diagnose: setup.yaml verwendet das Image nginx:1.29.4-doesnotexist, das kein echter Tag ist. Die Reparatur besteht darin, das Deployment auf ein echtes Image zu verweisen: nginx:1.29.4.

  1. Repariert es, der k9s-Weg (e). Geht zu :deploy, markiert broken und drückt e zum Editieren. k9s öffnet die Ressource in eurem Editor. Ändert den Image-Tag auf nginx:1.29.4, speichert und schließt den Editor.

k9s nutzt den Editor aus der Umgebungsvariable K9S_EDITOR (oder EDITOR). Setzt sie, bevor ihr k9s startet:

# Windows (PowerShell)
$env:K9S_EDITOR = "notepad"
# macOS / Linux
export K9S_EDITOR=nano
  1. Repariert es, der zuverlässige Fallback. Falls das Editieren in k9s umständlich ist (kein Editor konfiguriert, oder ihr nutzt lieber die Kommandozeile), führt das in eurer Shell aus. Es funktioniert in Bash und PowerShell identisch:
kubectl set image deployment/broken nginx=nginx:1.29.4
  1. Beobachtet die Erholung. Beide Reparaturen lösen ein neues Rollout aus. Geht in k9s zu :pods und schaut zu: Ein frischer broken-...-Pod wird erzeugt, zieht das echte Image und wird grün (Running). Bestätigt mit d, dass die Events nun einen erfolgreichen Pull und Start zeigen.

Aufgabe: Wie viele broken-Pods sind nach der Reparatur Running, und was zeigt die Pod-Status-Spalte?


Teil 6: Aufräumen

  1. Aus k9s heraus löschen. Geht zu :deploy, markiert broken und drückt Ctrl-D. Bestätigt den Lösch-Dialog. Das Deployment (und sein Pod) verschwindet aus der Tabelle. So löscht ihr in k9s jede Ressource.

  2. Alles Übrige entfernen. Beendet k9s (:q) und führt aus:

kubectl delete -f setup.yaml

broken ist bereits weg, daher seht ihr dafür eventuell einen "not found"-Hinweis. Das ist erwartet und harmlos.


Zusammenfassung: wichtige k9s-Bindings

Taste Aktion
: dann <ressource> Zu einem Ressourcen-Typ springen (:pods, :deploy, :svc, :ns)
? Hilfe / alle Key-Bindings für den aktuellen View
/ Aktuelle Tabelle filtern
0 Alle Namespaces umschalten
Enter In die markierte Ressource drillen (Deployment → Pods, ReplicaSet übersprungen)
z Die ReplicaSets des markierten Deployments anzeigen
Esc Zurückgehen / Filter löschen
d Describe (mit Events)
y Vollständiges YAML anzeigen
l Logs streamen
s Shell in einen Pod / Deployment skalieren (kontextabhängig)
Shift-F Port-Forward
e In $K9S_EDITOR editieren
Ctrl-D Die markierte Ressource löschen
:q Enter / Ctrl-C k9s beenden

Weiterführende Ressourcen