Liveness- und Readiness-Probes konfigurieren

KubernetesBeginner
Jetzt üben

Einführung

Logs, Events, Exec-Befehle und Port-Forwarding helfen Ihnen bei der Untersuchung einer Anwendung. Probes ermöglichen es Kubernetes, die Anwendung kontinuierlich zu überwachen. Eine Readiness-Probe beantwortet die Frage: „Sollte dieser Pod Datenverkehr empfangen?“ Eine Liveness-Probe beantwortet die Frage: „Sollte dieser Container neu gestartet werden?“

In diesem Lab konfigurieren Sie Readiness- und Liveness-Probes separat. Zuerst erstellen Sie eine Anwendung, die erst dann als „Ready“ (bereit) gilt, wenn sie einen /ready-Endpunkt erstellt hat. Anschließend erstellen Sie eine weitere Anwendung mit einer Liveness-Probe, löschen deren Gesundheitsdatei mittels kubectl exec und beobachten, wie Kubernetes den Container neu startet.

Einen Namespace für Probe-Übungen vorbereiten

In diesem Schritt bereiten Sie einen sauberen Namespace für die Übungen mit Probes vor.

Beginnen Sie im Verzeichnis /home/labex/project. Sie werden die Manifeste für die Probes in diesem Verzeichnis 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 Cluster-Networking-Pod bereit ist. Probes und Services hängen von einem funktionierenden Pod-Netzwerk ab.

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-probes und legen Sie diesen als aktuellen Namespace fest:

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

Bestätigen Sie den aktuellen Namespace:

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

Erwartete Ausgabe:

ckad-prep-probes

Eine Readiness-Probe konfigurieren

In diesem Schritt konfigurieren Sie eine Readiness-Probe und beobachten, dass der Service nur bereite Pods verwendet.

Der Container startet sofort einen HTTP-Server, erstellt jedoch erst einige Sekunden später die Datei /www/ready. Die Readiness-Probe prüft GET /ready auf Port 8080. Bis dieser Pfad existiert, kann der Pod zwar den Status „Running“ haben, ist aber nicht „Ready“, und der Service sollte keinen Datenverkehr an ihn senden.

Erstellen Sie readiness-web.yaml:

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

Wenden Sie das Manifest an und betrachten Sie die Pods kurz nach der Erstellung:

kubectl apply -f readiness-web.yaml
sleep 3
kubectl get pods -l app=readiness-web

Die erwartete Ausgabe zeigt möglicherweise Pods, die zwar „Running“, aber noch nicht „Ready“ sind:

NAME                             READY   STATUS    RESTARTS   AGE
readiness-web-...                0/1     Running   0          ...

Warten Sie, bis das Deployment verfügbar ist:

kubectl rollout status deployment/readiness-web --timeout=120s

Erwartete Ausgabe:

deployment "readiness-web" successfully rolled out

Untersuchen Sie die Service-Endpunkte über EndpointSlice. Nachdem die Readiness-Probe erfolgreich war, sollte der Service zwei bereite Endpunkte haben.

kubectl get endpointslice -l kubernetes.io/service-name=readiness-web

Die erwartete Ausgabe enthält:

NAME                ADDRESSTYPE   PORTS   ENDPOINTS
readiness-web-...   IPv4          8080    ... + 1 more...

Erstellen Sie einen Client-Pod und testen Sie den Service:

kubectl run probe-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/probe-client --timeout=120s
kubectl exec probe-client -- wget -qO- http://readiness-web

Erwartete Ausgabe:

readiness-ok

Eine Liveness-Probe konfigurieren

In diesem Schritt konfigurieren Sie eine Liveness-Probe, die eine Gesundheitsdatei überprüft.

Eine Liveness-Probe entscheidet, ob Kubernetes einen Container neu starten soll. Dieses Beispiel verwendet eine exec-Probe, die test -f /tmp/healthy innerhalb des Containers ausführt. Der Container erstellt diese Datei beim Start, sodass er anfangs als gesund gilt.

