TL; DR
- Um eine hohe Beobachtbarkeit von Containern und Microservices zu erreichen, reichen Protokolle und primäre Metriken nicht aus.
- Für eine schnellere Wiederherstellung und erhöhte Ausfallsicherheit sollten Anwendungen das High Observability Principle (HOP) anwenden.
- Auf Anwendungsebene erfordert NOP: ordnungsgemäße Protokollierung, genaue Überwachung, Integritätsprüfungen und Leistungs-/Übergangsverfolgung.
- Verwenden Sie Schecks als Element von NOR Bereitschaftsprobe и Lebendigkeit Probe Kubernetes.
Was ist eine Gesundheitscheck-Vorlage?
Beim Entwerfen einer geschäftskritischen und hochverfügbaren Anwendung ist es sehr wichtig, über einen Aspekt wie Fehlertoleranz nachzudenken. Eine Anwendung gilt als fehlertolerant, wenn sie sich nach einem Ausfall schnell erholt. Eine typische Cloud-Anwendung verwendet eine Microservices-Architektur, bei der jede Komponente in einem separaten Container platziert wird. Und um sicherzustellen, dass die Anwendung auf k8s beim Entwerfen eines Clusters hochverfügbar ist, müssen Sie bestimmten Mustern folgen. Darunter befindet sich auch die Health-Check-Vorlage. Es definiert, wie die Anwendung k8s mitteilt, dass sie fehlerfrei ist. Dabei handelt es sich nicht nur um Informationen darüber, ob der Pod läuft, sondern auch darüber, wie er Anfragen empfängt und darauf reagiert. Je mehr Kubernetes über den Zustand des Pods weiß, desto intelligentere Entscheidungen trifft es über die Weiterleitung des Datenverkehrs und den Lastausgleich. Somit ermöglicht das Prinzip der hohen Beobachtbarkeit der Anwendung, zeitnah auf Anfragen zu reagieren.
High-Observability-Prinzip (HOP)
Das Prinzip der hohen Beobachtbarkeit ist eines davon
Eine gut gestaltete Cloud-Anwendung protokolliert ihre wichtigsten Ereignisse mithilfe der Standard-E/A-Streams STDERR und STDOUT. Als nächstes kommt ein Hilfsdienst, zum Beispiel Filebeat, Logstash oder Fluentd, der Protokolle an ein zentrales Überwachungssystem (zum Beispiel Prometheus) und ein Protokollsammelsystem (ELK-Software-Suite) liefert. Das folgende Diagramm zeigt, wie eine Cloud-Anwendung gemäß dem Health Test Pattern und dem High Observability Principle funktioniert.
Wie wende ich das Health Check Pattern in Kubernetes an?
Standardmäßig überwacht k8s den Status der Pods mithilfe eines der Controller (
In unserem Beispiel ist dies bei k8s der Fall Funktionsprüfung. Bei dieser Art der Überprüfung überprüft das Kubelet kontinuierlich den Status des Prozesses im Container. Sobald er versteht, dass der Prozess gestoppt wurde, wird er ihn neu starten. Wenn der Fehler durch einen einfachen Neustart der Anwendung behoben werden kann und das Programm so konzipiert ist, dass es bei jedem Fehler herunterfährt, ist eine Prozessgesundheitsprüfung alles, was Sie brauchen, um dem NOP und dem Gesundheitstestmuster zu folgen. Schade nur, dass nicht alle Fehler durch einen Neustart behoben werden. In diesem Fall bietet k8s zwei tiefergehende Möglichkeiten, Probleme mit dem Pod zu identifizieren:
LivenessProbe
Es ist Zeit Lebendigkeit Probe Kubelet führt drei Arten von Prüfungen durch: Es stellt nicht nur fest, ob der Pod ausgeführt wird, sondern auch, ob er bereit ist, Anfragen zu empfangen und angemessen darauf zu reagieren:
- Richten Sie eine HTTP-Anfrage an den Pod ein. Die Antwort muss einen HTTP-Antwortcode im Bereich von 200 bis 399 enthalten. Die Codes 5xx und 4xx signalisieren also, dass der Pod Probleme hat, obwohl der Prozess läuft.
- Um Pods mit Nicht-HTTP-Diensten (z. B. dem Postfix-Mailserver) zu testen, müssen Sie eine TCP-Verbindung herstellen.
- Einen beliebigen Befehl für einen Pod ausführen (intern). Die Prüfung gilt als erfolgreich, wenn der Befehlsabschlusscode 0 ist.
Ein Beispiel dafür, wie das funktioniert. Die nächste Pod-Definition enthält eine NodeJS-Anwendung, die bei HTTP-Anfragen einen Fehler 500 auslöst. Um sicherzustellen, dass der Container neu gestartet wird, wenn ein solcher Fehler empfangen wird, verwenden wir den Parameter livenessProbe:
apiVersion: v1
kind: Pod
metadata:
name: node500
spec:
containers:
- image: magalix/node500
name: node500
ports:
- containerPort: 3000
protocol: TCP
livenessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 5
Dies unterscheidet sich nicht von jeder anderen Pod-Definition, wir fügen jedoch ein Objekt hinzu .spec.containers.livenessProbe
. Parameter httpGet
akzeptiert den Pfad, an den die HTTP-GET-Anfrage gesendet wird (in unserem Beispiel ist dies /
, aber in Kampfszenarien kann es so etwas geben /api/v1/status
). Eine andere livenessProbe akzeptiert einen Parameter initialDelaySeconds
, der den Verifizierungsvorgang anweist, eine bestimmte Anzahl von Sekunden zu warten. Die Verzögerung ist erforderlich, da der Container Zeit zum Starten benötigt und nach einem Neustart für einige Zeit nicht verfügbar ist.
Um diese Einstellung auf einen Cluster anzuwenden, verwenden Sie:
kubectl apply -f pod.yaml
Nach einigen Sekunden können Sie den Inhalt des Pods mit dem folgenden Befehl überprüfen:
kubectl describe pods node500
Am Ende der Ausgabe finden Sie
Wie Sie sehen können, hat livenessProbe eine HTTP-GET-Anfrage initiiert, der Container hat einen Fehler 500 generiert (wofür er programmiert war) und das Kubelet hat ihn neu gestartet.
Wenn Sie sich fragen, wie die NideJS-Anwendung programmiert wurde, finden Sie hier die verwendeten app.js- und Docker-Dateien:
app.js.
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(500, { "Content-type": "text/plain" });
res.end("We have run into an errorn");
});
server.listen(3000, function() {
console.log('Server is running at 3000')
})
Dockerfile
FROM node
COPY app.js /
EXPOSE 3000
ENTRYPOINT [ "node","/app.js" ]
Es ist wichtig zu beachten: livenessProbe startet den Container nur dann neu, wenn er fehlschlägt. Wenn ein Neustart den Fehler, der die Ausführung des Containers verhindert, nicht behebt, kann das Kubelet keine Maßnahmen zur Behebung des Problems ergreifen.
Bereitschaftsprobe
readinessProbe funktioniert ähnlich wie livenessProbes (GET-Anfragen, TCP-Kommunikation und Befehlsausführung), mit Ausnahme von Fehlerbehebungsaktionen. Der Container, in dem der Fehler erkannt wird, wird nicht neu gestartet, sondern vom eingehenden Datenverkehr isoliert. Stellen Sie sich vor, dass einer der Container viele Berechnungen durchführt oder stark ausgelastet ist, wodurch sich die Antwortzeiten verlängern. Im Fall von livenessProbe wird die Antwortverfügbarkeitsprüfung ausgelöst (über den Prüfparameter timeoutSeconds), woraufhin das Kubelet den Container neu startet. Beim Start beginnt der Container mit der Ausführung ressourcenintensiver Aufgaben und wird erneut gestartet. Dies kann für Anwendungen, die Reaktionsgeschwindigkeit erfordern, von entscheidender Bedeutung sein. Wenn beispielsweise ein Auto unterwegs auf eine Antwort vom Server wartet, verzögert sich die Antwort – und das Auto gerät in einen Unfall.
Schreiben wir eine redinessProbe-Definition, die die Antwortzeit der GET-Anfrage auf nicht mehr als zwei Sekunden festlegt und die Anwendung nach 5 Sekunden auf die GET-Anfrage antwortet. Die pod.yaml-Datei sollte so aussehen:
apiVersion: v1
kind: Pod
metadata:
name: nodedelayed
spec:
containers:
- image: afakharany/node_delayed
name: nodedelayed
ports:
- containerPort: 3000
protocol: TCP
readinessProbe:
httpGet:
path: /
port: 3000
timeoutSeconds: 2
Lassen Sie uns einen Pod mit kubectl bereitstellen:
kubectl apply -f pod.yaml
Warten wir ein paar Sekunden und sehen uns dann an, wie die readinessProbe funktioniert:
kubectl describe pods nodedelayed
Am Ende der Ausgabe können Sie sehen, dass einige der Ereignisse ähnlich sind
Wie Sie sehen, hat kubectl den Pod nicht neu gestartet, als die Prüfzeit 2 Sekunden überschritt. Stattdessen stornierte er die Anfrage. Eingehende Kommunikation wird an andere, funktionierende Pods umgeleitet.
Beachten Sie, dass kubectl nach dem Auslagern des Pods erneut Anfragen an ihn weiterleitet: Antworten auf GET-Anfragen werden nicht mehr verzögert.
Zum Vergleich finden Sie unten die geänderte Datei app.js:
var http = require('http');
var server = http.createServer(function(req, res) {
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
sleep(5000).then(() => {
res.writeHead(200, { "Content-type": "text/plain" });
res.end("Hellon");
})
});
server.listen(3000, function() {
console.log('Server is running at 3000')
})
TL; DR
Vor dem Aufkommen von Cloud-Anwendungen waren Protokolle das wichtigste Mittel zur Überwachung und Überprüfung des Anwendungszustands. Es bestand jedoch keine Möglichkeit, Korrekturmaßnahmen zu ergreifen. Protokolle sind auch heute noch nützlich; sie müssen gesammelt und an ein Protokollerfassungssystem gesendet werden, um Notfallsituationen zu analysieren und Entscheidungen zu treffen. [All dies ließe sich ohne Cloud-Anwendungen beispielsweise mit Monit bewerkstelligen, aber mit k8s wurde es viel einfacher :) – Anmerkung der Redaktion. ]
Korrekturen müssen heute nahezu in Echtzeit vorgenommen werden, sodass Anwendungen keine Blackbox mehr sein müssen. Nein, sie sollten Endpunkte anzeigen, die es Überwachungssystemen ermöglichen, wertvolle Daten über den Status von Prozessen abzufragen und zu sammeln, damit sie bei Bedarf sofort reagieren können. Dies wird als Performance Test Design Pattern bezeichnet und folgt dem High Observability Principle (HOP).
Kubernetes bietet standardmäßig zwei Arten von Gesundheitsprüfungen: readinessProbe und livenessProbe. Beide verwenden die gleichen Prüfarten (HTTP-GET-Anfragen, TCP-Kommunikation und Befehlsausführung). Sie unterscheiden sich darin, welche Entscheidungen sie als Reaktion auf Probleme in den Gruppen treffen. livenessProbe startet den Container neu in der Hoffnung, dass der Fehler nicht erneut auftritt, und readinessProbe isoliert den Pod vom eingehenden Datenverkehr, bis die Ursache des Problems behoben ist.
Ein ordnungsgemäßes Anwendungsdesign sollte beide Arten der Überprüfung umfassen und sicherstellen, dass genügend Daten erfasst werden, insbesondere wenn eine Ausnahme ausgelöst wird. Es sollte auch die notwendigen API-Endpunkte anzeigen, die das Überwachungssystem (Prometheus) mit wichtigen Gesundheitsmetriken versorgen.
Source: habr.com