Wir sammeln Protokolle mit Loki

Wir sammeln Protokolle mit Loki

Wir bei Badoo überwachen ständig neue Technologien und bewerten, ob es sinnvoll ist, diese in unser System zu integrieren. Eine solche Studie möchten wir mit der Community teilen. Sie ist Loki gewidmet – einem System zur Aggregation von Logs.

Loki ist eine Lösung zur Speicherung und Anzeige von Logs, außerdem bietet dieser Stack ein flexibles System zur Analyse und zum Senden von Daten an Prometheus. Im Mai wurde ein weiteres Update veröffentlicht, das aktiv von den Entwicklern beworben wird. Uns interessierte, was Loki kann, welche Möglichkeiten es bietet und inwieweit es als Alternative zu ELK – dem Stack, den wir derzeit verwenden – dienen kann.

Was ist Loki

Grafana Loki ist ein Set von Komponenten für ein vollwertiges System zur Arbeit mit Logs. Im Gegensatz zu anderen ähnlichen Systemen basiert Loki auf der Idee, nur die Metadaten der Logs – Labels (wie auch in Prometheus) – zu indexieren und die eigentlichen Logs in separaten Chunks komprimiert zu speichern.

Startseite, GitHub

Bevor ich zur Beschreibung dessen komme, was man mit Loki tun kann, möchte ich erläutern, was mit "der Idee, nur die Metadaten zu indexieren" gemeint ist. Lassen Sie uns den Ansatz von Loki mit dem Ansatz der Indexierung in traditionellen Lösungen wie Elasticsearch am Beispiel einer Zeile aus einem nginx-Log vergleichen:

172.19.0.4 - - [01/Jun/2020:12:05:03 +0000] "GET /purchase?user_id=75146478&item_id=34234 HTTP/1.1" 500 8102 "-" "Stub_Bot/3.0" "0.001"

Traditionelle Systeme parsen die gesamte Zeile, einschließlich der Felder mit einer Vielzahl von einzigartigen Werten wie user_id und item_id, und speichern alles in großen Indizes. Der Vorteil dieses Ansatzes besteht darin, dass komplexe Abfragen schnell ausgeführt werden können, da fast alle Daten im Index enthalten sind. Dies hat jedoch den Nachteil, dass der Index groß wird, was zu einem erhöhten Speicherbedarf führt. Letztendlich ist der Volltext-Index der Logs in seiner Größe mit den Logs selbst vergleichbar. Damit man schnell danach suchen kann, muss der Index im Speicher geladen werden. Und je mehr Logs vorhanden sind, desto schneller wächst der Index und desto mehr Speicher benötigt er.

Der Ansatz von Loki erfordert, dass aus der Zeichenfolge nur die erforderlichen Daten extrahiert werden, deren Anzahl gering ist. So erhalten wir einen kleinen Index und können die Daten suchen, indem wir sie nach Zeit und nach indizierten Feldern filtern und dann die verbleibenden Daten mithilfe von regulären Ausdrücken oder Teilstring-Suchvorgängen scannen. Der Prozess scheint nicht der schnellste zu sein, aber Loki teilt die Anfrage in mehrere Teile auf und führt diese parallel aus, wobei er eine große Menge an Daten in kurzer Zeit verarbeitet. Die Anzahl der Shards und der parallelen Anfragen in diesen wird konfiguriert; somit hängt die Menge an Daten, die in einer Zeiteinheit verarbeitet werden kann, linear von der Anzahl der zur Verfügung gestellten Ressourcen ab.

Dieser Kompromiss zwischen großem, schnellem Index und kleinem Index mit parallelem vollständigem Durchlauf ermöglicht es Loki, die Systemkosten zu kontrollieren. Es kann flexibel an die Bedürfnisse angepasst und erweitert werden.

Der Loki-Stack besteht aus drei Komponenten: Promtail, Loki, Grafana. Promtail sammelt Protokolle, verarbeitet sie und sendet sie an Loki. Loki speichert sie. Grafana kann Daten aus Loki abfragen und diese anzeigen. Im Allgemeinen kann Loki nicht nur zur Speicherung von Protokollen und zur Suche danach verwendet werden. Der gesamte Stack bietet große Möglichkeiten zur Verarbeitung und Analyse der eingehenden Daten, wobei der Prometheus-Ansatz verwendet wird.
Eine Beschreibung des Installationsprozesses finden Sie hier.

