Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Lassen Sie uns die Grundlagen des Loggings in Docker und Kubernetes durchgehen und anschließend zwei Werkzeuge betrachten, die sicher im Produktionsumfeld eingesetzt werden können: Grafana Loki und den EFK-Stack (Elasticsearch + Fluent Bit + Kibana).

Das Material des Artikels ist eine Zusammenfassung aus einer offenen Vorlesung der Schule „Slurmr“. Wenn das Interesse besteht und aufgrund der Produktionsanforderungen ist eine vollständige Schulung möglich – melden Sie sich für den Kurs an über Monitoring und Logging von Infrastrukturen in Kubernetes.

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Logging in Docker

Auf der Kubernetes-Ebene werden Anwendungen in Pods gestartet, aber auf der darunterliegenden Ebene arbeiten sie normalerweise in Docker. Daher muss das Logging so konfiguriert werden, dass Logs von den Containern gesammelt werden. Die Container werden von Docker gestartet – daher muss man herausfinden, wie das Logging auf Docker-Ebene funktioniert.

Ich hoffe, dass jeder Leser weiß: Anwendungs-Logs sollten in stdout/stderr geschrieben werden und nicht im Container selbst. Docker Daemon aggregiert die Logs, und er arbeitet nur mit den Logs, die an stdout/stderr gesendet werden. Außerdem kann das Schreiben von Logs im Container problematisch sein: Der Container wächst mit dem wachsenden Log (da es wahrscheinlich keinen Logrotate im Container gibt), und Docker Daemon ist sich dieses Logs nicht bewusst.

Docker hat mehrere Log-Manager oder Plugins zur Sammlung von Container-Logs. In der kostenlosen Version Docker Community Edition (CE) gibt es weniger Log-Manager als in der kommerziellen Docker Enterprise Edition (EE).

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Docker EE habe ich in der Praxis noch nie verwendet: In Southbridge bemühen wir uns um Open-Source-Lösungen, und den Kunden fehlen oft die meisten zusätzlichen Funktionen von Docker EE.

Log-Manager in Docker CE:

local – Speicherung von Logs in internen Dateien des Docker Daemon;
json-file – Erstellung eines json-Logs im Ordner jedes Containers;
journald – Versand von Logs an journald.

Die Logging-Einstellungen in Docker befinden sich in der Datei daemon.json.

Im Feld „log-driver“ geben Sie das Plugin an, und im Feld „log-opts“ – dessen Einstellungen. Im obigen Beispiel wurde das Plugin „json-file“ angegeben, mit einer Log-Größenbegrenzung – „max-size“: „10m“; begrenzte Anzahl von Dateien (Rotationsparameter) – „max-file“: „3“; sowie Werte, die an die Logs angehängt werden.

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Einige Einstellungen des Log-Managers können über die Befehlszeilenanwendung festgelegt werden. Das ist praktisch, wenn ein einzelner Container mit einem anderen Log-Manager gestartet werden muss.

So sieht das Logging-Schema in Docker aus:

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

So funktioniert das Schema: Der Log-Manager, zum Beispiel json-file, erstellt Dateien. Die Log-Sammler (Rsyslog, Fluentd, Logagent und andere) sammeln diese Dateien und übertragen sie zur Speicherung in Elastic, Sematext oder andere Speicher.

Besonderheiten des Loggings in Kubernetes

Vereinfacht sieht das Logging-Schema in Kubernetes so aus: Es gibt einen Pod, in dem ein Container läuft, der Container sendet Logs an stdout/stderr. Anschließend erstellt Docker eine Datei und schreibt die Logs hinein, die dann rotiert werden können.

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Betrachten wir die Besonderheiten des Loggings in Kubernetes.

Logs zwischen Deployments speichern. Dies ist eine Voraussetzung für die korrekte Einrichtung des Loggings. Wenn Logs zwischen Deployments nicht gespeichert werden, gehen die Logs der vorherigen Version bei der Einführung einer neuen Version der Anwendung verloren, ebenso kann ein Containerneustart zum Verlust von Logs führen. Kubernetes hat einen Schalter —previous, mit dem man die Logs der Anwendung vor dem letzten Neustart des Pods einsehen kann, aber nicht tiefer.

Logs von allen Instanzen aggregieren. Wenn Mikrodienste in der Cloud gehostet werden, ist der Cloud-Anbieter für die Systemüberwachung verantwortlich. Wenn Mikrodienste auf eigener Hardware betrieben werden, müssen neben den Logs der Container auch die Systemlogs gesammelt werden.

