24.08.2022

Logs aus dem gesamten Cluster sammeln

Kubernetes Logging mit Promtail, Loki und Grafana

Das Lesen von Protokollen aus mehreren Kubernetes-Pods mit kubectl kann schnell umständlich werden. Was wäre, wenn es eine Möglichkeit gäbe, Protokolle aus dem gesamten Cluster an einem einzigen Ort zu sammeln und sie einfach zu filtern, abzufragen und zu analysieren? Hier kommen Promtail, Loki und Grafana ins Spiel.

my image

Table of contents

Einführung (Was ist das, warum brauchen wir es)

Standardmäßig halten Logs in Kubernetes nur während der Lebensdauer eines Pods. Um Logs länger als die Lebensdauer eines einzelnen Pods aufzubewahren, verwenden wir Log-Aggregation. Das bedeutet, dass wir Logs aus verschiedenen Quellen an einem einzigen Ort speichern, um sie auch nach einem Fehler leicht analysieren zu können. Während der ELK-Stack (kurz für Elasticsearch, Logstash, Kibana) eine beliebte Lösung für die Log-Aggregation ist, haben wir uns für etwas leichtgewichtigeres entschieden: Loki.

Entwickelt von Grafana Labs, ist "Loki ein horizontal skalierbares, hochverfügbares, mandantenfähiges Log-Aggregationssystem, das von Prometheus inspiriert ist". Loki ermöglicht eine einfache Sammlung von Logs aus verschiedenen Quellen mit unterschiedlichen Formaten, skalierbare Persistenz über Objektspeicher und einige weitere coole Funktionen, die wir später im Detail erklären werden. Werfen wir jetzt einen Blick auf das von uns erstellte Setup.

Deck

Wenn du nur einen schnellen Blick darauf werfen möchtest, kannst du Deck verwenden, um diesen Stack mit einem Befehl auf deinem Computer einzurichten. Nach der Installation von Deck kannst du Folgendes ausführen:

$ deck get https://raw.githubusercontent.com/Getdeck/wharf/main/loki/deck.yaml

Folge den Anweisungen, die nach Abschluss des Installationsprozesses angezeigt werden, um sich bei Grafana anzumelden und mit der Erkundung zu beginnen.

Setup

In diesem Artikel konzentrieren wir uns auf die Helm-Installation. Grafana Labs bietet eine Reihe von anderen Installationsmethoden an.

Im Helm-Chart-Repository von Grafana findest du 5 Charts, die mit Loki zusammenhängen. Loki-canary ermöglicht dir die Installation von Canary-Builds von Loki in deinem Cluster. Loki-distributed installiert die relevanten Komponenten als Microservices und bietet dir die üblichen Vorteile von Microservices wie Skalierbarkeit, Ausfallsicherheit usw., während du sie unabhängig voneinander konfigurieren kannst. Loki-simple-scalable ist ähnlich, jedoch sind einige der Komponenten immer aktiviert, was einige der Konfigurationsmöglichkeiten einschränkt. Das Chart mit dem Namen Loki wird einen einzelnen StatefulSet in deinem Cluster bereitstellen, der alles enthält, was du zum Ausführen von Loki benötigst. Das letzte in der Gruppe ist loki-stack, das zusätzlich zum Loki-Chart dasselbe StatefulSet bereitstellt, auch Promtail, Grafana und einige andere. Für unseren Anwendungsfall haben wir uns für das Loki-Chart entschieden. Neben Loki selbst werden in unserem Cluster auch Promtail und Grafana ausgeführt. Im folgenden Abschnitt zeigen wir dir, wie du diesen Log-Aggregations-Stack in deinem Cluster installieren kannst!

Voraussetzungen

Um mitzumachen, benötigst du einen Kubernetes-Cluster, auf den du über kubectl zugreifen kannst, und Helm muss auf deinem Computer eingerichtet sein.

Zunächst müssen wir das Chart-Repository von Grafana zu unserer lokalen Helm-Installation hinzufügen und die neuesten Charts abrufen, wie folgt:

