Zentralisiertes Logging setzt heute meist auf Splunk oder auf ElasticSearch, LogStash und Kibana. Doch wo Hardwareressourcen und Budget geschont
werden sollen, ist Loki eine leichtfüßige Alternative, die Logdaten zentral
akkumuliert. Wir zeigen, wie
das funktioniert und bringen Loki und
sein Gegenstück auf der Host-Seite
Promtail sowie Grafana schnell an den Start. Abschließend blicken wir auf die
Integration mit Kubernetes.
Die Cloud sorgt in der IT für diverse Umwälzungen. Eine
massive Änderung ist, dass sich klassische IT-Dienstleister heute immer öfter zu
Plattformbetreibern wandeln, die ihren Kunden verschiedene As-a-Service-Angebote
zur Verfügung stellen – oder virtuelle Hardware, um darauf eigene Dienste zu
betreiben. So oder so nimmt die Zahl an Systemen, mit denen ein
durchschnittlicher IT-Verantwortlicher es heute zu tun hat, kontinuierlich zu.
Selbst einfache Virtualisierung sorgt bereits dafür, dass auf einem einzelnen
Blech Dutzende virtuelle Instanzen laufen, die der Admin irgendwie unter
Kontrolle bringen muss.
Dieser Wildwuchs an zu wartenden Systemen erhöht die
Komplexität des gesamten Setups und macht es bei einem Ausfall nicht leichter,
das Problem zu identifizieren. Denn statt ein paar Systemen sieht sich der
Administrator heute üblicherweise weit verstreuten virtuellen Instanzen
gegenüber, in denen Dienste nach dem Microservices-Prinzip laufen und
untereinander munter Daten austauschen. Bei der Fehlersuche tummelt sich der
IT-Verantwortliche im schlechtesten Fall auf etlichen Systemen gleichzeitig,
indem er die dortigen Logs durchstöbert. Das ist weder effizient noch sonderlich
zuverlässig. Und dass ein Admin vor dem Hintergrund des Stresses, den ein
flächendeckender Ausfall auslöst, etwas übersieht, ist höchstwahrscheinlich.
Vor Jahren schon hat sich in der IT deshalb die Überzeugung
durchgesetzt, anstelle vieler kleiner loggender Inseln brauche es eine zentrale
Instanz, die sämtliche Logs eines Setups vorhält, indiziert und durchsuchbar
macht. Praktisch gibt es im Augenblick zwei konkurrierende Ansätze am Markt, die
dieses Prinzip umsetzen. Wer es sich leisten will greift zu Splunk und bekommt
gut funktionierende, zentrale Logging-Fähigkeiten nach strikten Vorgaben. Wer
das Geld sparen will oder für die eigene Umgebung mehr Flexibilität braucht,
landet heute meist bei einer Mischung aus ElasticSearch, LogStash und Kibana,
abgekürzt meist als "ELK". Dabei ist LogStash die Komponente, die Logs von den
Zielsystemen einsammelt, ElasticSearch die zentrale Datenbank und Kibana das
Frontend, das den Zugriff auf ElasticSearch ermöglicht.
Die Cloud sorgt in der IT für diverse Umwälzungen. Eine
massive Änderung ist, dass sich klassische IT-Dienstleister heute immer öfter zu
Plattformbetreibern wandeln, die ihren Kunden verschiedene As-a-Service-Angebote
zur Verfügung stellen – oder virtuelle Hardware, um darauf eigene Dienste zu
betreiben. So oder so nimmt die Zahl an Systemen, mit denen ein
durchschnittlicher IT-Verantwortlicher es heute zu tun hat, kontinuierlich zu.
Selbst einfache Virtualisierung sorgt bereits dafür, dass auf einem einzelnen
Blech Dutzende virtuelle Instanzen laufen, die der Admin irgendwie unter
Kontrolle bringen muss.
Dieser Wildwuchs an zu wartenden Systemen erhöht die
Komplexität des gesamten Setups und macht es bei einem Ausfall nicht leichter,
das Problem zu identifizieren. Denn statt ein paar Systemen sieht sich der
Administrator heute üblicherweise weit verstreuten virtuellen Instanzen
gegenüber, in denen Dienste nach dem Microservices-Prinzip laufen und
untereinander munter Daten austauschen. Bei der Fehlersuche tummelt sich der
IT-Verantwortliche im schlechtesten Fall auf etlichen Systemen gleichzeitig,
indem er die dortigen Logs durchstöbert. Das ist weder effizient noch sonderlich
zuverlässig. Und dass ein Admin vor dem Hintergrund des Stresses, den ein
flächendeckender Ausfall auslöst, etwas übersieht, ist höchstwahrscheinlich.
Vor Jahren schon hat sich in der IT deshalb die Überzeugung
durchgesetzt, anstelle vieler kleiner loggender Inseln brauche es eine zentrale
Instanz, die sämtliche Logs eines Setups vorhält, indiziert und durchsuchbar
macht. Praktisch gibt es im Augenblick zwei konkurrierende Ansätze am Markt, die
dieses Prinzip umsetzen. Wer es sich leisten will greift zu Splunk und bekommt
gut funktionierende, zentrale Logging-Fähigkeiten nach strikten Vorgaben. Wer
das Geld sparen will oder für die eigene Umgebung mehr Flexibilität braucht,
landet heute meist bei einer Mischung aus ElasticSearch, LogStash und Kibana,
abgekürzt meist als "ELK". Dabei ist LogStash die Komponente, die Logs von den
Zielsystemen einsammelt, ElasticSearch die zentrale Datenbank und Kibana das
Frontend, das den Zugriff auf ElasticSearch ermöglicht.
Loki minimiert Ressourcenbedarf
Galt ELK noch vor wenigen Jahren als Patentlösung für
zentralisiertes Logging, so mehren sich mittlerweile auch kritische Stimmen. Das
liegt vorrangig an der Art und Weise, wie ElasticSearch funktioniert. Denn das
Programm indiziert sämtliche eingehenden Logdateien vollständig und speichert
sie entsprechend ab. Das sorgt zwar dafür, dass eine umfassende Volltextsuche
zur Verfügung steht, über die sich diverse Ereignisse auch effizient korrelieren
lassen. Auf der anderen Seite bedient das ELK-Gespann sich aber auch frei- wie
großzügig an der vorhandenen Hardware. In vielen Fällen dimensionieren Admins
ihr ELK zu klein und laufen später in große Probleme. Hier treten die Entwickler
der Monitoring-Software Grafana auf den Plan: Sie haben in Form von Loki [1]
einen Gegenentwurf zu ELK für zentralisiertes Logging konzipiert, der der
Monitoringsoftware Prometheus in mancherlei Hinsicht ähnelt.
Der größte Unterschied zu ELK ist dabei, dass Loki die
eingesammelten Daten nicht vollständig indiziert, sondern lediglich in einzelnen
Teilen ("Chunks") speichert. Die Suche geschieht stattdessen ad hoc, wenn der
Nutzer tatsächlich Details aus den gespeicherten Logdateien braucht. Insgesamt
präsentiert sich Loki damit deutlich leichtfüßiger als die Konkurrenz, ohne im
administrativen Alltag relevante Features vermissen zu lassen. Besonders
praktisch: Loki verfügt über eine native Integration mit Kubernetes und kann
Logdateien aus Pods und Kubernetes verarbeiten.
Bild 1: Loki und Promtail lassen sich auf den Zielsystemen problemlos als Container betreiben, weil der Hersteller fertige Docker-Abbilder zur Verfügung stellt.
Wie Loki funktioniert
Wer die Komplexität von ELK gewohnt ist, wird sich bei Loki fast unterfordert
fühlen. Denn die Architektur des Programms ist ausgesprochen simpel. Loki selbst
ist eine Datenbank geschrieben in Go, die für das zentrale Speichern der Logs
verantwortlich ist. Im Innern besteht es aus mehreren Komponenten, die
ineinandergreifen. Die Loki-Entwickler unterscheiden bei ihrem Werkzeug zwischen
dem Schreiben von Logdateien einerseits und dem Lesen von Logdateien
andererseits, denn beide Vorgänge nehmen unterschiedliche Wege durch die
einzelnen Komponenten in Loki.
Zwar behauptet Loki von sich "wie Prometheus, aber für Logs" zu sein. Zwischen
Prometheus und Loki gibt es allerdings einen zentralen Unterschied: Prometheus
setzt auf das Pull-Verfahren, holt sich seine Metrikdaten also bei den
konfigurierten Zielen ab. Loki hingegen wartet darauf, dass Agenten auf
sämtlichen Zielsystemen ihre Logging-Daten senden – es folgt also dem
Push-Prinzip. Empfängt Loki eingehende Daten, landen diese zunächst in einer
Komponente namens "Distributor". Ein Distributor zeigt in Loki auf mehrere
Instanzen des sogenannten "Ingester", der die Monitoringdaten einem Downsampling
unterzieht. Dabei verwirft die Software bestimmte Teile und legt sie danach in
einem zentralen Ort ab. Zuvor komprimiert der Ingester die Daten allerdings
noch, um so viel Platz wie möglich zu sparen. Weil Logdaten meist reiner Text
sind, ist die Komprimierungsrate hier besonders hoch und der Admin braucht
weniger Hardware. Die Ingester pflegen zugleich auch die Indizes, in denen die
gespeicherten Chucks verzeichnet sind.
Der Lesepfad gestaltet sich etwas anders: Hier landen eingehende Requests
zunächst bei der "Query"-Komponente, die die Regeln für ihre Suche von einem
Bestandteil namens "Ruler" bezieht. Die Ruler-Komponente pflegt die Indizes der
hinterlegten Logs und hält sie in einem heißen Cache bereit, ebenso wie die
Query-Komponente. Erst wenn der Query-Dienst anhand der eingegebenen Daten klar
identifiziert hat, welche Logs er dem Client ausliefern soll, schreitet er zur
Tat. Anders als bei ELK steht dabei keine echte Volltextsuche zur Verfügung,
eben weil die Daten nicht in Loki vollständig indiziert sind. Der Admin wird in
den allermeisten Fällen jedoch in der Lage sein, aus einer Liste etwaiger
Logeinträge die passenden zu finden.
Der Speicherort als
wichtige Entscheidung
Klar ist freilich auch: Wie das große ELK muss Loki die von den Zielsystemen
geholten Logdaten irgendwo speichern. Hier spielt die Architektur von Loki eine
entscheidende Rolle. Denn sämtliche genannten Bestandteile, also die Querier,
die Distributors und jene Komponenten, die die Metadaten verwalten, lassen sich
allesamt redundant betreiben. Hierfür ist auch kein eigener Cluster-Modus nötig:
Jede Loki-Instanz kann in Grafana später als eigene Datenquelle zum Einsatz
kommen, sodass Grafana selbst sich bei einem der verfügbaren Backends bedient,
etwa im Round-Robin-Verfahren.
Damit das funktioniert, speichert Loki zwei Arten von Daten ab, die
tatsächlichen Nutzdaten (Chunks) und die dazugehörenden Indizes. Um die
Verwaltung beider Datenarten kann Loki sich wahlweise lokal kümmern. Zusätzlich
unterstützt Loki sowohl für die Indizes als auch für die Chucks diverse externe
Speicherarten. Die Indizes etwa finden auf Wunsch ihren Platz in Apache
Cassandra. Und die Chucks lassen sich in einem S3-kompatiblen Objektspeicher
lagern. Das reduziert die Last des lokalen Setups nochmals erheblich, weil
Clients auf der Suche nach bestimmten Inhalten die Chucks selbst via S3 laden,
statt sie durch das Loki-Setup zu beziehen.
Wer Loki verteilt und hochverfügbar betreiben will, sollte sich die Optionen
beim Thema "externer Speicher" jedenfalls gut ansehen. S3-Speicher bei Amazon
ist eher günstig, zumal seine Performance hier eine untergeordnete Rolle spielt.
Logdateien erreichen jedoch in Summe schnell große Umfänge und nicht jedes Setup
hat genug Platz, um die Logs etlicher Wochen vorzuhalten. Ein Cloudspeicher ist
hier vielleicht eine passende Alternative.
Promtail sammelt die Logs
Die Architektur von Loki ist wie beschrieben wenig komplex und einfach gebaut
ist auch der Dienst, der von den Zielsystemen die Logdateien einsammelt. Die
Loki-Entwickler haben das Werkzeug kurzerhand "Promtail" genannt, was eine
Reminiszenz an Prometheus einerseits und das Kommandozeilen-Werkzeug "tail"
andererseits ist. Tatsächlich betrachten die Entwickler Loki vorrangig als
Werkzeug, um über eine Vielzahl von Systemen gleichzeitig ein "tail -f"-Kommado
auszuführen und die Ergebnisse schnell miteinander zu korrelieren.
Doch weil Loki anders als Prometheus auf das Push-Verfahren setzt, ergibt sich
ein feiner Unterschied: Pro Instanz von Loki, die der Admin mit Logdaten
betanken möchte, benötigt er auf den Systemen eine eigene Promtail-Instanz. Ein
Tipp aus der Praxis sei hier deshalb gegeben: Die Skalierung von Loki in die
Breite erfolgt idealerweise auf allen Ebenen mit vorgeschaltetem Loadbalancer.
Sowohl der Distributor für Schreibvorgänge als auch das Query-Frontend für
Lesevorgänge lassen sich in mehreren parallelen Instanzen hinter einem HAProxy
oder einem anderen Loadbalancer gut betreiben. Dasselbe gilt für die Ingesters,
die Queriers und die Rulers – alle lassen sich in vielen parallelen Instanzen
betreiben, die aufeinander verweisen. Der im Hintergrund genutzte Speicher
sollte für alle Instanzen der verteilten Umgebung aber dieselben Dateien
enthalten, sonst laufen die basalen Loki-Funktionen ins Leere.
Loki aufsetzen
Es ist nicht kompliziert, einmal zu testen, ob Loki womöglich als Ersatz für Ihr
ELK-Setup taugt. Schon gar nicht, wenn Sie im ersten Wurf mit den
Standardeinstellungen zufrieden sind und sich nicht gleich ein an die eigenen
Bedürfnisse angepasstes
Setup basteln möchten. Des Rätsels Lösung sind Container: Im Docker-Hub finden
sich fertige Docker-Abbilder [2] für Loki, die sich auf aktuellen RHEL-Systemen
auch mit Podman nutzen lassen. Die Container enthalten sämtliche Komponenten,
die für den Loki-Betrieb notwendig sind, sodass ein lauffähiges Loki binnen
kürzester Zeit zur Verfügung steht. Schauen wir also auf die dafür notwendigen
Schritte.
Wollen Sie Loki wie in diesem Beispiel in Form von Containern betreiben,
brauchen Sie auf dem Host, auf dem die Software laufen soll, nicht viele
Vorkehrungen zu treffen. Es genügt, eine funktionale Container-Laufzeitumgebung
zu haben. Aktuell ist die eleganteste Methode dafür entweder ein Red Hat
Enterprise Linux 8.4 mitsamt seinem Podman-Interface, das zu Docker
binärkompatibel ist. Alternativ klappt das Setup auch mit Ubuntu 20.04 LTS, für
das Docker selbst sein docker-ce-Tool anbietet. Eine Anleitung, wie Sie
docker-ce auf Ubuntu 20.04 installieren, finden Sie in der offiziellen
Docker-Dokumentation [3]. Danach beziehen Sie das aktuelle Docker-Image mit
Loki. Der Befehl
docker pull grafana/loki
reicht auf Ubuntu aus. Unter Red Hat Enterprise Linux 8 nutzen Sie stattdessen:
podman pull docker.io/grafana/loki
Der nächste Schritt ist dann die Konfiguration des Diensts. Loki speichert seine
gesamte Konfiguration in einer einzelnen, lokalen Datei. Es empfiehlt sich,
diese Datei per "mount"-Direktive dynamisch in den Container einzubinden, damit
sie von außen modifizierbar bleibt. Legen Sie zu diesem Zweck auf dem Loki-Host
zunächst den Ordner "/srv/containers/loki" an und darin die beiden Unterordner
"etc" sowie "lib". Der "etc"-Ordner findet sich im Container später als
"/etc/loki" wieder, der "lib"-Ordner als "/loki".
Für unser Beispiel fehlt noch die Loki-Konfigurationsdatei. Eine zu unserem
Beispiel passende findet sich im Listing 1. Die Datei gehört auf dem Host als
"loki.conf" in den Ordner "/srv/containers/loki/etc", sodass Loki sie dort
später findet.
setzen Sie den Container in Gang (unter Ubuntu ersetzen Sie "podman" durch
"docker"). Anschließend überprüfen Sie mittels ss -tulpen, ob auf Port 3100
lokal Loki läuft. Ist das der Fall, ist der Dienst bereit für den Einsatz. Falls
der Port zwar geöffnet ist, Sie ihn aber nicht erreichen, müssen Sie noch den
Port 3100 in der Firewall des Systems freigeben.
Der Clou an der Container-Variante ist übrigens, dass Sie Loki mit dieser
Methode auch produktiv betreiben können. Das Deployment von Containern, das
Anlegen von Ordnern und das Konfigurieren von Systemd-Units lässt sich aus den
meisten Automatisierungswerkzeugen heraus leicht steuern. Wenn Sie Ihrem
Loki-Container also noch eine Systemd-Unit verpassen, können Sie Loki mit der
beschriebenen Methode auch für den echten Einsatz an den Start bringen. Wobei
Sie dann nochmal über das genutzte Speicher-Backend nachdenken sollten, denn
andernfalls würden Sie die Logs in Loki separat und überall dort lokal
speichern, wo eine Loki-Instanz läuft.
Bild 2: Hosts, auf denen Promtail läuft, wertet der Admin per Grafana und PromQL auf die Logfrequenz und die -menge aus.
Promtail konfigurieren
Nun haben Sie zwar ein laufendes Loki, doch ohne echte Logs im System kommen wir
noch nicht weit – es muss also Promtail her. Auch das lässt sich in Form eines
Containers betreiben und der Set-up-Prozess verläuft zu jenem von Loki sehr
ähnlich. Organisieren Sie sich zunächst auf allen Quellsystemen für Logs auf
Ubuntu mittels
docker pull grafana/promtail
oder unter Red Hat per
podman pull docker.io/grafana/promtail
die jeweils aktuellste Version des Containers mit Promtail.
Der Rest funktioniert wie bei Loki auch: Legen Sie den Ordner "/srv/containers/
promtail/" auf allen Systemen an, von denen Sie Logs einsammeln, und darin die
Unterordner "etc" und "lib". Sorgen Sie danach dafür, dass in "/srv/containers/
promtail/etc/" die Datei "promtail.yml" mit dem Inhalt aus Listing 2 liegt.
Dabei ersetzen Sie "LOKI_IP" durch die IP-Adresse Ihrer Loki-Instanz und
"HOSTNAME" durch den Hostnamen, auf dem die Promtail-Instanz läuft. Anschließend
starten Sie den Promtail-Container mit
podman run -d --name=promtail -v /var/log:/var/log -v
/srv/containers/promtail/etc:/etc/promtail:Z -v /srv/containers/promtail/lib:/
Auf Ubuntu ersetzen Sie erneut "podman" durch "docker". Danach fördert podman ps
oder docker ps eine laufende Promtail-Instanz zu Tage. Sollte das nicht der Fall
sein, lohnt es sich, die Permissions von "/srv/containers/loki" ebenso zu
überprüfen wie die UID des Containers. Je nach Distribution kann es auch
notwendig sein, den Container im "privileged"-Modus zu starten. Dafür sorgen
Sie, indem Sie dem Container-Aufruf noch ein "--privileged" vor der Angabe des
Ports hinzufügen.
Auch das Deployment von Promtail lässt sich automatisieren und per Puppet & Co.
gut abwickeln. Dabei sei allerdings auf einen Umstand hingewiesen, dass Promtail
das Senden von Ergebnissen stets in einem Thread erledigt. Zwar ist es also
möglich, mehrere Clients zu konfigurieren, doch fällt einer dieser Clients aus,
betrifft das auch alle anderen Loki-Instanzen. Die Promtail-Instanz schickt dann
im schlechtesten Fall gar keine Logs mehr nach irgendwo. Sollten Sie also
mehrere parallele Loki-Instanzen aus HA-Gründen zur selben Zeit mit Logs
betanken wollen, betreiben Sie auf dem Quellsystem mehrere Promtail-Instanzen
für die unterschiedlichen Loki-Ziele.
Grafana für die Visualisierung
Wenn Promtail Logs sammelt und an Loki sendet, bleibt nur noch eine Frage offen:
Wie visualisieren Sie die Logdateien? Die gute Nachricht ist: Grafana beherrscht
die Darstellung von Logs aus Loki mittlerweile problemlos. Konfigurieren Sie
Loki hierzu als Datenquelle in Grafana. Danach haben Sie die Möglichkeit, eigene
Queries für Grafana zu schreiben, um die Metrikdaten aus Loki auszulesen.
Loki hat für diese Zwecke eine eigene Query-Sprache implementiert, die sich
LogQL nennt und stark an PromQL von Prometheus angelehnt ist. Eine vollständige
Anleitung für LogQL liefert [4].
Loki und Kubernetes
Alle bisher beschriebenen Schritte zielen darauf ab, Loki als eigenständiges
Tool auf blankem Blech zu installieren. Wer Loki im Kontext von Kubernetes
nutzen möchte, braucht diesen Spagat aber so gar nicht zu vollziehen, denn Loki
ist darauf ausgelegt, perfekt mit Kubernetes zu harmonieren. Das gilt sowohl für
die Kubernetes-Nodes selbst, auf denen Loki sich ausrollen lässt, als auch für
die Anwendungen, die Nutzer in Kubernetes betreiben.
Um Kubernetes-Logs in Loki zu sammeln, installieren Sie in einem Cluster Loki
per Helm und holen sich Promtail gleich mit auf die Systeme. Letzteres ist ab
Werk so eingerichtet, dass es die Labels, die Kubernetes für die Konfiguration
von Pods nutzt, automatisch einsammelt. Anhand dieser Labels fällt es Ihnen im
Anschluss leichter, Dashboards in Grafana so zu konstruieren, dass sie Ihnen die
erwünschten Informationen schnellstmöglich präsentieren.
Und auch wer die Logs seiner in Kubernetes gehosteten Anwendungen als Nutzer mit
Loki zentral einsammeln möchte, greift unmittelbar auf die Kubernetes-API
zurück. Die Kubernetes-Dokumentation beschreibt diesen Vorgang ausführlich [5].
Fazit
Loki unterscheidet sich schon im Ansatz radikal von Wunschlos-Glücklich-Lösungen
wie ELK oder Splunk. Es ermöglicht keine Volltextsuche über sämtliche Logs einer
Applikation der vergangenen fünf Jahre, sondern ist eher ein mehrdimensionaler
"tail -f"-Befehl auf vielen Servern gleichzeitig. Das ist allerdings eher ein
Feature als fehlender Komfort, denn dadurch braucht Loki signifikant weniger
Ressourcen als die vollindizierende Konkurrenz. Obendrein ist Loki mit den
modernen Anwendungen der Gegenwart wie Systemd und Kubernetes bestens
integriert. Wer sich also über seine langsame ELK-Lizenz ärgert und für Splunk
nicht tief in die Tasche greifen möchte, sollte sich Loki genauer anschauen.