Debugging mit exec und Port Forwarding

KubernetesBeginner
Jetzt üben

Einführung

Im vorherigen Lab haben wir uns auf Logs und Events konzentriert. Diese dienen als erste Anhaltspunkte, doch manchmal ist es notwendig, einen laufenden Container direkt zu untersuchen oder einen Service vorübergehend vom eigenen Terminal aus zu erreichen. Kubernetes bietet hierfür zwei gängige Werkzeuge: kubectl exec und kubectl port-forward.

In diesem Lab stellen Sie eine kleine Webanwendung bereit, verwenden kubectl exec, um Dateien und Prozesse innerhalb eines Pods zu prüfen, und nutzen kubectl port-forward, um eine temporäre lokale Verbindung zum Service herzustellen. Der Arbeitsablauf ist bewusst einfach gehalten, damit Sie sich auf die Debugging-Techniken konzentrieren können, anstatt sich mit der Komplexität der Anwendung auseinanderzusetzen.

Einen Namespace für das Debugging vorbereiten

In diesem Schritt bereiten Sie einen sauberen Namespace für die Übungen mit exec und Port-Forwarding vor.

Beginnen Sie im Verzeichnis /home/labex/project. Hier werden Sie das Manifest der Anwendung speichern.

mkdir -p /home/labex/project
cd /home/labex/project

Überprüfen Sie, ob der Kubernetes API-Server erreichbar ist. Falls die VM gerade erst gestartet wurde und der Node noch nicht bereit ist, warten Sie einige Sekunden und führen Sie den Befehl erneut aus.

kubectl get nodes --request-timeout=5s

Die erwartete Ausgabe sieht in etwa so aus:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

Warten Sie, bis der Pod für das Cluster-Netzwerk den Status "Ready" erreicht hat. Port-Forwarding nutzt die Verbindung zum API-Server, aber die Anwendung benötigt dennoch einen funktionsfähigen Pod und Service.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

Erwartete Ausgabe:

pod/calico-node-... condition met

Erstellen Sie einen Namespace namens ckad-prep-debug und legen Sie diesen als aktuellen Namespace fest:

kubectl create namespace ckad-prep-debug
kubectl config set-context --current --namespace=ckad-prep-debug

Bestätigen Sie den aktuellen Namespace:

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

Erwartete Ausgabe:

ckad-prep-debug

Eine kleine Webanwendung bereitstellen

In diesem Schritt stellen Sie eine einfache Anwendung bereit, die Sie anschließend untersuchen und auf die Sie zugreifen werden.

Der Pod schreibt eine index.html-Datei und startet BusyBox httpd auf Port 8080. Ein Service namens debug-web macht die Pods innerhalb des Clusters auf Port 80 verfügbar. Der Service ist Teil der Übung, da kubectl port-forward sowohl auf einen Service als auch auf einen Pod zielen kann.

Erstellen Sie die Datei debug-web.yaml:

cat > debug-web.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: debug-web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: debug-web
  template:
    metadata:
      labels:
        app: debug-web
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: web
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - |
          mkdir -p /www
          echo "debug-web-ready" > /www/index.html
          httpd -f -p 8080 -h /www
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 1
          periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
  name: debug-web
spec:
  selector:
    app: debug-web
  ports:
  - port: 80
    targetPort: 8080
EOF

Wenden Sie das Manifest an und warten Sie auf das Deployment:

kubectl apply -f debug-web.yaml
kubectl rollout status deployment/debug-web --timeout=120s

Die erwartete Ausgabe enthält:

deployment.apps/debug-web created
service/debug-web created
deployment "debug-web" successfully rolled out

Überprüfen Sie die Pods und den Service:

kubectl get pods -l app=debug-web
kubectl get service debug-web

Die erwartete Ausgabe zeigt zwei laufende Pods und einen ClusterIP-Service:

debug-web-...   1/1   Running
debug-web       ClusterIP

Einen laufenden Container mit exec untersuchen

In diesem Schritt verwenden Sie kubectl exec, um Befehle innerhalb eines Anwendungs-Pods auszuführen.

