Lebendigkeitsprüfungen in Kubernetes können gefährlich sein

Notiz. übersetzen: Der leitende Ingenieur von Zalando, Henning Jacobs, hat wiederholt Probleme bei Kubernetes-Benutzern festgestellt, wenn es darum geht, den Zweck von Liveness- (und Bereitschafts-)Probes und deren korrekte Verwendung zu verstehen. Deshalb hat er seine Gedanken in dieser umfangreichen Notiz zusammengefasst, die schließlich Teil der K8s-Dokumentation werden wird.

Lebendigkeitsprüfungen in Kubernetes können gefährlich sein

Gesundheitschecks, in Kubernetes bekannt als Lebendigkeitssonden (d. h. wörtlich „Lebensfähigkeitstests“ – ungefähre Übersetzung), kann ziemlich gefährlich sein. Ich empfehle, sie nach Möglichkeit zu vermeiden: Ausnahmen gibt es nur, wenn sie wirklich notwendig sind und Sie sich der Besonderheiten und Folgen ihrer Verwendung voll bewusst sind. In dieser Veröffentlichung geht es um Lebendigkeits- und Bereitschaftsprüfungen und Sie erfahren auch, in welchen Fällen ist und Sie sollten sie nicht verwenden.

Mein Kollege Sandor teilte kürzlich auf Twitter die häufigsten Fehler mit, auf die er stößt, darunter auch solche im Zusammenhang mit der Verwendung von Bereitschafts-/Liveness-Probes:

Lebendigkeitsprüfungen in Kubernetes können gefährlich sein

Falsch konfiguriert livenessProbe kann Situationen mit hoher Auslastung verschlimmern (Schneelast-Abschaltung + möglicherweise lange Container-/Anwendungsstartzeit) und zu anderen negativen Folgen wie Abhängigkeitsverlusten führen (siehe auch mein aktueller Artikel zur Begrenzung der Anzahl der Anfragen in der K3s+ACME-Kombination). Noch schlimmer ist es, wenn die Lebendigkeitsprüfung mit einem Gesundheitscheck kombiniert wird, bei dem es sich um eine externe Datenbank handelt: Ein einzelner DB-Fehler führt dazu, dass alle Ihre Container neu gestartet werden!

Allgemeine Nachricht „Verwenden Sie keine Lebendigkeitssonden“ In diesem Fall hilft es nicht viel, also schauen wir uns an, wozu die Bereitschafts- und Lebendigkeitsprüfungen dienen.

Hinweis: Der größte Teil des folgenden Tests war ursprünglich in der internen Entwicklerdokumentation von Zalando enthalten.

Bereitschafts- und Lebendigkeitsprüfungen

Kubernetes bietet zwei wichtige Mechanismen namens Liveness-Probes und Readiness-Probes. Sie führen regelmäßig eine Aktion durch – etwa das Senden einer HTTP-Anfrage, das Öffnen einer TCP-Verbindung oder das Ausführen eines Befehls im Container – um zu bestätigen, dass die Anwendung wie erwartet funktioniert.

Kubernetes verwendet Bereitschaftssondenum zu verstehen, wann der Container bereit ist, Datenverkehr anzunehmen. Ein Pod gilt als gebrauchsfertig, wenn alle seine Behälter bereit sind. Eine Verwendung dieses Mechanismus besteht darin, zu steuern, welche Pods als Backends für Kubernetes-Dienste (und insbesondere Ingress) verwendet werden.

Lebendigkeitssonden Helfen Sie Kubernetes zu verstehen, wann es Zeit ist, den Container neu zu starten. Mit einer solchen Prüfung können Sie beispielsweise einen Deadlock abfangen, wenn eine Anwendung an einer Stelle hängen bleibt. Ein Neustart des Containers in diesem Zustand hilft dabei, die Anwendung trotz Fehlern zum Laufen zu bringen, kann aber auch zu kaskadierenden Fehlern führen (siehe unten).

Wenn Sie versuchen, ein Anwendungsupdate bereitzustellen, das die Liveness-/Bereitschaftsprüfungen nicht besteht, wird sein Rollout verzögert, da Kubernetes auf den Status wartet Ready aus allen Hülsen.

Beispiel

Hier ist ein Beispiel für eine Bereitschaftsprüfung, die einen Pfad überprüft /health über HTTP mit Standardeinstellungen (Intervall: 10 Sekunden, Timeout: 1 Sekunde, Erfolgsschwelle: 1, Fehlerschwelle: 3):