Früher gab es keine geeigneten Werkzeuge zur Sammlung von Logs sowohl vom System als auch von Mikrodiensten. Üblicherweise sammelte ein Werkzeug die Systemlogs (zum Beispiel Rsyslog), ein anderes die Logs von Docker (zum Beispiel journal-bit mit der Konfiguration des Log-Treibers Docker auf journald). Wir haben versucht, journal-bit zu verwenden - Logs sowohl von Containern (im Log-Treiber Docker angeben, dass die Logs in journald geschrieben werden sollen) als auch vom System (in CentOS 7 gibt es bereits systemd und journald). Die Lösung funktioniert, ist aber nicht ideal. Wenn es viele Logs gibt, beginnt journal-bit zu laggen, und Nachrichten gehen verloren.

Die Experimente setzten sich fort - und es fand sich ein anderer Weg. In CentOS 7 werden die Haupt-Systemlogs (messages, audit, secure) im var-Log in Form von Dateien dupliziert. Auch in Docker kann man das Speichern von Logs in JSON-Dateien einrichten. Entsprechend können diese Dateien aus CentOS 7 und Docker zusammen gesammelt werden.

Mit der Zeit wurde die Lösung ELK Stack populär. Dies ist eine Kombination mehrerer Werkzeuge: Elasticsearch, Logstash und Kibana.

Elasticsearch speichert die Logs von Containern, Logstash sammelt die Logs von Instanzen, Kibana ermöglicht die Verarbeitung der gesammelten Logs und das Erstellen von Grafiken. Eine Zeit lang wurde ELK Stack intensiv genutzt, aber meiner Meinung nach ist seine Zeit vorbei. Später werde ich erklären, warum.

Metadaten hinzufügen. Pods, Anwendungen und Container können überall gestartet werden. Darüber hinaus kann eine Anwendung mehrere Instanzen haben. Die Protokolle werden in einem einheitlichen Format aufgezeichnet, und wir müssen verstehen, welche Kopie es ist, welcher Pod sie schreibt und in welchem Namespace er sich befindet. Genau aus diesem Grund müssen den Protokollen Metadaten hinzugefügt werden.

Protokolle analysieren. Lustig, aber die Kosten für die Unterstützung eines Protokollierungs- und Überwachungssystems können die Ausgaben für die Hauptanwendung übersteigen. Wenn Sie Dutzende und Hunderte von Tausenden von Protokollen pro Sekunde haben, erscheint das logisch, aber man muss trotzdem die Grenze kennen. Eine Möglichkeit, diese Grenze zu finden, ist die Protokollanalyse.

In der Regel ist es nicht notwendig, alle Protokolle zu sammeln und zu speichern; es sollte nur ein Teil zur Speicherung gesendet werden – beispielsweise Protokolle mit dem Status „Warnung“ oder „Fehler“. Wenn es um Protokolle von nginx oder Ingress-Controllern geht, können nur die Protokolle zur Speicherung gesendet werden, deren Status von 200 abweicht. Aber das ist kein universeller Rat: Wenn Sie irgendwie eine Analyse der Nginx-Protokolle erstellen, ist es offensichtlich sinnvoll, sie zu sammeln.

Es wird nicht empfohlen, Protokolle gedankenlos zu filtern, da möglicherweise nicht genügend gefilterte Daten für eine ordentliche Analyse vorhanden sind. Andererseits könnte die Analyse sinnvoller sein, nicht auf Protokollierungsebene, sondern auf Metrikebene durchzuführen. Dann müssen nicht Hunderte von Tausenden von Zeilen mit dem Code 200 gespeichert werden. Ein Ansatz besteht darin, Informationen über den Traffic und Fehler aus den Metriken der Ingress-Controller zu erhalten.

Insgesamt muss man hier gut überlegen, was man speichern möchte und wie lange, denn sonst kann es zu einer Situation kommen, in der das Protokollierungssystem mehr Ressourcen beansprucht als das Hauptprojekt.

Es gibt derzeit keine Standardlösung für die Protokollierung. Im Gegensatz zur Überwachung, wo es eine am weitesten verbreitete Lösung (Prometheus) gibt, gibt es keinen Standard bei der Protokollierung.

In diesem Vortrag werden wir zwei Tools betrachten: eines ist populär, das andere gewinnt an Popularität. Abgesehen davon gibt es noch andere, aber in diesem Artikel werden wir nicht darauf eingehen.

Unter Berücksichtigung aller oben genannten Merkmale kann die Protokollierung in Kubernetes nun so dargestellt werden:

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Es bleibt das Containerprotokoll, die Rotation, aber es gibt einen Sammler-Agenten, der die Protokolle erfasst und zur Speicherung sendet (in der Abbildung – in das Logging Backend). Der Agent läuft auf jedem Knoten und wird in der Regel in Kubernetes gestartet.

Jetzt betrachten wir die Werkzeuge für das Logging.