Suche in Protokollen

In den Protokollen kann über die spezielle Benutzeroberfläche Grafana - Explorer - gesucht werden. Für Abfragen wird die Sprache LogQL verwendet, die PromQL, die in Prometheus verwendet wird, sehr ähnlich ist. Man kann sie grundsätzlich als verteiltes grep betrachten.

Die Suchoberfläche sieht so aus:

Wir sammeln Protokolle mit Loki

Die Anfrage besteht aus zwei Teilen: selector und filter. Der Selector ist die Suche nach indizierten Metadaten (Labels), die den Protokollen zugewiesen sind, und der Filter ist der Suchstring oder RegEx, mit dem die durch den Selector definierten Einträge gefiltert werden. Im gegebenen Beispiel: In geschweiften Klammern befindet sich der Selector, alles, was danach kommt - der Filter.

{image_name="nginx.promtail.test"} |= "index"

Wegen des Arbeitsprinzips von Loki können keine Anfragen ohne Selector gestellt werden, aber die Labels können beliebig allgemein gestaltet werden.

Der Selector ist ein Key-Value-Wert in geschweiften Klammern. Selector können kombiniert und unterschiedliche Suchbedingungen mithilfe der Operatoren =, != oder regulären Ausdrücken festgelegt werden:

{instance=~"kafka-[23]",name!="kafka-dev"} 
// Findet Protokolle mit dem Label Instance, die die Werte kafka-2, kafka-3 haben und schließt dev aus. 

Ein Filter ist ein Text oder Regex, der alle Daten, die vom Selektor erhalten wurden, herausfiltert.

Es besteht die Möglichkeit, ad-hoc-Diagramme aus den erhaltenen Daten im Metrics-Modus zu erstellen. Zum Beispiel kann man die Häufigkeit von Einträgen im nginx-Protokoll herausfinden, die den String index: enthalten:

Wir sammeln Protokolle mit Loki

Eine vollständige Beschreibung der Möglichkeiten finden Sie in der Dokumentation. LogQL.

Protokollanalyse

Es gibt mehrere Möglichkeiten, Protokolle zu sammeln:

  • Mit Promtail, dem Standardkomponenten des Stacks zum Sammeln von Protokollen.
  • Direkt vom Docker-Container durch Loki Docker Logging Driver.
  • Verwenden Sie Fluentd oder Fluent Bit, die in der Lage sind, Daten an Loki zu senden. Im Gegensatz zu Promtail haben sie bereits fertige Parser für nahezu jede Art von Protokoll und bewältigen auch Multiline-Protokolle.

Normalerweise wird Promtail zur Analyse verwendet. Es macht drei Dinge:

  • Es findet Datenquellen.
  • Es fügt Labels hinzu.
  • Es sendet Daten an Loki.

Aktuell kann Promtail Protokolle von lokalen Dateien und aus dem systemd-Journal lesen. Es muss auf jeder Maschine installiert werden, von der Protokolle gesammelt werden.

Es gibt eine Integration mit Kubernetes: Promtail erkennt automatisch über die Kubernetes REST-API den Zustand des Clusters und sammelt Protokolle von Knoten, Diensten oder Pods und fügt sofort Labels basierend auf Metadaten aus Kubernetes hinzu (Pod-Name, Dateiname usw.).