# часть общего описания deployment'а/стека
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080

Empfehlungen

  1. Für Microservices mit HTTP-Endpunkt (REST usw.) Definieren Sie immer eine Bereitschaftssonde, der prüft, ob die Anwendung (Pod) bereit ist, Datenverkehr anzunehmen.
  2. Stellen Sie sicher, dass die Bereitschaftssonde vorhanden ist deckt die Verfügbarkeit des tatsächlichen Webserver-Ports ab:
    • Verwendung von Ports für administrative Zwecke, genannt „admin“ oder „management“ (z. B. 9090), z readinessProbeStellen Sie sicher, dass der Endpunkt nur dann „OK“ zurückgibt, wenn der primäre HTTP-Port (z. B. 8080) bereit ist, Datenverkehr zu akzeptieren*;

      *Mir ist mindestens ein Fall bei Zalando bekannt, bei dem dies nicht geschehen ist, nämlich readinessProbe Ich habe den „Management“-Port überprüft, aber der Server selbst funktionierte aufgrund von Problemen beim Laden des Caches nicht.

    • Das Anschließen einer Bereitschaftsprüfung an einen separaten Port kann dazu führen, dass die Überlastung des Hauptports nicht in der Gesundheitsprüfung berücksichtigt wird (d. h. der Thread-Pool auf dem Server ist voll, aber die Gesundheitsprüfung zeigt immer noch, dass alles in Ordnung ist ).
  3. Stelle sicher das Der Bereitschaftstest ermöglicht die Initialisierung/Migration der Datenbank;
    • Der einfachste Weg, dies zu erreichen, besteht darin, den HTTP-Server erst zu kontaktieren, nachdem die Initialisierung abgeschlossen ist (z. B. die Migration einer Datenbank von Flyway usw.); Das heißt, anstatt den Zustandsprüfungsstatus zu ändern, starten Sie den Webserver einfach erst, wenn die Datenbankmigration abgeschlossen ist*.

      * Sie können Datenbankmigrationen auch von Init-Containern außerhalb des Pods ausführen. Ich bin immer noch ein Fan von eigenständigen Anwendungen, also solchen, bei denen der Anwendungscontainer weiß, wie er die Datenbank ohne externe Koordination in den gewünschten Zustand bringt.

  4. Verwenden httpGet für Bereitschaftsprüfungen durch typische Integritätsprüfungsendpunkte (z. B. /health).
  5. Machen Sie sich mit den Standardprüfparametern vertraut (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3):
    • Die Standardoptionen bedeuten, dass der Pod wird nicht bereit nach etwa 30 Sekunden (3 fehlgeschlagene Plausibilitätsprüfungen).
  6. Verwenden Sie einen separaten Port für „admin“ oder „management“, wenn der Technologie-Stack (z. B. Java/Spring) dies zulässt, um die Integritäts- und Metrikverwaltung vom regulären Datenverkehr zu trennen:
    • aber vergessen Sie nicht Punkt 2.
  7. Bei Bedarf kann der Bereitschaftstest zum Aufwärmen/Laden des Caches verwendet werden und einen 503-Statuscode zurückgeben, bis der Container aufgewärmt ist:
    • Ich empfehle Ihnen außerdem, den neuen Scheck zu lesen startupProbe, erschien in Version 1.16 (Wir haben darüber auf Russisch geschrieben hier - ca. übersetzt).

