Kubernetes NetworkPolicies Troubleshooting

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

Dieser Artikel behandelt zwei Themen, die den Kurs abschließen: Netzwerk-Segmentierung mit NetworkPolicies und ein systematisches Vorgehen beim Debuggen kaputter Pods.

Netzwerk-Segmentierung mit NetworkPolicies

Ausgangslage ohne Policy
  • Standardmäßig darf in Kubernetes jeder Pod mit jedem anderen Pod im Cluster kommunizieren – unabhängig von Namespace oder Anwendung. Das entspricht in etwa einem einzigen, komplett offenen Netz.
Die Analogie zu nftables
  • Eine NetworkPolicy funktioniert im Prinzip wie eine Firewall-Regel, nur auf Pod-Ebene statt auf Interface- oder IP-Ebene. Statt Quell-IPs und Ports zu filtern, werden Pods über ihre Labels ausgewählt – das grundsätzliche Prinzip "erlaubt ist nur, was explizit erlaubt wird" ist identisch zu dem, was aus nftables-Regelwerken bekannt ist.
Voraussetzung
  • NetworkPolicies werden nicht von Kubernetes selbst durchgesetzt, sondern vom eingesetzten Netzwerk-Plugin (CNI). Das bei k3s standardmäßig verwendete Flannel unterstützt sie nicht. Für diese Übung wird deshalb ein Policy-fähiges CNI wie Calico benötigt, oder die Policy wird nur zur Veranschaulichung des YAML-Aufbaus besprochen, ohne die Durchsetzung praktisch zu erzwingen. Welcher Weg gewählt wird, hängt vom vorbereiteten Kurs-Image ab.

Beispiel: nur web darf zu db

Ziel: Ausschließlich Pods mit dem Label app: web dürfen Verbindungen zum db-Pod aufbauen. Jeder andere Zugriff wird verweigert.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-allow-web-only
spec:
  podSelector:
    matchLabels:
      app: db
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: web
      ports:
        - protocol: TCP
          port: 5432
Wichtig zum Verständnis
  • Sobald für einen Pod irgendeine NetworkPolicy mit Ingress existiert, gilt ab diesem Moment für diesen Pod: alles ist verboten außer dem, was explizit erlaubt wurde. Vorher galt "alles erlaubt", danach "alles verboten außer den Ausnahmen" – ein Umdenken, das viele Einsteiger überrascht.
Anwenden
  • kubectl apply -f db-networkpolicy.yaml
Wirkung testen
  • Von einem Pod ohne das Label app: web aus (zum Beispiel einem frisch gestarteten Test-Pod) sollte die Verbindung zu db:5432 nun fehlschlagen, während sie vom web-Pod aus weiterhin funktioniert.

Systematisches Troubleshooting

Bei Problemen mit einem Pod hilft ein festes Vorgehen, statt wahllos Befehle auszuprobieren.

Schritt 1
Überblick verschaffen
  • kubectl get pods -o wide
  • Zeigt Status, Neustarts und den Node, auf dem der Pod läuft.
Schritt 2
Details und Ereignisse ansehen
  • kubectl describe pod <pod-name>
  • Der Abschnitt Events am Ende der Ausgabe verrät in den meisten Fällen sofort die Ursache – falsches Image, fehlende Ressourcen, fehlgeschlagene Probe.
Schritt 3
Logs des aktuellen Containers prüfen
  • kubectl logs <pod-name>
Schritt 4
Bei Neustart-Schleifen die Logs des vorherigen Versuchs prüfen
  • Nach einem Absturz sind die aktuellen Logs oft leer oder nutzlos, weil der Container gerade erst wieder gestartet ist.
  • kubectl logs <pod-name> --previous
Schritt 5
Cluster-weite Ereignisse prüfen
  • Hilfreich, wenn ein Pod gar nicht erst startet (zum Beispiel wegen fehlender Ressourcen im Cluster).
  • kubectl get events --sort-by='.lastTimestamp'
Schritt 6
Bei Bedarf direkt in den Container
  • kubectl exec -it <pod-name> -- /bin/sh

Typische Fehlerbilder

Status Typische Ursache Erster Debugging-Schritt
ImagePullBackOff Image-Name falsch geschrieben oder Tag existiert nicht kubectl describe pod, Abschnitt Events
CrashLoopBackOff Anwendung stürzt beim Start ab kubectl logs --previous
Pending Zu wenig Ressourcen im Cluster oder kein passender Node kubectl describe pod, Abschnitt Events
Running, aber nicht erreichbar Falscher Service-Selector oder fehlende Readiness kubectl get endpoints, Labels prüfen

Übung: NetworkPolicy verifizieren

  1. Wendet die oben gezeigte Policy an.
  2. Startet einen Test-Pod ohne das Label app: web: kubectl run test --rm -it --image=curlimages/curl -- sh
  3. Versucht von dort aus, db:5432 zu erreichen, und bestätigt, dass die Verbindung blockiert wird.
  4. Wechselt in den web-Pod und bestätigt, dass die Verbindung zu db:5432 von dort weiterhin funktioniert.

Übung: Geführtes Troubleshooting

In dieser Übung wird absichtlich ein Fehler eingebaut, den es systematisch mit den oben gezeigten Schritten zu finden gilt, ohne die Lösung vorher zu kennen.

  1. Wendet ein Deployment mit einem absichtlich falschen Image-Namen an.
  2. Findet mit dem beschriebenen Vorgehen (nicht durch Raten) die genaue Fehlerursache.
  3. Korrigiert den Fehler und bestätigt, dass der Pod danach normal läuft.
  4. Wiederholt die Übung mit einem zweiten, unangekündigten Fehler (zum Beispiel einer fehlerhaften Readiness Probe, die auf einen falschen Port zeigt) und wendet dasselbe Vorgehen erneut an.

Übung: Alles zusammenführen

Als Abschluss wird die komplette Anwendung aus den vorherigen Artikeln noch einmal von Grund auf neu aufgesetzt, diesmal ohne Anleitung Schritt für Schritt, nur anhand der eigenen Notizen:

  1. Erstellt alle benötigten Objekte (ConfigMap, Secret, PVC, beide Deployments, beide Services, Ingress, NetworkPolicy) in einer sinnvollen Reihenfolge.
  2. Prüft den vollständigen Zustand mit kubectl get all und kubectl get pvc,ingress,networkpolicy.
  3. Führt ein Rolling Update durch und bestätigt es mit kubectl rollout status.
  4. Simuliert einen Ausfall (Pod löschen) und beobachtet die Selbstheilung.
  5. Räumt zum Abschluss den gesamten Namespace auf: kubectl delete all --all