$ helm repo add grafana https://grafana.github.io/helm-charts
$ helm repo update

Sobald das erledigt ist, können wir mit dem eigentlichen Installationsprozess beginnen.

Loki Installation

Lass uns damit beginnen, Loki in unserem Cluster zum Laufen zu bringen. Um deine Installation zu konfigurieren, wirf einen Blick auf die Werte, die das Loki-Chart über den Befehl 'helm show values' akzeptiert, und speichere diese in einer Datei.

$ helm show values grafana/loki > loki-values.yaml

Wir werden die Einstellungen nicht im Detail besprechen, da die meisten Werte auf ihren Standardwerten belassen werden können. Du solltest jedoch einen Blick auf den persistence-Schlüssel werfen, um Loki so zu konfigurieren, dass deine Protokolle tatsächlich in einem PersistentVolume gespeichert werden.

persistence:
    enabled: true
    accessModes:
    - ReadWriteOnce
    size: 10Gi
    annotations: {}

Sobald du die Werte an deine Vorlieben angepasst hast, installiere Loki in deinem Cluster mit dem folgenden Befehl:

$ helm upgrade --install loki grafana/loki -n loki -f loki-values.yaml

Nachdem das erledigt ist, kannst du überprüfen, ob alles funktioniert hat, indem du kubectl verwendest:

$ kubectl get pods -n loki
NAME                            READY   STATUS    RESTARTS   AGE
loki-0                          1/1     Running   0          1h

Wenn die Ausgabe ähnlich aussieht, herzlichen Glückwunsch! Das ist einer von drei Komponenten, die erfolgreich installiert wurden.

Promtail Installation

Als nächstes schauen wir uns Promtail an. Promtail hat 3 Hauptfunktionen, die für unsere Einrichtung wichtig sind:

  1. Es erkennt Ziele (Pods, die in unserem Cluster ausgeführt werden)
  2. Es beschriftet Logstreams (hängt Metadaten wie Pod/Dateinamen usw. an, um sie später einfacher identifizieren zu können)
  3. Es versendet sie an unsere Loki-Instanz

Um es zu installieren, benötigen wir zuerst eine Werte-Datei, genau wie wir es für Loki getan haben:

$ helm show values grafana/promtail > promtail-values.yaml

Wie bei Loki können die meisten Werte auf ihren Standardwerten belassen werden, um Promtail zum Laufen zu bringen. Wir müssen jedoch Promtail mitteilen, wohin es die gesammelten Protokolle senden soll, indem wir Folgendes tun:

$ kubectl get svc -n loki
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
loki            ClusterIP   10.101.163.181           3100/TCP   1h

Wir fragen kubectl nach den Diensten im Loki-Namespace und es wird uns mitgeteilt, dass es einen Dienst namens Loki gibt, der den Port 3100 freigibt. Um Promtail dazu zu bringen, unsere Protokolle an das richtige Ziel zu senden, zeigen wir es über den 'config'-Schlüssel in unserer Werte-Datei auf den Loki-Dienst.

config:
 logLevel: info
 serverPort: 3101
 lokiAddress: http://loki:3100/loki/api/v1/push

Unter 'lokiAddress' geben wir an, dass Promtail Protokolle an 'http://loki:3100/loki/api/v1/push' senden soll. Beachtem dass du, wenn Loki nicht im selben Namespace wie Promtail läuft, die vollständige Service-Adressnotation verwenden musst, z. B. '..svc.cluster.local:'. Promtail läuft als DaemonSet und hat die folgenden Tolerations, um auf Master- und Worker-Knoten ausgeführt zu werden.

tolerations:
    - key: node-role.kubernetes.io/master
    operator: Exists
    effect: NoSchedule
    - key: node-role.kubernetes.io/control-plane
    operator: Exists
    effect: NoSchedule

Wenn du nicht möchtest, dass Promtail auf deinen Master-/Control-Plane-Knoten ausgeführt wird, kannst du dies hier ändern.