— unserem neuen Log-Aggregationssystem — das sichergestellt hat, dass alle Ingester sich während und nach dem Ausfall ordnungsgemäß verhalten haben.

— unserem neuen Log-Aggregationssystem — das sichergestellt hat, dass alle Ingester sich während und nach dem Ausfall ordnungsgemäß verhalten haben. ist kürzlich erschienen, hat sich aber bereits recht bekannt gemacht. Seine Vorteile: leicht zu installieren, verbraucht wenig Ressourcen, erfordert keine Elasticsearch-Installation, da er Daten in einer TSDB (time series database) speichert. In dem früheren Artikel habe ich erwähnt, dass Prometheus Daten in einer solchen Datenbank speichert, und das ist eine der zahlreichen Ähnlichkeiten zwischen beiden Produkten. Die Entwickler behaupten sogar, dass Loki "Prometheus für die Logging-Welt" ist.

Eine kleine Abweichung zur TSDB für diejenigen, die noch nicht gelesen haben. den vorherigen Artikel: TSDB bewältigt hervorragend die Aufgabe, große Datenmengen und Zeitreihen zu speichern, ist jedoch nicht für die langfristige Speicherung gedacht. Wenn Sie aus irgendeinem Grund Logs länger als zwei Wochen aufbewahren müssen, ist es besser, deren Übertragung in eine andere Datenbank einzurichten.

Ein weiterer Vorteil von Loki ist, dass Grafana zur Visualisierung der Daten verwendet wird. Sehr praktisch: In Grafana sehen wir die Überwachungsdaten und können dort auch, verbunden mit Loki, die Logs ansehen. Aus den Logs können Grafiken erstellt werden.

Die Architektur von Loki sieht ungefähr so aus:

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Mit Hilfe von DaemonSet wird auf allen Servern des Clusters ein Agent - Promtail oder Fluent Bit - bereitgestellt. Der Agent sammelt die Logs. Loki holt sie ab und speichert sie in seiner TSDB. Den Logs werden sofort Metadaten hinzugefügt, was praktisch ist: man kann nach Pods, Namespaces, Container-Namen und sogar Labels filtern.

Installationsanleitung für Loki

Loki funktioniert in der vertrauten Oberfläche von Grafana. Loki hat sogar eine eigene Abfragesprache, die LogQL heißt - benannt nach und im Syntax ähnlich zu PromQL in Prometheus. In der Loki-Oberfläche gibt es Vorschläge für Abfragen, sodass man sie nicht auswendig wissen muss.

Dokumentation zur Sprache LogQL

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet
Loki in der Grafana-Oberfläche

Mit Hilfe von Filtern kann man in Loki Codes finden ("400", "404" und jeden anderen); die Logs von der gesamten Node einsehen; alle Logs filtern, die das Wort "error" enthalten. Wenn man auf das Log klickt, wird eine Karte mit allen Informationen zum Ereignis angezeigt.

In Loki gibt es genügend Werkzeuge, die es ermöglichen, die gewünschten Logs zu extrahieren, obwohl es technisch gesehen ehrlich gesagt auch mehr sein könnten. Momentan entwickelt sich Loki aktiv und gewinnt an Popularität.

Elastic + Fluent Bit + Kibana (EFK-Stack)

Der EFK-Stack ist ein klassisches, nicht weniger beliebtes Logging-Tool.

Zu Beginn des Artikels wurde ELK (Elasticsearch + Logstash + Kibana) erwähnt, jedoch ist dieser Stack aufgrund von Logstash, das nicht sehr leistungsfähig und gleichzeitig ressourcenintensiv ist, veraltet. An seiner Stelle wird jetzt der leichtere und leistungsfähigere Fluentd verwendet, und nach einer gewissen Zeit kam ihm zur Hilfe Fluent Bit — ein noch leichterer und noch leistungsfähigerer Log-Collector.

Wenn man den Entwicklern Glauben schenken darf, dann ist Fluent Bit mehr als 100 Mal besser in der Leistung als Fluentd: „wo Fluentd 20 MB RAM verbraucht, wird Fluent Bit 150 KB verbrauchen“ — ein wörtliches Zitat aus der Dokumentation. In Anbetracht dessen wird Fluent Bit häufiger verwendet.

Fluent Bit hat weniger Funktionen als Fluentd, deckt jedoch die grundlegenden Anforderungen ab, weshalb wir hauptsächlich Fluent Bit nutzen.

Das Schema der EFK-Architektur: Der Agent sammelt Logs von allen Pods (in der Regel handelt es sich um ein DaemonSet, das auf allen Servern des Clusters läuft) und sendet sie an den Speicher (Elasticsearch, PostgreSQL oder Kafka). Kibana verbindet sich mit dem Speicher und ruft alle erforderlichen Informationen ab.

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Kibana stellt die Informationen in einer benutzerfreundlichen Weboberfläche dar. Es gibt Grafiken, Filter und vieles mehr.

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Anhand der Logs können ganze Dashboards erstellt werden.

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Die Möglichkeiten von Fluent Bit