Labels können auch basierend auf den Daten aus dem Protokoll mit Hilfe von Pipelines hinzugefügt werden. Die Pipeline von Promtail kann aus vier Arten von Phasen bestehen. Genauere Informationen finden Sie in offiziellen Dokumentation, hier möchte ich einige Nuancen erwähnen.

  1. Parsing-Stufen. Dies ist die RegEx- und JSON-Phase. In diesem Schritt extrahieren wir Daten aus Protokollen in das sogenannte extracted map. Daten können aus JSON extrahiert werden, indem die benötigten Felder in das extracted map kopiert werden, oder über reguläre Ausdrücke (RegEx), bei denen in extracted map "named groups" abgebildet werden. Das extracted map stellt einen Key-Value-Speicher dar, wo der Key der Feldname und der Value dessen Wert aus den Protokollen ist.
  2. Transformationsstufen. Diese Phase hat zwei Optionen: transform, wo wir Transformationsregeln festlegen, und source – die Datenquelle für die Transformation aus dem extracted map. Wenn ein Feld im extracted map nicht vorhanden ist, wird es erstellt. So können Labels erstellt werden, die nicht auf dem extracted map basieren. In diesem Schritt können wir die Daten im extracted map manipulieren, indem wir eine ausreichend leistungsfähige Golang-Vorlage verwenden.. Außerdem ist zu beachten, dass die extracted map beim Parsen vollständig geladen wird, was es ermöglicht, beispielsweise den Wert darin zu überprüfen: “{{if .tag}tag value exists{end}}”. Die Vorlage unterstützt Bedingungen, Schleifen und einige Stringfunktionen wie Replace und Trim.
  3. Aktionsphasen. In dieser Phase kann etwas mit dem Ausgezogenen gemacht werden:
    • Ein Label aus den extrahierten Daten erstellen, das von Loki indiziert wird.
    • Die Zeit des Ereignisses aus dem Protokoll ändern oder festlegen.
    • Die Daten (Logtext), die an Loki gesendet werden, ändern.
    • Metriken erstellen.
  4. Filterphasen. Die Match-Phase, in der man entweder die unnötigen Einträge an /dev/null senden oder sie zur weiteren Verarbeitung weiterleiten kann.

Ich zeige am Beispiel der Verarbeitung von regulären nginx-Protokollen, wie man Protokolle mit Promtail parsen kann.

Für den Test verwenden wir als nginx-Proxy ein modifiziertes Image von nginx jwilder/nginx-proxy:alpine und einen kleinen Daemon, der sich selbst über HTTP abfragen kann. Der Daemon hat mehrere Endpunkte konfiguriert, auf die er Antworten unterschiedlicher Größe, mit verschiedenen HTTP-Status und unterschiedlichen Verzögerungen geben kann.

Wir sammeln Protokolle von Docker-Containern, die man unter /var/lib/docker/containers//-json.log findet.

In docker-compose.yml konfigurieren wir Promtail und geben den Pfad zur Konfiguration an:

promtail:
  image: grafana/promtail:1.4.1
 // ...
 volumes:
   - /var/lib/docker/containers:/var/lib/docker/containers:ro
   - promtail-data:/var/lib/promtail/positions
   - ${PWD}/promtail/docker.yml:/etc/promtail/promtail.yml
 command:
   - '-config.file=/etc/promtail/promtail.yml'
 // ...

Wir fügen in promtail.yml den Pfad zu den Protokollen hinzu (in der Konfiguration gibt es die Option "docker", die dasselbe in einer Zeile macht, aber das wäre nicht so anschaulich):