Vorbehalte

  1. Verlassen Sie sich nicht auf externe Abhängigkeiten (z. B. Data Warehouses) beim Ausführen von Bereitschafts-/Liveness-Tests – dies kann zu kaskadierenden Fehlern führen:
    • Nehmen wir als Beispiel einen zustandsbehafteten REST-Dienst mit 10 Pods, die von einer Postgres-Datenbank abhängig sind: Wenn die Prüfung von einer funktionierenden Verbindung zur Datenbank abhängt, können alle 10 Pods fehlschlagen, wenn es auf der Netzwerk-/Datenbankseite zu einer Verzögerung kommt – normalerweise alles endet schlimmer als es könnte;
    • Bitte beachten Sie, dass Spring Data standardmäßig die Datenbankverbindung überprüft*;

      * Dies ist das Standardverhalten von Spring Data Redis (zumindest war es das letzte Mal, als ich es überprüft habe), was zu einem „katastrophalen“ Fehler führte: Als Redis für kurze Zeit nicht verfügbar war, „stürzten alle Pods ab“.

    • „extern“ kann in diesem Sinne auch andere Pods derselben Anwendung bedeuten, d. h. idealerweise sollte die Prüfung nicht vom Zustand anderer Pods desselben Clusters abhängen, um kaskadierende Abstürze zu verhindern:
      • Die Ergebnisse können für Anwendungen mit verteiltem Status variieren (z. B. In-Memory-Caching in Pods).
  2. Verwenden Sie keine Lebendigkeitssonde für Pods (Ausnahmen sind Fälle, in denen sie wirklich notwendig sind und Sie sich der Besonderheiten und Folgen ihrer Verwendung voll bewusst sind):
    • Eine Liveness-Prüfung kann dabei helfen, hängende Container wiederherzustellen. Da Sie aber die volle Kontrolle über Ihre Anwendung haben, sollten Dinge wie hängende Prozesse und Deadlocks im Idealfall nicht passieren: Die beste Alternative besteht darin, die Anwendung absichtlich zum Absturz zu bringen und sie in den vorherigen stabilen Zustand zurückzubringen.
    • Eine fehlgeschlagene Liveness-Prüfung führt dazu, dass der Container neu gestartet wird, was möglicherweise die Auswirkungen von Fehlern im Zusammenhang mit dem Booten verschlimmert: Ein Neustart des Containers führt zu Ausfallzeiten (zumindest für die Dauer des Anwendungsstarts, sagen wir 30+ Sekunden), was zu neuen Fehlern führt. Erhöhung der Belastung anderer Container und Erhöhung der Wahrscheinlichkeit ihres Ausfalls usw.;
    • Lebendigkeitsprüfungen in Kombination mit einer externen Abhängigkeit sind die schlechtestmögliche Kombination und drohen kaskadierende Ausfälle: Eine leichte Verzögerung auf der Datenbankseite führt zu einem Neustart aller Ihrer Container!
  3. Parameter der Lebendigkeits- und Bereitschaftsprüfungen muss anders sein:
    • Sie können eine Lebendigkeitssonde mit derselben Gesundheitsprüfung, aber einem höheren Antwortschwellenwert verwenden (failureThreshold) beispielsweise den Status zuweisen nicht bereit nach 3 Versuchen und gehen davon aus, dass die Lebendigkeitsprüfung nach 10 Versuchen fehlgeschlagen ist;
  4. Verwenden Sie keine Exec-Checks, da sie mit bekannten Problemen verbunden sind, die zum Auftreten von Zombie-Prozessen führen:

Zusammenfassung

  • Verwenden Sie Bereitschaftstests, um festzustellen, wann ein Pod für den Empfang von Datenverkehr bereit ist.
  • Verwenden Sie Liveness-Sonden nur, wenn sie wirklich benötigt werden.
  • Eine unsachgemäße Verwendung von Bereitschafts-/Liveness-Probes kann zu einer verringerten Verfügbarkeit und kaskadierenden Fehlern führen.

Lebendigkeitsprüfungen in Kubernetes können gefährlich sein

Zusätzliche Materialien zum Thema

Update Nr. 1 vom 2019

Über Init-Container für die Datenbankmigration: Fußnote hinzugefügt.

EJ erinnerte mich zu PDB: Eines der Probleme bei Lebendigkeitsprüfungen ist die mangelnde Koordination zwischen Pods. Kubernetes hat Pod-Unterbrechungsbudgets (PDB) Um die Anzahl gleichzeitiger Fehler zu begrenzen, die bei einer Anwendung auftreten können, berücksichtigen die Prüfungen jedoch nicht die PDB. Im Idealfall könnten wir K8s sagen: „Starten Sie einen Pod neu, wenn sein Test fehlschlägt, aber starten Sie nicht alle neu, um eine Verschlechterung zu vermeiden.“

Bryan hat es perfekt ausgedrückt: „Verwenden Sie Lebendigkeitsmessungen, wenn Sie genau wissen, was Am besten beenden Sie die Anwendung„(Lassen Sie sich noch einmal nicht mitreißen).

Lebendigkeitsprüfungen in Kubernetes können gefährlich sein

Update Nr. 2 vom 2019

Bezüglich des Lesens der Dokumentation vor der Verwendung: Ich habe die entsprechende Anfrage erstellt (Featureanfrage), um Dokumentation zu Lebendigkeitsprüfungen hinzuzufügen.

PS vom Übersetzer

Lesen Sie auch auf unserem Blog:

Source: habr.com

Kommentar hinzufügen