kubectl exec ist nützlich, wenn der Pod zwar läuft, Sie aber prüfen müssen, was der Container "sieht". Es ist kein Ersatz für Logs und sollte nicht dazu verwendet werden, während des normalen Betriebs manuelle Änderungen vorzunehmen. In einem Debugging-Workflow hilft es Ihnen, Dateien, Prozesse, Umgebungsvariablen und das lokale Netzwerkverhalten aus der Sicht des Containers zu verifizieren.

Speichern Sie den Namen eines Pods in einer Shell-Variablen:

POD_NAME="$(kubectl get pods -l app=debug-web -o jsonpath='{.items[0].metadata.name}')"
echo "$POD_NAME"

Die erwartete Ausgabe ist ein Pod-Name:

debug-web-...

Führen Sie hostname innerhalb des Containers aus. Die Ausgabe sollte dem Pod-Namen entsprechen, da Kubernetes den Hostnamen des Containers auf Basis des Pod-Namens setzt.

kubectl exec "$POD_NAME" -- hostname

Erwartete Ausgabe:

debug-web-...

Listen Sie die laufenden Prozesse innerhalb des Containers auf:

kubectl exec "$POD_NAME" -- ps

Die erwartete Ausgabe enthält den httpd-Prozess:

PID   USER     TIME  COMMAND
...   root     ...   httpd -f -p 8080 -h /www

Lesen Sie die Datei, die vom Webserver bereitgestellt wird:

kubectl exec "$POD_NAME" -- cat /www/index.html

Erwartete Ausgabe:

debug-web-ready

Testen Sie abschließend den Webserver von innerhalb desselben Containers:

kubectl exec "$POD_NAME" -- wget -qO- http://127.0.0.1:8080

Erwartete Ausgabe:

debug-web-ready

Den Service mit Port Forwarding testen

In diesem Schritt verwenden Sie kubectl port-forward, um vom Terminal aus auf den Service zuzugreifen.

Port-Forwarding erstellt einen temporären Tunnel von einem lokalen Port zu einem Pod oder Service im Cluster. Dies ist für schnelles Debugging nützlich, da keine Änderung des Service-Typs, kein Ingress und keine Öffnung für externen Zugriff erforderlich ist. Ein im Vordergrund laufender kubectl port-forward-Befehl bleibt aktiv, bis Sie ihn beenden. Daher starten wir ihn in diesem Lab im Hintergrund, testen ihn und beenden ihn anschließend wieder.

Starten Sie ein Port-Forwarding vom lokalen Port 18080 zum Service-Port 80. Die Ausgabe wird in /tmp/debug-web-port-forward.log geschrieben, damit das Terminal weiterhin nutzbar bleibt.

kubectl port-forward service/debug-web 18080:80 > /tmp/debug-web-port-forward.log 2>&1 &
PF_PID=$!
sleep 3
cat /tmp/debug-web-port-forward.log

Die erwartete Ausgabe enthält:

Forwarding from 127.0.0.1:18080 -> 8080

Senden Sie eine Anfrage über den lokalen weitergeleiteten Port:

wget -qO- http://127.0.0.1:18080

Erwartete Ausgabe:

debug-web-ready

Beenden Sie den Hintergrundprozess des Port-Forwardings. Diese Bereinigung ist wichtig, da der lokale Port sonst belegt bliebe.

kill "$PF_PID"
wait "$PF_PID" 2>/dev/null || true

Bestätigen Sie, dass das Port-Forwarding-Log eine verarbeitete Verbindung aufgezeichnet hat:

cat /tmp/debug-web-port-forward.log

Die erwartete Ausgabe enthält:

Handling connection for 18080

Zusammenfassung

Sie haben zwei praktische Debugging-Werkzeuge kennengelernt. Sie haben kubectl exec verwendet, um den Hostnamen, die Prozesse, Dateien und die lokale HTTP-Antwort eines laufenden Containers zu untersuchen. Zudem haben Sie kubectl port-forward genutzt, um eine temporäre lokale Verbindung zu einem ClusterIP-Service herzustellen, diese vom Terminal aus getestet und den Hintergrundprozess sauber beendet.