scrape_configs:
 - job_name: containers

   static_configs:
       labels:
         job: containerlogs
         __path__: /var/lib/docker/containers/*/*log  # nur für Linux

Wenn diese Konfiguration aktiviert ist, gelangen Protokolle von allen Containern in Loki. Um dies zu vermeiden, ändern wir die Einstellungen des Test-nginx in docker-compose.yml — wir fügen die Protokollierung mit dem Feld tag hinzu:

proxy:
 image: nginx.test.v3
//…
 logging:
   driver: "json-file"
   options:
     tag: "{{.ImageName}}|{{.Name}}"

Wir bearbeiten promtail.yml und konfigurieren die Pipeline. Die Protokolle, die eintreffen, haben folgendes Format:

{"log":"u001b[0;33;1mnginx.1    | u001b[0mnginx.test 172.28.0.3 - - [13/Jun/2020:23:25:50 +0000] "GET /api/index HTTP/1.1" 200 0 "-" "Stub_Bot/0.1" "0.096"n","stream":"stdout","attrs":{"tag":"nginx.promtail.test|proxy.prober"},"time":"2020-06-13T23:25:50.66740443Z"}
{"log":"u001b[0;33;1mnginx.1    | u001b[0mnginx.test 172.28.0.3 - - [13/Jun/2020:23:25:50 +0000] "GET /200 HTTP/1.1" 200 0 "-" "Stub_Bot/0.1" "0.000"n","stream":"stdout","attrs":{"tag":"nginx.promtail.test|proxy.prober"},"time":"2020-06-13T23:25:50.702925272Z"}

Pipeline-Phase:

 - json:
     expressions:
       stream: stream
       attrs: attrs
       tag: attrs.tag

Wir extrahieren die Felder stream, attrs, attrs.tag (falls vorhanden) aus dem eingehenden JSON und legen sie in die extrahierte Map.

 - regex:
     expression: ^(?P([^|]+))|(?P([^|]+))$
     source: "tag"

Wenn es gelungen ist, das Feld tag in die extrahierte Map zu legen, extrahieren wir mit einem regulären Ausdruck die Namen des Bildes und des Containers.

 - labels:
     image_name:
     container_name:

Wir weisen Labels zu. Wenn in den extrahierten Daten die Schlüssel image_name und container_name gefunden werden, werden ihre Werte den entsprechenden Labels zugewiesen.

 - match:
     selector: '{job="docker",container_name="",image_name=""}'
     action: drop

Wir verwerfen alle Logs, bei denen die festgelegten Labels image_name und container_name nicht gefunden wurden.

  - match:
     selector: '{image_name="nginx.promtail.test"}'
     stages:
       - json:
           expressions:
             row: log

Für alle Logs, bei denen image_name gleich nginx.promtail.test ist, extrahieren wir das Feld log aus dem ursprünglichen Log und legen es in die extrahierte Map mit dem Schlüssel row.

  - regex:
         # Farben unterdrücken
         expression: .+nginx.+|.+[0m(?P[a-z_.-]+) +(?P.+)
         source: logrow

Wir bereinigen die Eingabestrings mit regulären Ausdrücken und extrahieren den nginx-virtuellen Host und die nginx-Logzeile.

     - regex:
         source: nginxlog
         expression: ^(?P[w.]+) - (?P[^ ]*) [(?P[^ ]+).*] "(?P[^ ]*) (?P[^ ]*) (?P[^ ]*)" (?P[d]+) (?P[d]+) "(?P[^"]*)" "(?P[^"]*)"( "(?P[d.]+)")?

Wir parsen das nginx-Log mit regulären Ausdrücken.

    - regex:
           source: request_url
           expression: ^.+.(?Pjpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$
     - regex:
           source: request_url
           expression: ^/photo/(?P[^/?.]+).*$
       - regex:
           source: request_url
           expression: ^/api/(?P[^/?.]+).*$

Wir analysieren request_url. Mit Hilfe eines regulären Ausdrucks bestimmen wir den Zweck der Anfrage: ob es sich um statische Inhalte, Fotos oder API handelt und setzen den entsprechenden Schlüssel in die extrahierte Map.

       - template:
           source: request_type
           template: "{{if .photo}}photo{{else if .static_type}}static{{else if .api_request}}api{{else}}other{{end}}"

Mit bedingten Operatoren in der Vorlage überprüfen wir die festgelegten Felder in der extrahierten Map und setzen die erforderlichen Werte für das Feld request_type: photo, static, API. Wir setzen other, wenn es nicht möglich war. Jetzt enthält request_type den Typ der Anfrage.

       - labels:
           api_request:
           virtual_host:
           request_type:
           status:

Wir setzen die Labels api_request, virtual_host, request_type und status (HTTP-Status) basierend auf den Werten, die wir in die extrahierte Map gelegt haben.

       - output:
           source: nginx_log_row

Wir ändern das output. Jetzt wird das bereinigte nginx-Log aus der extrahierten Map an Loki gesendet.

Wir sammeln Protokolle mit Loki

Nach dem Start der angegebenen Konfiguration kann man sehen, dass jeder Eintragung basierend auf den Logdaten Labels zugewiesen wurden.

Es ist zu beachten, dass das Extrahieren von Labels mit einer hohen Anzahl von Werten (Kardinalität) die Leistung von Loki erheblich verlangsamen kann. Das bedeutet, dass man beispielsweise user_id nicht in den Index aufnehmen sollte. Weitere Informationen hierzu finden Sie im Artikel “Wie Labels in Loki Log-Abfragen schneller und einfacher machen können”. Aber das bedeutet nicht, dass man nicht ohne Indizes nach user_id suchen kann. Man sollte Filter beim Suchen verwenden („grepen“ Sie die Daten), und der Index fungiert hier als Stream-ID.

Log-Visualisierung

Wir sammeln Protokolle mit Loki

Loki kann als Datenquelle für Grafana-Diagramme dienen, indem es LogQL verwendet. Folgende Funktionen werden unterstützt:

  • rate — Anzahl der Einträge pro Sekunde;
  • count over time — Anzahl der Einträge in einem bestimmten Zeitraum.

Es gibt auch aggregierende Funktionen wie Sum, Avg und andere. Man kann ziemlich komplexe Diagramme erstellen, zum Beispiel ein Diagramm über die Anzahl der HTTP-Fehler:

Wir sammeln Protokolle mit Loki

Die Standard-Datenquelle Loki hat im Vergleich zur Datenquelle Prometheus eingeschränkte Funktionalitäten (zum Beispiel kann das Legend nicht geändert werden), aber Loki kann als Datenquelle vom Typ Prometheus angeschlossen werden. Ich bin mir nicht sicher, ob dies ein dokumentiertes Verhalten ist, aber laut der Antwort der Entwickler “Wie man Loki als Prometheus-Datenquelle konfiguriert? · Problem #1222 · grafana/loki”, ist dies beispielsweise durchaus legitim, und Loki ist vollständig mit PromQL kompatibel.

Fügen Sie Loki als Datenquelle vom Typ Prometheus hinzu und schreiben Sie die URL /loki dazu:

Wir sammeln Protokolle mit Loki

Und man kann Diagramme erstellen, als ob wir mit Metriken aus Prometheus arbeiten würden:

Wir sammeln Protokolle mit Loki

Ich denke, dass die Unterschiede in der Funktionalität vorübergehend sind und die Entwickler dies in Zukunft beheben werden.

Wir sammeln Protokolle mit Loki

Metriken

In Loki besteht die Möglichkeit, numerische Metriken aus Logs zu extrahieren und an Prometheus zu senden. Zum Beispiel enthält das Nginx-Log die Anzahl der Bytes in der Antwort sowie, bei einer bestimmten Modifikation des Standardlogformats, die Zeit in Sekunden, die für die Antwort benötigt wurde. Diese Daten können extrahiert und an Prometheus gesendet werden.

Fügen wir einen weiteren Abschnitt in die promtail.yml hinzu:

- match:
   selector: '{request_type="api"}'
   stages:
     - metrics:
         http_nginx_response_time:
           type: Histogram
           description: "Antwortzeit ms"
           source: response_time
           config:
             buckets: [0.010,0.050,0.100,0.200,0.500,1.0]
- match:
   selector: '{request_type=~"static|photo"}'
   stages:
     - metrics:
         http_nginx_response_bytes_sum:
           type: Counter
           description: "Summe der Antwortbytes"
           source: bytes_out
           config:
             action: add
         http_nginx_response_bytes_count:
           type: Counter
           description: "Anzahl der Antwortbytes"
           source: bytes_out
           config:
             action: inc

Die Option ermöglicht es, Metriken basierend auf den Daten aus der extracted map zu definieren und zu aktualisieren. Diese Metriken werden nicht an Loki gesendet – sie erscheinen im Promtail /metrics-Endpunkt. Prometheus muss so konfiguriert sein, dass die auf dieser Stufe erhaltenen Daten abgerufen werden. Im gegebenen Beispiel für request_type="api" sammeln wir die Histogramm-Metrik. Mit dieser Art von Metriken sind Perzentile bequem zu erhalten. Für Statis und Fotos sammeln wir die Byte-Summe und die Anzahl der Zeilen, in denen wir Bytes erhalten haben, um den Durchschnittswert zu berechnen.

Mehr über Metriken erfahren Sie hier.

Öffnen Sie den Port auf Promtail:

promtail:
     image: grafana/promtail:1.4.1
     container_name: monitoring.promtail
     expose:
       - 9080
     ports:
       - "9080:9080"

Stellen Sie sicher, dass die Metriken mit dem Präfix promtail_custom erschienen sind:

Wir sammeln Protokolle mit Loki

Konfigurieren Sie Prometheus. Fügen Sie Job promtail hinzu:

- job_name: 'promtail'
 scrape_interval: 10s
 static_configs:
   - targets: ['promtail:9080']

Und zeichnen Sie das Diagramm:

Wir sammeln Protokolle mit Loki

So kann man beispielsweise die vier langsamsten Anfragen herausfinden. Außerdem können Sie das Monitoring auf diese Metriken einstellen.

Skalierung

Loki kann sowohl im Einzelmodus (single binary mode) als auch im sharded (horizontally-scalable mode) betrieben werden. Im zweiten Fall kann es Daten in der Cloud speichern, wobei Chunks und Indizes getrennt gespeichert werden. In Version 1.5 wurde die Möglichkeit implementiert, alles an einem Ort zu speichern, wird jedoch derzeit nicht für den Einsatz in der Produktion empfohlen.

Wir sammeln Protokolle mit Loki

Chunks können in einem S3-kompatiblen Speicher gespeichert werden; für die Speicherung von Indizes sollten horizontal skalierbare Datenbanken wie Cassandra, BigTable oder DynamoDB verwendet werden. Andere Teile von Loki – Distributors (für Schreiben) und Querier (für Abfragen) – sind stateless und können ebenfalls horizontal skaliert werden.

Auf der Konferenz DevOpsDays Vancouver 2019 sagte einer der Teilnehmer, Callum Styan, dass sein Projekt mit Loki Petabytes an Protokollen hat, wobei der Index weniger als 1 % der Gesamtgröße beträgt: “Wie Loki Metriken und Protokolle korreliert – Und Ihnen Geld spart”.

Vergleich zwischen Loki und ELK

Größe des Indexes

Zur Überprüfung der erhaltenen Indexgröße habe ich Protokolle vom nginx-Container verwendet, für den der oben genannte Pipeline konfiguriert wurde. Die Protokolldatei enthielt 406.624 Zeilen mit einem Gesamtvolumen von 109 MB. Die Protokolle wurden über eine Stunde hinweg generiert, etwa 100 Einträge pro Sekunde.

Beispiel von zwei Zeilen aus dem Protokoll:

Wir sammeln Protokolle mit Loki

Bei der Indizierung durch ELK führte dies zu einer Indexgröße von 30,3 MB:

Wir sammeln Protokolle mit Loki

Im Falle von Loki ergab sich ein Index von etwa 128 KB und etwa 3,8 MB Daten in den Chunks. Es ist zu beachten, dass das Protokoll künstlich generiert wurde und nicht sehr vielfältige Daten aufwies. Ein einfacher gzip auf dem ursprünglichen Docker-JSON-Log mit Daten ergab eine Kompression von 95,4 %, und da im Loki nur das bereinigte Nginx-Protokoll gesendet wurde, ist die Verdichtung auf 4 MB nachvollziehbar. Die Gesamtanzahl der einzigartigen Werte für die Labels in Loki betrug 35, was die kleine Größe des Indexes erklärt. Auch für ELK wurde das Protokoll bereinigt. Somit komprimierte Loki die ursprünglichen Daten um 96 %, während ELK 70 % erreichte.

Speicherverbrauch

Wir sammeln Protokolle mit Loki

Wenn man den gesamten Stack von Prometheus und ELK vergleicht, verbraucht Loki deutlich weniger. Es ist klar, dass ein Service in Go weniger benötigt als ein Service in Java, und der Vergleich der Größe des JVM-Heaps von Elasticsearch und des zugewiesenen Speichers für Loki ist nicht korrekt, dennoch ist zu beachten, dass Loki viel weniger Speicher verwendet. Sein Vorteil beim CPU-Verbrauch ist nicht so offensichtlich, aber ebenfalls vorhanden.

Geschwindigkeit

Loki verarbeitet Protokolle schneller. Die Geschwindigkeit hängt von vielen Faktoren ab – welche Protokolle es sind, wie raffiniert wir sie parsen, Netzwerk, Festplatte usw. – aber sie ist eindeutig höher als die von ELK (in meinem Test etwa doppelt so schnell). Das wird dadurch erklärt, dass Loki viel weniger Daten in den Index legt und dementsprechend weniger Zeit für die Indizierung benötigt. Bei der Geschwindigkeit der Suche ist die Situation jedoch umgekehrt: Loki verlangsamt sich merklich bei Daten, die größer als mehrere Gigabyte sind, während die Suchgeschwindigkeit bei ELK nicht von der Größe der Daten abhängt.

Suche in Protokollen

Loki hat erhebliche Einschränkungen bei den Suchmöglichkeiten im Protokoll. Grep mit regulären Ausdrücken ist eine starke Methode, aber es ist nicht vergleichbar mit einer vollwertigen Datenbank. Das Fehlen von Range-Abfragen, die Aggregation nur nach Labels und die Unfähigkeit, ohne Labels zu suchen, schränken uns bei der Suche nach interessanten Informationen in Loki ein. Das bedeutet nicht, dass man mit Loki nichts finden kann, aber es prägt den Workflow mit Protokollen, bei dem man zunächst ein Problem in den Grafiken von Prometheus findet und dann anhand dieser Labels nachforscht, was in den Protokollen passiert ist.

Benutzeroberfläche

Erstens, es sieht gut aus (entschuldigung, ich konnte nicht widerstehen). Grafana hat eine ansprechende Benutzeroberfläche, aber Kibana ist deutlich funktioneller.

Vorteile und Nachteile von Loki

Unter den Vorteilen kann man hervorheben, dass Loki nahtlos mit Prometheus integriert ist, wodurch wir Metriken und Alarme sofort nutzen können. Es eignet sich gut zur Erfassung und Speicherung von Logs mit Kubernetes Pods, da es über das von Prometheus geerbte Service Discovery verfügt und automatisch Labels anbringt.

Zu den Nachteilen gehört die schwache Dokumentation. Einige Dinge, wie die Besonderheiten und Funktionen von Promtail, habe ich nur im Verlauf der Untersuchung des Codes entdeckt, zum Glück ist es Open Source. Ein weiterer Nachteil sind die schwachen Parsing-Möglichkeiten. Zum Beispiel kann Loki keine Multiline-Logs parsen. Zu den Nachteilen zählt auch, dass Loki eine relativ junge Technologie ist (die Version 1.0 wurde im November 2019 veröffentlicht).

Fazit

Loki ist eine zu 100 % interessante Technologie, die sich für kleine und mittelgroße Projekte eignet und zahlreiche Aufgaben im Bereich Log-Aggregation, Log-Suche, Monitoring und Log-Analyse löst.

Wir verwenden Loki bei Badoo nicht, da wir einen ELK-Stack haben, der uns zufriedenstellt und über viele Jahre hinweg mit verschiedenen maßgeschneiderten Lösungen gewachsen ist. Für uns ist die Log-Suche ein entscheidender Punkt. Bei fast 100 GB Logs pro Tag ist es wichtig, alles und etwas mehr schnell finden zu können. Für das Erstellen von Grafiken und Monitoring verwenden wir andere Lösungen, die auf unsere Bedürfnisse zugeschnitten und miteinander integriert sind. Der Loki-Stack hat spürbare Vorteile, aber er wird uns nicht mehr bieten als das, was wir bereits haben, und seine Vorteile überwiegen auf keinen Fall die Kosten einer Migration.

Und obwohl nach der Untersuchung klar wurde, dass wir Loki nicht verwenden können, hoffen wir, dass dieser Beitrag Ihnen bei Ihrer Wahl hilft.

Das Repository mit dem in dem Artikel verwendeten Code befindet sich hier.

Quelle: habr.com

60GB SSD 8Gb DDR4