Erstellen Sie liveness-web.yaml:

cat > liveness-web.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: liveness-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: liveness-web
  template:
    metadata:
      labels:
        app: liveness-web
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: web
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - |
          touch /tmp/healthy
          mkdir -p /www
          echo liveness-ok > /www/index.html
          httpd -f -p 8080 -h /www
        ports:
        - containerPort: 8080
        livenessProbe:
          exec:
            command:
            - test
            - -f
            - /tmp/healthy
          initialDelaySeconds: 3
          periodSeconds: 3
          failureThreshold: 1
EOF

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

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

Die erwartete Ausgabe enthält:

deployment.apps/liveness-web created
deployment "liveness-web" successfully rolled out

Speichern Sie den Pod-Namen und bestätigen Sie, dass die Gesundheitsdatei existiert:

LIVE_POD="$(kubectl get pods -l app=liveness-web -o jsonpath='{.items[0].metadata.name}')"
echo "$LIVE_POD"
kubectl exec "$LIVE_POD" -- test -f /tmp/healthy
echo "health file exists"

Die erwartete Ausgabe enthält den Pod-Namen und:

health file exists

Beschreiben Sie den Pod und suchen Sie nach der Konfiguration der Liveness-Probe:

kubectl describe pod "$LIVE_POD" | grep -A3 'Liveness:'

Die erwartete Ausgabe enthält:

Liveness:  exec [test -f /tmp/healthy] delay=3s timeout=1s period=3s

Einen Liveness-Neustart auslösen

In diesem Schritt entfernen Sie die Gesundheitsdatei und beobachten, wie die Liveness-Probe den Container neu startet.

Das Pod-Objekt bleibt gleich, während der darin enthaltene Container neu startet. Deshalb beobachten wir den Neustart-Zähler (Restart Count), anstatt einen neuen Pod-Namen zu erwarten.

Speichern Sie den aktuellen Pod-Namen:

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

Entfernen Sie die Gesundheitsdatei aus dem Container:

kubectl exec "$LIVE_POD" -- rm /tmp/healthy

Beobachten Sie den Neustart-Zähler, bis er größer als Null ist. Die Liveness-Probe läuft alle drei Sekunden, daher kann dies einen kurzen Moment dauern.

for i in $(seq 1 20); do
  RESTARTS="$(kubectl get pod "$LIVE_POD" -o jsonpath='{.status.containerStatuses[0].restartCount}')"
  echo "restart-count=$RESTARTS"
  if [ "$RESTARTS" != "0" ]; then
    break
  fi
  sleep 3
done

Die erwartete Ausgabe enthält schließlich:

restart-count=1

Nachdem der Container neu gestartet wurde, erstellt der Startbefehl die Datei /tmp/healthy erneut. Bestätigen Sie, dass die Datei wieder vorhanden ist:

kubectl exec "$LIVE_POD" -- test -f /tmp/healthy
echo "health file recreated"

Erwartete Ausgabe:

health file recreated

Lesen Sie die Pod-Events und suchen Sie nach dem Fehler der Liveness-Probe:

kubectl describe pod "$LIVE_POD" | sed -n '/Events:/,$p'

Die erwartete Ausgabe enthält:

Warning  Unhealthy  ...  Liveness probe failed
Normal   Killing    ...  Container web failed liveness probe

Zusammenfassung

Sie haben beide wichtigen Anwendungs-Probes konfiguriert. Die Readiness-Probe steuerte, wann Pods den Service-Endpunkten beitraten, während die Liveness-Probe einen Container neu startete, nachdem dessen Gesundheitsdatei entfernt wurde. Sie haben außerdem EndpointSlices, Pod-Beschreibungen, Neustart-Zähler und Events untersucht, um die Probe-Konfiguration mit dem sichtbaren Verhalten von Kubernetes zu verknüpfen.