Jetzt, da wir die wichtigsten Werte festgelegt haben, lass uns das installieren!

$ helm upgrade --install promtail grafana/promtail --namespace=loki -f promtail-values.yaml

Überprüfe, ob alles wie erwartet funktioniert:

$ kubectl get ds -n loki
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
promtail   8         8         8       8            8                     1h

Du kannst auch mit dem Flag '-o wide' einen Blick auf die Pods werfen, um zu sehen, auf welchem Knoten sie ausgeführt werden:

$ kubectl get pods -n loki -o wide
NAME                            READY   STATUS    RESTARTS   AGE    IP         NODE                     NOMINATED NODE   READINESS GATES
promtail-2j9dj                  1/1     Running   0          1h    1.1.1.1     control-plane-3                     
promtail-5wjxl                  1/1     Running   0          1h    1.1.1.1     control-plane-1                     
promtail-9nvps                  1/1     Running   0          1h    1.1.1.1     worker-1                            
promtail-brgj2                  1/1     Running   0          1h    1.1.1.1     worker-2                            
promtail-cfnff                  1/1     Running   0          1h    1.1.1.1     control-plane-2                     
promtail-gtt6m                  1/1     Running   0          1h    1.1.1.1     worker-3                            
promtail-hnh4z                  1/1     Running   0          1h    1.1.1.1     worker-4                            
promtail-r4xsz                  1/1     Running   0          1h    1.1.1.1     worker-5                            

Grafana Installation

Zu guter Letzt, lass uns eine Instanz von Grafana in unserem Cluster starten.

Die folgenden Werte ermöglichen die Persistenz. Wenn du möchtest, dass deine Grafana-Instanz E-Mails senden kann, kannst du SMTP wie unten gezeigt konfigurieren. Füge einfach deinen SMTP-Host und 'from_address' hinzu, um ein Secret mit deinen Anmeldeinformationen zu erstellen.

persistence:
 type: pvc
 enabled: true
 # storageClassName: default
 accessModes:
   - ReadWriteOnce
 size: 10Gi
grafana.ini:
 smtp:
   enabled: true
   host: smtp.smtpserver.io:465
   from_address: grafana@collectallthelogs.io
   skip_verify: true
smtp:
 # `existingSecret` is a reference to an existing secret containing the smtp configuration
 # for Grafana.
 existingSecret: "grafana-smtp"
 userKey: "user"
 passwordKey: "password"

Sobald du deine Werte konfiguriert hast, kannst du Grafana wie folgt in deinem Cluster installieren:

helm upgrade --install loki-grafana grafana/grafana --namespace=loki -f grafana-values.yaml

Überprüfe, ob alles reibungslos verlaufen ist:

$ kubectl get pods -n loki
NAME                            READY   STATUS    RESTARTS   AGE
loki-grafana-64b4b79494-8bt7c   1/1     Running   0          1h

Alle drei Komponenten sind einsatzbereit, super! Jetzt, da alles eingerichtet ist, schauen wir uns an, wie wir dies tatsächlich nutzen können.

UNSER KUBERNETES-PODCAST

Werkzeuge für das Handwerk: Die Navigation im Kubernetes-Ökosystem

Michael und Robert sprechen ausführlich über die Feinheiten der lokalen Kubernetes-Entwicklung und geben auch einige echte Codierungsbeispiele.

Weitere Ausgaben unseres Podcasts findest du hier:

Verwendung

Verbinde deine neu erstellte Loki-Instanz einfach mit Grafana. Alles, was du tun musst, ist eine Datenquelle in Grafana zu erstellen. Unter Konfiguration → Datenquellen klicke auf 'Datenquelle hinzufügen' und wähle Loki aus der Liste aus. Dir wird dieses Einstellungsfenster angezeigt, in dem du nur die URL deiner Loki-Instanz konfigurieren musst, um deine Protokolle mit Grafana zu analysieren. Da Grafana im selben Namespace wie Loki läuft, reicht es aus, 'http://loki:3001' anzugeben.

