Podman Container Logs mit Fluent Bit, Postgres und TimescaleDB verarbeiten
Posted on So 10 Juli 2022 in Blog
Fluent Bit ist eine Open-Source-Software um Log-Dateien zu verarbeiten und zeichnet sich durch eine einfache Installation und Anwendung aus. Fluent Bit bietet eine hohe Flexibilität hinsichtlich Input und auch Output. In diesem Beitrag möchte ich zeigen, wie man mithilfe von Fluent Bit und Postgres Container-Logs von Podman verarbeiten und speichern kann.
Die Befehle für diesen Beitrag wurden unter Rocky Linux 8.5 getestet, aber ich denke, sie sollten auch auf anderen Derivaten ohne Probleme laufen.
Der Container, dessen Log-Outputs gespeichert werden soll, wird im rootless-Modus laufen. Als Benutzer für diesen Testlauf habe ich den Benutzer webapp verwendet, aber grundsätzlich ist jeder Benutzer möglich. Über Podman und die Möglichkeit, Container rootless laufen zu lassen, habe ich auch in einem anderen Beitrag etwas geschrieben: Container mit Podman
Inhalt:
Postgres
Wie könnte es auch anders sein, möchte ich die Log-Dateien der Container in einer Postgres-Datenbank weiterverarbeiten. Da es sich bei Log-Dateien um klassische Zeitreihendaten handelt, bietet es sich an, die Postgres-Erweiterung TimescaleDB zu nutzen.
Die Dokumentation gibt einen guten Überblick, welche Möglichkeiten es gibt, Postgres mit der Timescale Erweiterung laufen zu lassen: Installation TimescaleDB
Für dieses Beispiel habe ich mich entschieden, die Datenbank in einem Container laufen zu lassen.
podman run -d --name timescaledb -p 5432:5432 -e POSTGRES_PASSWORD=password timescale/timescaledb:latest-pg14
Um später die Daten für Fluent Bit zu speichern, werden wir auch den entsprechenden Benutzer und die Datenbank anlegen. Dafür verwende ich psql, aber man kann natürlich auch jeden anderen Postgres-Client verwenden:
-- Datenbankbenutzer anlegen
postgres=# create user fluentbit with encrypted password 'fluentbit';
CREATE ROLE
-- Datenbank für die Logdateien anlegen
postgres=# create database fluentbit;
CREATE DATABASE
-- in die neu erstelle Datenbank wechseln
postgres=# \c fluentbit
You are now connected to database "fluentbit" as user "postgres".
-- die Tabelle für die Logs erstellen
fluentbit=# create table fluentbit (tag text, time timestamp without time zone, data jsonb);
-- TimescaleDB mitteilen, welche Tabelle eine Zeitreihentabelle ist
fluentbit=# SELECT create_hypertable('fluentbit', 'time');
-- und dem fluentbit Benutzer noch die Rechte geben, um die Datenbank zu nutzen
fluentbit=# grant select, insert on table fluentbit to fluentbit;
Die Tabellenstruktur für den Fluent Bit Log-Output habe ich der Dokumentation entnommen: Fluent Bit PostgreSQL Output
Durch den create_hypertable erstellt TimescaleDB automatische Partitionen der Daten. Siehe dazu auch: Create hypertable
Fluent Bit Installation
Die Installation von Fluent Bit ist sehr simpel und auch sehr gut dokumentiert: https://docs.fluentbit.io/manual/installation/linux/redhat-centos#install-on-redhat-centos
Wenn man diesen Schritten folgt, dann sollte sich Fluent Bit auf Rocky Linux und ähnlichen Plattformen ohne Probleme installieren lassen.
Der Konfiguration von Fluent Bit widmen wir uns in einem nächsten Schritt: Fluent Bit Konfiguration
Testanwendung
Als Testanwendung verwenden wir einfach einen Nginx-Container.
Daher habe ich mich als webapp
-Benutzer am System angemeldet und die folgenden Befehle werden als ebendieser
Benutzer ausgeführt.
In den Container kopieren wir dann einfach eine simple HTML-Datei und schon ist unser "Webanwendung" fertig.
[webapp@rockylinux]$ mkdir webapp
[webapp@rockylinux]$ tee webapp/index.html <<EOL
> <html>
> <head>
> <title>Postgres, Timescale und Fluent Bit</title>
> </head>
> <body>
> <h1>Meine Webapp</h1>
> </body>
> </html>
> EOL
[webapp@rockylinux]$ podman run --name nginx -v /home/webapp/webapp:/usr/share/nginx/html:z -p 8080:80 --log-driver='k8s-file' --log-opt path=/tmp/webapp.json -d nginx
Beim Befehl podman run
hat man die Möglichkeit Log-Optionen zu setzen.
Einerseits wurde hier mittels --log-driver
der verwendete Log-Typ angegeben und
andrerseits über --log-opt
path der Speicherort der Log-Datei angeben
(Natürlich ist der /tmp
prinzipiell ein ungeeigneter Ort, um Log-Dateien abzulegen und
wurde hier nur zu Demonstrationszwecke verwendet, um sich eine entsprechende Konfiguration der Rechte
in /var/log
zu sparen ;-).
Fluent Bit Konfiguration
Um später auf die Postgres-Datenbank zugreifen zu können, muss in /root
die Datei
.pgpass
mit den entsprechenden Verbindungsparametern gespeichert werden. Dadurch braucht man dann in der
Fluent Bit Konfiguration selbst kein Passwort angeben.
Der Inhalt von .pgpass
ist dann wie folgt:
localhost:5432:fluentbit:fluentbit:fluentbit
Damit die Datei auch gelesen werden kann, müssen die Berechtigungen noch entsprechend gesetzt werden:
chmod 600 .pgpass
Nachdem die Testanwendung läuft, muss man Fluent Bit "nur" noch mitteilen, wo die Log-Datei gefunden werden kann und um welche Art von Log-Datei es sich handelt. Einerseits müssen der Input (Log-Datei unsere Webanwendung) und andrerseits der Output (unsere Postgres-Datenbank) definiert werden.
Hierfür wird nun die Datei /etc/fluent-bit/fluent-bit.conf
bearbeitet:
[INPUT]
Name tail
Path /tmp/webapp.json
Parser cri
Tag webapp
Mem_Buf_Limit 5MB
Skip_Long_Lines On
[OUTPUT]
Name pgsql
Match *
Host localhost
Port 5432
User fluentbit
Database fluentbit
Table fluentbit
Timestamp_Key ts
Im ersten Teil wird der Input definiert. Hier wird angegeben, wo sich die zu lesende Log-Datei befindet, welcher Parser verwendet werden soll und welche Bezeichnung (Tag) die Log-Dateien in der Datenbank dann auffindbar machen sollen. Für den Podman-Container wird der CRI (Container Runtime Interface)-Parser verwendet. Beispiel hierfür findet sich im Kubernetes-Teil von Fluentbit: Container Runtime Interface (CRI) parser
Eine Alternative zum CRI-Parser wäre der docker-Parser, der im Prinzip einfach den JSON-Output weitergibt. Die Unterschiede sind jetzt auch nicht sehr gravierend, wie nachfolgendes Beispiel der Nginx-Outputs, einmal mit dem CRI-Parser und einmal mit dem docker-Parser, zeigt.
-- cri-parser
webapp | 2022-07-10 13:47:21.786909 | {"ts": 1657460841.786909, "logtag": "F", "stream": "stdout", "message": "10.0.2.100 - - [10/Jul/2022:13:47:21 +0000] \"GET / HTTP/1.1\" 200 117 \"-\" \"curl/7.61.1\" \"-\""}
-- docker-parser
webapp | 2022-07-10 13:58:41.912788 | {"ts": 1657461521.912788, "log": "2022-07-10T13:58:41.912651048+00:00 stdout F 10.0.2.100 - - [10/Jul/2022:13:58:41 +0000] \"GET / HTTP/1.1\" 200 117 \"-\" \"curl/7.61.1\" \"-\""}
Im Output-Bereich werden nun die Verbindungsparameter unserer Datenbank angegeben. Ein Passwort muss nicht
angegeben werden. Dafür sorgt die .pgpass
-Datei, die wir erstellt haben.
Mehr Informationen zu Postgres als Fluent Bit Output findet man in der
Dokumentation
Nachdem die Konfiguration bearbeitet wurde, sollte auch noch das Fluent Bit Service (neu) gestartet werden.
Analyse der Daten
Eine Stärke von TimescaleDB sind die zusätzlichen Funktionen, die einfach per "normalem“ Postgres-Interface
genutzt werden können.
Die time_bucket Funktion
kann dazu genutzt werden, beispielsweise die Daten für jegliche Art der Visualisierung in gleich große Zeiträume einzuteilen.
Im beruflichen Umfeld nutze ich Grafana oder
Apache Superset,
um auf die Daten zuzugreifen und dabei ist time_bucket
eine mehr als nützliche Funktion.
ZUsätzlich bietet TimescaleDB auch noch Funktionen, die die Erstellung einer Data Retention Policy ermöglichen oder eine Kompression der Daten.
Fazit
Ich finde die Möglichkeiten, die Fluent Bit bietet, um Log-Dateien von Podman zentral abzuspeichern, sehr gut. Auch das Zusammenspiel mit TimescaleDB zeigt auch bei der Visualisierung der Daten große Stärken.
Und durch andere bekannte Erweiterungen aus dem Postgres-Umfeld, beispielsweise Postgis, kann man umfangreiche Analysen machen.