Da über Fluent Bit in der Regel weniger bekannt ist als über Logstash, betrachten wir ihn etwas genauer. Fluent Bit lässt sich logisch in 6 Module unterteilen, auf einige Module können Plugins aufgesetzt werden, die die Funktionen von Fluent Bit erweitern.

Protokollierung in Kubernetes: Wie man Protokolle sammelt, speichert, analysiert und verarbeitet

Input-Modul sammelt Logs aus Dateien, systemd-Diensten und sogar aus TCP-Sockets (man muss nur den Endpoint angeben, und Fluent Bit beginnt, dort zu holen). Diese Möglichkeiten sind ausreichend, um Logs sowohl vom System als auch von Containern zu sammeln.

In der Produktion verwenden wir am häufigsten die Plugins tail (man kann es auf einen Ordner mit Logs richten) und systemd (man kann ihm sagen, aus welchen Diensten Logs gesammelt werden sollen).

Parser-Modul formatiert die Logs einheitlich. Standardmäßig sind Nginx-Logs eine Zeichenkette. Mit Hilfe eines Plugins kann diese Zeichenkette in JSON umgewandelt werden: Felder und deren Werte können definiert werden. Mit JSON lässt sich viel einfacher arbeiten als mit stringbasierten Logs, da es flexiblere Möglichkeiten zur Sortierung bietet.

Filter-Modul. Auf dieser Ebene werden unnötige Logs herausgefiltert. Zum Beispiel werden nur Logs mit dem Wert „warning“ oder bestimmten Labels zum Speichern gesendet. Die ausgewählten Logs gelangen in einen Puffer.

Buffer-Modul. Fluent Bit hat zwei Arten von Buffern: einen Speicher- und einen Festplattenspeicher. Ein Buffer ist ein vorübergehender Speicher für Logs, der im Falle von Fehlern oder Ausfällen benötigt wird. Jeder möchte RAM sparen, daher wählt man in der Regel den Festplattenspeicher. Es ist jedoch zu beachten, dass Logs vor dem Speichern auf der Festplatte zunächst im Speicher abgelegt werden.

Modul Routing/Output enthält Regeln und Adressen zum Versenden von Logs. Wie bereits erwähnt, können Logs an Elasticsearch, PostgreSQL oder beispielsweise Kafka gesendet werden.

Interessant ist, dass Logs von Fluent Bit auch an Fluentd gesendet werden können. Da das erste leichter und weniger funktional ist, kann man Logs darüber sammeln und an Fluentd senden, wo sie dann mit zusätzlichen Plugins weiterverarbeitet und in Speicher abgelegt werden.

Wenn Sie vorhaben, Elasticsearch zu verwenden…

Zuletzt zwei Tipps für diejenigen, die Elasticsearch als Log-Speicher in der Produktion verwenden möchten.

  1. Richten Sie Benachrichtigungen mit Hilfe von ElastAlertein. Dieses Programm extrahiert wichtige Nachrichten aus dem allgemeinen Log-Stream und erstellt Alarme für E-Mail oder andere Kanäle. Allerdings gab es vor nicht allzu langer Zeit eine traurige Nachricht, dass das Projekt möglicherweise bald eingestellt wird..
  2. Rotieren Sie Logs mit Hilfe der Anwendung Curator oder durch die API von Elasticsearch. Elastic unternimmt derzeit erhebliche Schritte zur Verwaltung des Lebenszyklus von Indizes ohne Verwendung dritter Werkzeuge. Es macht insgesamt wenig Sinn, Logs lange zu speichern: es ist eher unwahrscheinlich, dass ein Log nach zwei Wochen benötigt wird – wenn es wirklich kritisch ist, wird es innerhalb von zwei Wochen in jedem Fall bearbeitet. Im äußersten Fall können alte Logs archiviert und an einen Ort für die Langzeitaufbewahrung gesendet werden. Ich habe von speziellen Logs gehört, die gesetzlich bis zu 5 Jahre aufbewahrt werden müssen. Damit habe ich persönlich keine Erfahrung, aber ich würde solche Informationen nicht mit normalen Logs gleichsetzen und sie möglicherweise sogar getrennt aufbewahren.

Fortsetzung folgt…

Autor: Marsel Ibraev, zertifizierter Kubernetes-Administrator, praktizierender Ingenieur bei der Firma Southbridge, Redner und Entwickler von Kursen Slurm.

Quelle: habr.com

60GB SSD 8Gb DDR4