Verwendung

Wenn du fertig bist, klicke auf 'Speichern & Testen' und voilà, du bist bereit, Abfragen gegen Loki auszuführen.

LogQL

‘LogQL ist die von Grafana Loki inspirierte Abfragesprache, ähnlich wie PromQL. Abfragen fungieren wie ein verteilter grep, um Log-Quellen zu aggregieren. LogQL verwendet Labels und Operatoren zur Filterung.’

Mit LogQL kannst du einfach Abfragen gegen deine Protokolle ausführen. Du kannst entweder Protokollabfragen ausführen, um den Inhalt tatsächlicher Protokollzeilen zu erhalten, oder Metrikabfragen verwenden, um Werte basierend auf den Ergebnissen zu berechnen.

LogQL ist gut dokumentiert, daher gehen wir nicht auf jedes Feature im Detail ein, sondern geben dir stattdessen einige Abfragen, die du sofort gegen deine Protokolle ausführen kannst, um loszulegen. Gehe zum Explore-Panel in Grafana (${grafanaUrl}/explore), wähle deine Loki-Datenquelle im Dropdown-Menü aus und schau dir an, was Loki bisher für dich gesammelt hat.

Simple Log Query

Wenn du nur die Protokolle eines einzelnen Pods haben möchtest, ist es so einfach, eine Abfrage wie diese auszuführen:

{pod="loki-0"}

Grafana wählt automatisch das richtige Panel für dich aus und zeigt an, was dein Loki Pod protokolliert.

Fehler in einem Namespace

Diese Abfrage filtert Protokolle aus einem bestimmten Namespace, die das Wort "Fehler" enthalten. Sie zählt sie über den im Dashboard ausgewählten Bereich und gibt die Summe zurück, um dir einen einfachen Überblick darüber zu geben, was in deinem Cluster passiert.

sum(count_over_time({namespace="loki"} |= "error" [$__range]))

Durchschnittliche Antwortzeit in einem Namespace, nach Pfad und Anwendung

Diese Abfrage ist so komplex wie es in diesem Artikel wird. Sie sammelt Protokolle aus einem Namespace und wendet dann mehrere nützliche Funktionen von LogQL an, wie zum Beispiel Musterabgleich, reguläre Ausdrücke, Zeilenformatierung und Filterung. Am Ende erhältst du die durchschnittliche Antwortzeit von Anwendungen, die im angegebenen Namespace innerhalb des ausgewählten Intervalls ausgeführt werden. Sie filtern effektiv die Protokollzeilen heraus, die von Kubernetes Liveness- und Readiness-Probes generiert werden, gruppiert nach App-Label und Pfad. Hinweis: Diese genaue Abfrage funktioniert für das Protokollformat von Django Hurricane, aber du kannst sie anpassen, indem du das Muster an dein Protokollformat anpasst.

avg_over_time({namespace="application"} | pattern " 

Sonstige Merkmale/Weitere Lektüre/Heiligtümer

Wenn du deine Logs nicht in deinem Cluster speichern möchtest, kannst du die gesammelten Daten an S3-kompatible Speicherlösungen wie Amazon S3 oder MinIO senden. Der Prozess der Log-Analyse/-Ansicht bleibt derselbe.

Die Dateispeicherung funktioniert nicht, wenn du das verteilte Chart verwendest, da mehrere Pods Lese-/Schreibvorgänge auf demselben PV durchführen müssten. Dies ist im Chart-Repository dokumentiert, wird jedoch leider nicht in der offiziellen Dokumentation von Loki erwähnt.

LogCLI ist das CLI-Tool von Loki, mit dem du deine Protokolle bequem von der Kommandozeile aus durchsuchen kannst. Hierfür musst du deine Loki-Instanz über HTTP freigeben oder Port-Forwarding von deinem Cluster zu deinem Computer verwenden.

BLUESHOE GmbH
© 2024 BLUESHOE GmbH