Dennis Hemeier
Dennis Hemeier
August 7, 2022

101 Series: Kubernetes Probes

101 Series
Wie überwacht Kubernetes mithilfe der LivenessProbe, ReadinessProbe und StartupProbe meine Applikation und warum sollte man diese konfigurieren? Erfahrt in dieser 101-Series alles über das Thema Kubernetes Probes.
Kubernetes Probes

Warum werden Probes benötigt?

Innerhalb eines Kubernetes Clusters hat man typischerweise viele Applikationen gleichzeitig laufen. Alle diese Anwendungen sind meist über HTTP(S)-Traffic von außerhalb des Clusters erreichbar oder verbinden sich untereinander. Als Beispiel für internen Traffic sei an dieser Stelle die Kommunikation zwischen einem Backend und einer Datenbank genannt.

Bei all diesen Applikationen ist es wichtig, dass diese immer korrekt funktionieren. Sollte es einen Fehler geben, so sollte diese Applikation automatisiert neu gestartet werden.

Auch gibt es Anwendungsfälle, bei denen eine Applikation zwar schon läuft, aber noch nicht bereit ist, externen Traffic zu empfangen. Stellt euch hier z. B. eine Datenbank vor, die gerade intern ein Update durchführt. Während dieser Zeit läuft zwar unser Datenbankserver, aber jede Anfrage an diesen würde zu einem Fehler führen.

Für all diese Anwendungsfälle gibt es innerhalb von Kubernetes sogenannte Probes.

Was sind Probes?

Grundlegend handelt es sich bei Probes um eine regelmäßige Überprüfung der entsprechenden Applikation, um zu entscheiden, ob diese korrekt funktioniert oder nicht.

Beispielsweise kann ich damit meine Applikation alle 10 Sekunden überwachen lassen. Sobald dabei ein Fehler festgestellt wird, wird die Applikation neu gestartet.

Innerhalb von Kubernetes unterscheiden wir zwischen drei verschiedenen Probes:

LivenessProbe - Läuft der Container?

Diese Probe überwacht, ob eine Applikation gerade korrekt läuft. Sollte hierbei ein Fehler erkannt werden, so wird die Applikation neu gestartet.

ReadinessProbe - Kann der Container Requests empfangen?

Diese Probe sagt aus, ob eine Applikation auch tatsächlich verwendet werden kann. Nur weil der entsprechende Container läuft, heißt das ja nicht gleichzeitig, dass auch Request empfangen werden dürfen. Ein klassisches Beispiel hierfür haben wir bereits in der Einleitung dieses Beitrages erwähnt: Eine Datenbank läuft, macht intern ein Update und kann daher noch nicht (von außen betrachtet) verwendet werden.

StartupProbe - Sonderfall

Diese Probe wird ausschließlich beim Startvorgang eines Containers aktiv und ersetzt in dieser Zeit die Liveness- und ReadinessProbe. Sie ist nicht immer notwendig und wird in der Regel bei Legacy Applikationen verwendet, bei denen die anderen Probes nicht ausreichend wären.

Als Beispiel sei hier eine Applikation genannt, die unterschiedlich lange Startzeiten aufweist. In diesem Fall könnten wir die initialDelaySeconds nicht verwenden, da wir dort eine vergleichbar hohe Zeit eintragen müssten. Mit der Verwendung der StartupProbe können wir in solch einem Fall alternativ dafür sorgen, dass die Applikation sehr schnell online gehen kann.

Die Einstellung dafür sollte dann wie folgt gesetzt werden:
periodSeconds * failureThreshold > Maximal zu erwartende Startzeit der Applikation.

Wie werden Probes konfiguriert?

Egal, welche Probes ihr in euren Containern verwenden wollt, die Einstellungen sind bei allen Probes exakt identisch. Schauen wir uns zunächst einmal eine beispielhafte Readiness Probe an:

apiVersion: v1
kind: Pod
metadata:
  name: probe-example
spec:
  containers:
  - name: probe-example
    image: nginx
    # Readiness Probe configuration
    readinessProbe:
      # probe type
      httpGet:
        path: /
        port: 80
        scheme: HTTP
      # wait X seconds before first check
      initialDelaySeconds: 0
      # check every X seconds
      periodSeconds: 5
      # mark as failed after X failed checks
      failureThreshold: 3
      # mark as success after X checks
      successThreshold: 1
      # timeout for the probe requests
      timeoutSeconds: 1

Die erste Einstellung, die wir für unsere Probes setzen müssen, ist der ProbeType. Hierbei haben wir drei Optionen:

HTTP Probes (httpGet)

Dieser Typ einer Probe wird mit Abstand am häufigsten eingesetzt. Hierbei führt Kubernetes einen HTTP-Request an die Applikation aus. Der entsprechende Response wird bei HTTP-Status Code >= 200 und < 400 als erfolgreich gewertet.

httpGet:
  path: /
  port: 80
  scheme: HTTP

TCP Probes (tcpSocket)

Applikationen, die keinen Webtraffic unterstützen, können alternativ mit der TCP Socket Action überwacht werden. Hierbei wird ein TCP-Check gegen den angegebenen Port durchgeführt. Achtung: Dieser Typ sollte nicht bei Webapplikationen verwendet werden. Hierbei könnte es z. B. passieren, dass der Port 80 zwar offen ist, jeder Request an den Webserver aber mit einem HTTP-Status 500 antwortet. In diesem Fall würde unsere Probe keinen Fehler feststellen, da der Port ja offen ist.

tcpSocket:
  port: 80

Command Probes (exec)

Bei diesem Typ wird ein Command (z. B. ein Bash-Script) innerhalb des Containers ausgeführt. Kubernetes wertet diesen als erfolgreich aus, wenn der Exit-Code des Commands 0 ist. Jeder andere Code wird als Fehler gewertet. Diese Probes ist besonders dann sinnvoll, wenn die zu überprüfende Applikation keinen Port geöffnet hat.

exec:
  command: /healthcheck.sh

Alle weiteren Einstellungen sind Optional und können bei Bedarf angepasst werden:

  • initialDelaySeconds (Standard 0) Mit dieser Einstellung kann die Zeit definiert werden, die Kubernetes nach dem Starten des Containers wartet, bis der erste Probe Durchlauf startet. Diese Einstellung ist besonders dann sinnvoll, wenn die Applikation z. B. immer 30 Sekunden zum Starten benötigt.

  • periodSeconds (Standard 10) In welchem Intervall soll die Probe ausgeführt werden.

  • failureThreshold (Standard 3) Wie oft darf die Probe fehlschlagen, bis der gesamte Durchlauf als Fehlschlag gewertet werden.

  • successThreshold (Standard 1) Wie oft muss diese Probe erfolgreich durchlaufen, bis der gesamte Durchlauf als Erfolg gewertet wird

  • timeoutSeconds (Standard 1) Definiert den Timeout für einen einzelnen Probe Request

Auslesen des Status einer Probe

Um den aktuellen Status der Probes einzusehen, gibt es verschiedene Wege. Für die ReadinessProbe finden wir den Status direkt bei der Auflistung unserer Pods. In diesem Beispiel sehen wir drei Pods, wobei ein Pod aktuell noch nicht Ready ist:

$ kubectl get po -n probes
NAME                             READY   STATUS    RESTARTS   AGE
probe-example-6485dcb89d-gj8j2   1/1     Running   0          28s
probe-example-6485dcb89d-kgqlc   1/1     Running   0          28s
probe-example-6485dcb89d-kr8pz   0/1     Running   0          28s

Eine weitere Möglichkeit, den Status der Probes auszulesen, haben wir, indem wir einen Describe auf den gewünschten Pod ausführen. Dabei sehen wir zum einen die aktuelle Konfiguration der Probes, zum anderen – im Fehlerfall – entsprechende Nachrichten in den Events:

$ kubectl describe po -n probes 
Name:         probe-example-6485dcb89d-gj8j2
Namespace:    probes
[ . . . ]
Liveness:     http-get http://:80/healthz delay=0s timeout=1s period=5s #success=1 #failure=1
Readiness:    http-get http://:80/readiness delay=0s timeout=1s period=5s #success=1 #failure=1
[ . . . ]
Events:
  Type     Reason     Age              From               Message
  ----     ------     ----             ----               -------
  Warning  Unhealthy  1s (x5 over 8s)  kubelet            Readiness probe failed: HTTP probe failed with statuscode: 404

Im Falle der LivenessProbe wird unser Pod entsprechend neu gestartet. Dieses ist auch hier wieder über das Auflisten der Pods (RESTARTS > 0) sowie über die Events sichtbar:

$ kubectl get po -n probes
NAME                             READY   STATUS             RESTARTS     AGE
probe-example-7bc764c4fb-c2g8h   0/1     CrashLoopBackOff   3 (8s ago)   23s
$ kubectl describe po -n probes probe-example-7bc764c4fb-c2g8h
Name:         probe-example-7bc764c4fb-c2g8h
Namespace:    probes
[ . . . ]
Events:
  Type     Reason           Age                  From               Message
  ----     ------           ----                 ----               -------
  Warning  Unhealthy        2m44s (x3 over 2m54s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing          2m49s (x2 over 2m54s)  kubelet            Container nginx failed liveness probe, will be restarted

Container Probes - Best Practices

Das Wichtigste bei der Verwendung von Probes ist eine optimale Konfiguration der Applikation. Dazu hat sich ein Standard etabliert, der verwendet werden sollte. Typischerweise verwendet man für die LivenessProbe und die ReadinessProbe eigens implementierte httpGet Funktionen in der Applikation.

LivenessProbe: /livez

ReadinessProbe: /readyz

Zusätzlich sollten die Einstellungen der Probes auf failureThreshold: 1 geändert sein, sodass Kubernetes unsere Applikation direkt nach dem ersten erkannten Fehler neu startet.

Die Einstellung der initialDelaySeconds sowie die startupProbe sollten, wenn möglich, nicht verwendet werden.

Habt ihr noch Fragen oder Feedback zum Thema Probes? Weitere Informationen findet ihr in unserer Kubernetes Einführungsschulung! Ansonsten wendet euch gerne an uns und schreibt uns eine kurze Nachricht oder nutzt den Chat auf unserer Website. Wir freuen uns auf eure Nachrichten.