5
(1)

Logging mit Grafana Alloy und Loki: Zentrale Log-Verwaltung für Raspberry Pi

Erstellt / aktualisiert

wichtige Informationen...

Affiliate - Offenlegung

Auf meiner Seite verwende ich sogenannte Affiliate-Links, diese sind mit einem gekennzeichnet, damit du diese auch direkt erkennen kannst.
Sobald du über so einen Link das Produkt kaufen würdest, erhalte ich möglicherweise eine Provision vom jeweiligen Anbieter. Außerdem entstehen für Dich natürlich keine zusätzlichen Kosten!
Mich unterstützt du damit aber enorm und trägst dazu bei, dass es auch in Zukunft weitere Guides und Vorstellungen von mir hier geben wird.

Ich empfehle nur Tools / PlugIns / Anbieter / Produkte, hinter denen ich auch wirklich stehe, bzw. bei denen ich auch einen Mehrwert sehe.

DarkWolfCave.de ist Teilnehmer des Amazon-Partnerprogramms, das zur Bereitstellung eines Mediums für Webseiten konzipiert wurde, mittels dessen durch die Platzierung von Partner-Links zu Amazon.de Entgelte verdient werden können.


ACHTUNG! Bitte lesen!

Du benutzt das hier Gezeigte natürlich, wie immer, auf eigenes Risiko!
Ich habe alles selbst durchgeführt und mir mein System nicht zerschossen oder sonst irgendwelche negativen Auffälligkeiten bemerkt.

Aber dennoch… Backups sind immer gut….
Für WordPress-Backups am besten mit UpdraftPlus

Ich übernehme keine Haftung für Schäden jeglicher Art am System, der Hardware oder der Katze…. :-P


DarkWolfCave.de

Inhaltsverzeichnis

Effizientes Logging mit Grafana Alloy: Die optimale Lösung für Raspberry Pi

Logging mit Grafana Alloy bietet ein ressourcenoptimiertes Überwachungssystem speziell für eine Raspberry Pi Umgebungen.
Diese technische Kombination aus Loki als Backend und Alloy als Sammler ermöglicht eine strukturierte Erfassung aller relevanten Systemlogs durch selektive Metadaten-Indizierung anstelle speicherhungriger Volltext-Indexierung.
Das Ergebnis: Eine performante Log-Analyse bei minimalem RAM- und CPU-Verbrauch – entscheidend für ressourcenbeschränkte Systeme. Die vorliegende Anleitung führt dich systematisch durch die komplette Implementierung mittels Docker-Container, von der Grundinstallation über die Konfiguration der Erfassungsquellen bis zum praktischen Dashboard-Setup für das tägliche Monitoring.

DarkWolfCave.de

Logging mit Grafana Alloy und Loki

Ein zentrales Logging-System ist für jedes Homelab eine kritische Komponente zur Fehlerdiagnose und Systemüberwachung.
In dieser Anleitung zeige ich dir die Implementierung eines ressourceneffizienten Logging-Systems auf Basis von Grafana Loki und dem Alloy Agent für Raspberry Pi. Wie üblich werde ich alles in Docker-Containern bereitstellen.

Technische Komponenten im Überblick:

  • Grafana Loki: Ein horizontal skalierbares Log-Aggregationssystem, das Metadaten (Labels) statt Volltextindizes nutzt und dadurch minimale Ressourcen verbraucht
  • Grafana Alloy Agent: Der moderne Nachfolger von Promtail, konzipiert für effiziente Log-Sammlung aus diversen Quellen
  • Docker & Docker Compose: Für die Containerisierung und vereinfachte Verwaltung der Dienste
  • Traefik: Als optionaler Reverse Proxy für die zentrale Zugriffsverwaltung – sehr hilfreich, um sich nicht immer alle Ports für die jeweilige Anwendung merken zu müssen.

Vorteile dieser Logging-Lösung:

  • leicht erweiterbar für unter anderem Docker-Container, diverse Anwendungslogs und Netzwerkgeräte
  • Optimiert für ressourcenbeschränkte Systeme wie Raspberry Pi
  • Erfassung und Zentralisierung aller Systemlogs (systemd, Paketmanager, Anwendungen)
  • Leistungsfähige Abfrage- und Filtermöglichkeiten durch Grafana
DarkWolfCave - Logging mit Grafana Alloy - Dashboard

Systemvoraussetzungen für Logging mit Grafana Alloy

Für die erfolgreiche Implementierung dieses Logging-Systems benötigst du:

Hardware:

  • Raspberry Pi 4 mit mindestens 2 GB RAM (4 GB+ empfohlen für umfangreichere Logging-Anforderungen)
  • Mindestens 16 GB SD-Karte, besser 32 GB+ für längere Log-Aufbewahrung (am besten eine SSD)
  • Stabiles Netzteil mit 5V/3A

Software:

  • Raspberry Pi OS 64-Bit (Bullseye oder neuer) oder kompatible Linux-Distribution
  • SSH-Zugriff auf den Raspberry Pi
  • Internetverbindung für Container-Downloads

Erforderliche Kenntnisse:

  • Grundlegende Linux-Befehle und Terminal-Nutzung
  • Einfaches Verständnis für Docker-Konzepte
  • Grundkenntnisse in Netzwerkkonfiguration

Optionale Komponenten:

  • Pi-hole für lokale DNS-Auflösung (Alternative zu Host-Datei-Anpassungen)
  • Bestehender Reverse Proxy (falls vorhanden)
DarkWolfCave - Raspberry Pi

Auf dieser Hardware laufen meine Umgebungen

Bei mir gibt es mehrere sogenannte »Umgebungen«, die ich benutze.
Zum einen meine »Live« oder auch »Produktion« Umgebung, auf der alles läuft, was ich in meinem Netzwerk so benötige.
Dann gibt es noch Umgebungen für unterschiedliche Szenarien: ein Labor (LAB), eine Entwickler (DEV) und eine zum finalen Testen (UAT).

Hardwaretechnisch sind aber alle fast gleich ausgestattet, da ich mit diesen Kombinationen bisher nie Probleme hatte.
Lediglich setzt meine neue Live-Umgebung erstmalig auf eine NVMe-SSD.

Werbung

Affiliate – Links

DarkWolfCave.de ist Teilnehmer des Amazon-Partnerprogramm, das zur Bereitstellung eines Mediums für Webseiten konzipiert wurde, mittels dessen durch die Platzierung von Partner-Links zu Amazon.de Entgelte verdient werden können.

Werbung

Affiliate – Links

DarkWolfCave.de ist Teilnehmer des Amazon-Partnerprogramm, das zur Bereitstellung eines Mediums für Webseiten konzipiert wurde, mittels dessen durch die Platzierung von Partner-Links zu Amazon.de Entgelte verdient werden können.

Grundinstallation: Docker und Docker Compose

Falls Docker bisher nicht auf deinem Raspberry Pi installiert ist, hier eine grobe Anleitung:
Oder schaue dir den entsprechenden Artikel von mir dazu an.

Docker installieren

# System-Pakete aktualisieren
sudo apt update
sudo apt upgrade -y

# Docker installieren
curl -sSL https://get.docker.com | sh

# Deinen Benutzer zur Docker-Gruppe hinzufügen
sudo usermod -aG docker $USER

# Einmal die Gruppenrichtlinien neu starten
newgrp docker

Docker Compose installieren

# Die neueste Version von Docker Compose herunterladen
sudo apt-get install -y docker-compose-plugin

# Überprüfen, ob Docker Compose korrekt installiert wurde
docker compose version

Traefik – Was ist ein Reverse Proxy und wofür benötigen wir ihn?

Ein Reverse Proxy ist ein Server, der Anfragen von Clients entgegennimmt und an die entsprechenden Backend-Server weiterleitet.
In meinem Setup verwende ich Traefik als Reverse Proxy aus folgenden Gründen:

  1. Vereinfachter Zugriff: Du kannst über einen Domainnamen (z.B. loki.local) auf deine Dienste zugreifen, statt über IP-Adressen und Ports.
  2. Zentrales Routing: Alle deine Dienste können über einen einzigen Einstiegspunkt erreichbar sein.
  3. Automatische SSL-Verschlüsselung: Traefik kann automatisch Let’s Encrypt-Zertifikate für deine Dienste verwalten. (was aber in einem lokalen Netzwerk eher unnötig und auch nicht ganz so einfach einzurichten ist.)
  4. Load Balancing: Bei mehreren Instanzen eines Dienstes kann Traefik die Last verteilen. (aber eher bei einem Kubernetes Setup oder Docker Swarm interessant)

Traefik als Reverse Proxy einrichten

Wenn du bereits einen anderen Reverse Proxy (wie Nginx oder HAProxy) verwendest, kannst du diesen Abschnitt überspringen und deine Dienste entsprechend konfigurieren. Ich erkläre dir grob, wie du Traefik als Docker Container einrichten kannst. Weitere Informationen findest du in einem ausführlichen Artikel von mir.

Erstelle ein Verzeichnis für Traefik:

mkdir -p ~/docker/traefik/config
cd ~/docker/traefik

Erstelle eine docker-compose.yml für Traefik:

nano docker-compose.yml

Füge folgenden Inhalt ein:

services:
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"      # HTTP
      - "8080:8080"  # Traefik Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro # Docker-Socket für Container-Erkennung
      - ./config/traefik.yml:/etc/traefik/traefik.yml:ro # Hauptkonfiguration
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      # Dashboard lokal verfügbar machen
      - "traefik.http.routers.dashboard.rule=Host(`traefik.local`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.entrypoints=web"

networks:
  traefik_network:
    name: traefik_network

Erstelle die Traefik-Konfigurationsdatei:

cd config
nano traefik.yml

Füge folgenden Inhalt ein:

# Globale Konfiguration
global:
  checkNewVersion: true
  sendAnonymousUsage: false

# Log-Konfiguration
log:
  level: INFO
  # Für detailliertere Logs während der Einrichtung: level: DEBUG

# Traefik API und Dashboard aktivieren
api:
  dashboard: true
  insecure: true  # Im lokalen Netzwerk akzeptabel

# EntryPoints konfigurieren (Zugangspunkte für Anfragen)
entryPoints:
  web:
    address: ":80"

# Provider konfigurieren
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false  # Container müssen explizit per Label aktiviert werden
    network: traefik_network

Starte Traefik:

cd ..
docker compose up -d

DNS-Konfiguration für Traefik und Applikationen

Für den Zugriff auf die Applikationen über Hostnamen statt IP-Adressen stehen unter anderem zwei Methoden zur Verfügung:

Methode 1: Hosts-Datei anpassen

Diese Methode erfordert die Anpassung der Hosts-Datei auf jedem Client-Gerät, von dem aus du auf die Logging-Dienste zugreifen möchtest:

Für Windows:

  1. Öffne Notepad als Administrator
  2. Öffne die Datei C:\Windows\System32\drivers\etc\hosts
  3. Füge folgende Zeilen hinzu (ersetze 192.168.1.100 durch die IP-Adresse deines Raspberry Pi)
192.168.1.100 traefik.local
192.168.1.100 loki.local
192.168.1.100 alloy.local
192.168.1.100 grafana.local
  1. Speichere die Datei

Für Linux/macOS:

sudo nano /etc/hosts

Füge die gleichen Einträge wie oben hinzu und speichere die Datei.

Methode 2: Pi-hole für zentrale DNS-Verwaltung (Empfohlen)

Pi-hole bietet eine zentralisierte Möglichkeit, lokale DNS-Einträge für alle Netzwerkgeräte zu verwalten:

  1. Öffne das Pi-hole Admin-Dashboard (typischerweise http://pi.hole/admin)
  2. Navigiere zu „Local DNS“ > „DNS Records“
  3. Füge folgende Einträge hinzu:
    • Domain: traefik.local → IP: <Raspberry Pi IP>
    • Domain: loki.local → IP: <Raspberry Pi IP>
    • Domain: alloy.local → IP: <Raspberry Pi IP>
    • Domain: grafana.local → IP: <Raspberry Pi IP>

Vorteile der Pi-hole-Methode:

  • Einmalige zentrale Konfiguration
  • Automatische Namensauflösung für alle Netzwerkgeräte
  • Kombination mit Werbeblockierung und weiteren DNS-Funktionen

Die Pi-hole-Methode ist besonders für Heimnetzwerke mit mehreren Geräten zu empfehlen, während die Hosts-Datei-Methode für einzelne Testsysteme ausreichend ist.

Installation und Konfiguration von Grafana

Grafana dient als Visualisierungsplattform für unser Logging-System mit Alloy und Loki. Die folgende Anleitung beschreibt die Docker-basierte Installation:

Verzeichnisstruktur anlegen

mkdir -p ~/docker/grafana/data
cd ~/docker/grafana

Docker Compose Konfiguration erstellen

nano docker-compose.yml

Füge folgenden Inhalt ein:

services:
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    user: "1000"  # Anpassen an die UID des eigenen Benutzers, ggf. mit 'id -u' ermitteln
    environment:
      - GF_SECURITY_ALLOW_EMBEDDING=true
      - GF_AUTH_ANONYMOUS_ENABLED=false
    volumes:
      - ./data:/var/lib/grafana
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.grafana.rule=Host(`grafana.local`)"
      - "traefik.http.routers.grafana.entrypoints=web"
      - "traefik.http.services.grafana.loadbalancer.server.port=3000"
networks:
  traefik_network:
    external: true

Grafana starten und verifizieren

docker compose up -d
docker logs grafana

Überprüfe die Logs auf Fehlermeldungen. Bei erfolgreicher Installation und den notwendigen Einträgen in Pi-hole oder der Hosts-Datei sollte Grafana unter http://grafana.local erreichbar sein.

Erstanmeldung und Passwort ändern

  1. Öffne http://grafana.local im Browser
  2. Melde dich mit den Standard-Zugangsdaten an:
    • Benutzername: admin
    • Passwort: admin
  3. Ändere bei Aufforderung das Standardpasswort in ein sicheres Passwort
  4. Notiere das neue Passwort an einem sicheren Ort

Du wirst hier einen groben Überblick finden.
Allerdings biete ich dir auch noch etwas mehr Support an:

  • Du benötigst persönlichen Support
  • Du möchtest von Beginn an Unterstützung bei deinem Projekt
  • Du möchtest ein hier vorgestelltes Plugin durch mich installieren und einrichten lassen
  • Du würdest gerne ein von mir erstelltes Script etwas mehr an deine Bedürfnisse anpassen

Für diese Punkte und noch einiges mehr habe ich einen limitierten
VIP-Patreon Tarif
eingerichtet. Falls er dir dort zurzeit nicht angeboten wird,
kontaktiere mich bitte über Discord und wir finden eine Lösung!

Installation von Loki und Alloy

Nach der erfolgreichen Einrichtung von Traefik und Grafana folgt nun die Installation der zentralen Logging-Komponenten Loki und Alloy.

Verzeichnisstruktur erstellen

Erstelle ein dediziertes Verzeichnis für das Logging-Setup:

mkdir -p ~/docker/logging/
cd ~/docker/logging

Konfigurationsdateien erstellen

Wir erstellen nun die drei erforderlichen Konfigurationsdateien, und ich erkläre dir ein paar Details dazu.

Docker Compose für Loki und Alloy

Erstelle die Docker Compose-Datei:

nano docker-compose.yml

Mit diesem Inhalt haben wir direkt Loki und Alloy in einer Compose-Datei:

services:
  loki:
    image: grafana/loki:latest
    container_name: loki_traefik
    restart: unless-stopped
    volumes:
      - ./loki-config.yml:/etc/loki/loki-config.yml
      - loki-data:/loki
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.loki.rule=Host(`loki.local`)"
      - "traefik.http.routers.loki.entrypoints=web"
      - "traefik.http.services.loki.loadbalancer.server.port=3100"

  alloy:
    image: grafana/alloy:latest
    container_name: alloy_traefik
    restart: unless-stopped
    environment:
      - ALLOY_CONFIG=/etc/alloy/config.alloy
      - HOSTNAME=${HOSTNAME:-raspberrypi}  # Verwendet Systemhostnamen oder Fallback
    volumes:
      - ./alloy-config.yml:/etc/alloy/config.alloy
      - /var/log:/var/log:ro
      - /var/log/journal:/var/log/journal:ro
      - /var/log/unifi:/var/log/unifi:ro
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.alloy.rule=Host(`alloy.local`)"
      - "traefik.http.routers.alloy.entrypoints=web"
      - "traefik.http.services.alloy.loadbalancer.server.port=12345"
    command: >
      run
      --server.http.listen-addr=0.0.0.0:12345
      --storage.path=/var/lib/alloy/data
      /etc/alloy/config.alloy

networks:
  traefik_network:
    external: true

volumes:
  loki-data:
    driver: local 

Erklärung der Docker Compose-Datei:

Loki Service

  • image: grafana/loki:latest:
    Setzt auf das offizielle Loki-Image von Grafana, das stets aktuell gehalten wird. Dies gewährleistet die neuesten Funktionen und Sicherheitsupdates.
  • restart: unless-stopped:
    Dieser Parameter sorgt dafür, dass der Container automatisch neu startet, es sei denn, er wird manuell gestoppt. Dadurch wird die Betriebszeit maximiert und ungewollte Unterbrechungen werden minimiert.
  • volumes:
    • Hier werden die Konfigurationsdateien in den Container gemountet.
    • Zudem speichert es Loki-Daten in einem benannten Volume, was die Persistenz der Daten gewährleistet, auch wenn der Container neu gestartet wird.
  • networks:
    Loki wird mit dem Traefik-Netzwerk verbunden, was eine reibungslose Integration in eine vorhandene Netzwerkarchitektur ermöglicht.
  • labels:
    • Ermöglicht es Traefik, den Container zu erkennen und nahtlos zu integrieren.
    • Routing-Regeln sind so konfiguriert, dass sie basierend auf dem Hostnamen loki.local funktionieren.
    • Der interne Port ist auf 3100 festgelegt, um sicherzustellen, dass Anfragen korrekt geroutet werden.

Alloy Service

  • image: grafana/alloy:latest:
    Nutzt das neueste offizielle Image für Alloy, um sicherzustellen, dass alle aktuellen Features verfügbar sind.
  • environment:
    • ALLOY_CONFIG: Gibt den Pfad zur Konfigurationsdatei im Container an, was die Anpassung der Konfiguration vereinfacht.
    • HOSTNAME: Setzt den Hostnamen für die Vergabe von Labels aus einer Systemvariablen. Sollte diese nicht funktionieren, greift die Fallbacklösung (ändere „raspberrypi“ zu deinem Wunsch-Namen).
  • volumes:
    • Die Konfigurationsdatei wird gemountet, was dynamische Änderungen erleichtert.
    • Log-Verzeichnisse werden im read-only Modus gemountet, um sicherzustellen, dass Logs nicht unbeabsichtigt geändert werden können.
  • command:
    Spezifiziert den Startbefehl für Alloy, der sowohl einen HTTP-Server betreibt als auch die Datenspeicherung initiiert.
  • Netzwerke:
    Der Container nutzt ein bereits vorhandenes Netzwerk mit dem Namen traefik_network, wodurch die Konnektivität optimiert wird.
  • Volumes:
    Definiert ein benanntes Volume loki-data zur Sicherstellung der Persistenz.

Loki-Konfiguration

Erstelle die Loki-Konfigurationsdatei:

nano loki-config.yml

Füge folgenden Inhalt ein:

auth_enabled: false

server:
  http_listen_port: 3100
  log_level: info

schema_config:
  configs:
    - from: 2023-01-01
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /loki/index
    cache_location: /loki/cache
    shared_store: filesystem
    cache_ttl: 24h

compactor:
  working_directory: /loki/compactor
  shared_store: filesystem

limits_config:
  retention_period: 7d  # 7 Tage Aufbewahrung, anpassen nach Speicherbedarf
  ingestion_rate_mb: 4
  ingestion_burst_size_mb: 6

chunk_store_config:
  max_look_back_period: 168h  # Entspricht 7 Tagen

table_manager:
  retention_deletes_enabled: true
  retention_period: 168h

Erklärung der Loki-Konfigurationsdatei

Allgemein 

  • auth_enabled: false – Authentifizierung ist deaktiviert, das heißt, jeder mit Netzwerkzugriff auf Loki kann Daten abfragen oder speichern. Im produktiven Einsatz könnte es sinnvoll sein, die Authentifizierung zu aktivieren.
  • server:
    • http_listen_port: 3100 – Lokis Standard-Port, auf dem es HTTP-Anfragen entgegennimmt. Dies sollte in der Firewall berücksichtigt werden.
    • log_level: info – Legt die Log-Stufe fest. „Info“ bedeutet, dass normale Betriebs-Logs erfasst werden.

Schema-Konfiguration 

  • schema_config:
    • configs: Definiert, wie und wo Logs gespeichert werden, beginnend ab dem 1. Januar 2023.
      • store: boltdb-shipper – Ein eingebauter Index-Store, der die Verwaltung von Logs vereinfacht.
      • object_store: filesystem – Die Protokolldaten werden im Dateisystem gespeichert.
      • schema: v11 – Version des Schemas, sorgt für Kompatibilität und Performance.
      • index: Definition der Namenskonvention und Aufbewahrungsdauer für Indexe.

Speicherkonfiguration 

  • storage_config:
    • boltdb_shipper: Die Verzeichnisorte für aktiven Index und Cache sind /loki/index und /loki/cache.

Compactor

  • compactor:
    • working_directory: Gibt an, wo der Compactor temporäre Daten speichert, hier /loki/compactor.
    • shared_store: Hier ebenfalls filesystem, es speichert kompaktierte Chunks.

Limits-Konfiguration 

  • limits_config:
    • retention_period: 7d – Logs werden für 7 Tage aufbewahrt. Dies spielt in die Ressourcennutzung hinein.
    • ingestion_rate_mb und ingestion_burst_size_mb: Bestimmen die Eingaberatenlimits für Logs.

Chunk-Store-Konfiguration 

  • max_look_back_period: 168h – Entspricht 7 Tagen, und gibt die maximale Rückschau auf Logs an.

Table-Manager 

  • table_manager:
    • retention_deletes_enabled: true – Aktive Bereinigung basierend auf der Aufbewahrung.
    • retention_period: 168h – Entspricht wiederum 7 Tagen und kontrolliert die Aufbewahrung.

Diese Konfiguration ist optimiert für den Betrieb auf einem Raspberry Pi mit begrenzten Ressourcen.
Sie verwendet das Dateisystem als Speicher und behält Logs für eine Woche.

Alloy-Konfiguration

Erstelle die Alloy-Konfigurationsdatei:

nano alloy-config.yml

Füge den Inhalt der bereitgestellten alloy-config.yml ein:

# Systemd Journal Sammlung
discovery.relabel "systemd_journal" {
    targets = []
    rule {
        source_labels = ["__journal__systemd_unit"]
        target_label  = "unit"
    }
    rule {
        source_labels = ["__journal__hostname"]
        target_label  = "hostname"
    }
    rule {
        source_labels = ["__journal__transport"]
        target_label  = "transport"
    }
    rule {
        source_labels = ["__journal_priority_keyword"]
        target_label  = "level"
    }
}

loki.source.journal "systemd_journal" {
    max_age       = "12h0m0s"
    path          = "/var/log/journal"
    relabel_rules = discovery.relabel.systemd_journal.rules
    forward_to    = [loki.write.grafana_loki.receiver]
    labels        = {
        job  = "systemd",
        log  = "journal",
    }
}

# Paket-Management-Logs
local.file_match "package" {
  path_targets = [
    {"__path__" = "/var/log/dpkg.log", "log" = "dpkg"},
    {"__path__" = "/var/log/apt/history.log", "log" = "apt_history"},
    {"__path__" = "/var/log/apt/term.log", "log" = "apt_term"},
    ]
  sync_period = "10s"
}

loki.source.file "package" {
  targets    = local.file_match.package.targets
  forward_to = [loki.process.error_detector.receiver]
  tail_from_end = true
}

# Fehlererkennungs-Prozessor
loki.process "error_detector" {
  stage.regex {
    expression = "^(?P<log_level>ERROR|INFO|WARN|DEBUG).*"
  }
  stage.labels {
    values = {
      "level" = "log_level",
    }
  }
  forward_to = [loki.relabel.add_labels.receiver]
}

# Label-Hinzufügung
loki.relabel "add_labels" {
  forward_to = [loki.write.package.receiver]
  rule {
    target_label = "hostname"
    replacement = sys.env("HOSTNAME")
  }
  rule {
    target_label = "job"
    replacement = "package"
  }
}

# UniFi-Logs (optional - entfernen, wenn kein UniFi-Controller vorhanden)
local.file_match "unifi" {
  path_targets = [
    {"__path__" = "/var/log/unifi/access.log", "log" = "unifi_access"},
    {"__path__" = "/var/log/unifi/tasks.log", "log" = "unifi_tasks"},
    {"__path__" = "/var/log/unifi/mongod.log", "log" = "unifi_mongod"},
    {"__path__" = "/var/log/unifi_package.log", "log" = "unifi_package"},
    ]
  sync_period = "10s"
}

loki.source.file "unifi" {
  targets    = local.file_match.unifi.targets
  forward_to = [loki.relabel.unifi_add_labels.receiver]
  tail_from_end = true
}

loki.relabel "unifi_add_labels" {
  forward_to = [loki.write.unifi.receiver]
  rule {
    target_label = "hostname"
    replacement = sys.env("HOSTNAME")
  }
  rule {
    target_label = "job"
    replacement = "unifi"
  }
}

# Loki-Writer-Konfigurationen
loki.write "unifi" {
  endpoint {
    url = "http://loki_traefik:3100/loki/api/v1/push"
  }
}

loki.write "package" {
  endpoint {
    url = "http://loki_traefik:3100/loki/api/v1/push"
  }
}

loki.write "grafana_loki" {
  endpoint {
    url = "http://loki_traefik:3100/loki/api/v1/push"
  }
}

Erklärung der Alloy-Konfigurationsdatei:

Die Alloy-Konfiguration ist umfangreicher und gliedert sich in mehrere Bereiche:

Systemd Journal Sammlung:

   discovery.relabel "systemd_journal" {
       targets = []

       rule {
           source_labels = ["__journal__systemd_unit"]
           target_label  = "unit"
       }

       rule {
           source_labels = ["__journal__hostname"]
           target_label  = "hostname"
       }

       rule {
           source_labels = ["__journal__transport"]
           target_label  = "transport"
       }

       rule {
           source_labels = ["__journal_priority_keyword"]
           target_label  = "level"
       }
   }

   loki.source.journal "systemd_journal" {
       max_age       = "12h0m0s"
       path          = "/var/log/journal"
       relabel_rules = discovery.relabel.systemd_journal.rules
       forward_to    = [loki.write.grafana_loki.receiver]
       labels        = {
           job  = "systemd",
           log  = "journal",
       }
   }

Dieser Abschnitt konfiguriert das Sammeln von Logs aus dem systemd-Journal:

  • discovery.relabel: Definiert Regeln zum Umbenennen von Labels aus dem Journal.
  • loki.source.journal: Konfiguriert die Journal-Quelle:
    • max_age: Sammelt nur Logs der letzten 12 Stunden.
    • path: Pfad zum Journal-Verzeichnis.
    • relabel_rules: Verwendet die oben definierten Regeln.
    • forward_to: Sendet die Logs an den definierten Empfänger.
    • labels: Fügt zusätzliche Labels hinzu (job=systemd, log=journal).

Paket-Management-Logs:

   local.file_match "package" {
     path_targets = [
       {"__path__" = "/var/log/dpkg.log", "log" = "dpkg"},
       {"__path__" = "/var/log/apt/history.log", "log" = "history"},
       {"__path__" = "/var/log/apt/term.log", "log" = "term"},
       ]
     sync_period = "10s"
   }

   loki.source.file "package" {
     targets    = local.file_match.package.targets
     forward_to = [loki.process.error_detector.receiver]
     tail_from_end = true
   }

Dieser Abschnitt konfiguriert das Sammeln von Paketmanagement-Logs:

  • local.file_match: Definiert Datei-Pfade für Paket-Logs (dpkg, apt).
  • loki.source.file: Konfiguriert die Datei-Quelle:
    • targets: Verwendet die oben definierten Ziele.
    • forward_to: Sendet die Logs zur Fehlerverarbeitung.
    • tail_from_end: Beginnt am Ende der Datei mit dem Lesen.

Fehlererkennungs-Prozessor:

   loki.process "error_detector" {
     stage.regex {
       expression = "^(?P<log_level>ERROR|INFO).*"
     }

     stage.labels {
       values = {
         "level" = "log_level",
       }
     }

     forward_to = [loki.relabel.add_labels.receiver]
   }

Dieser Prozessor erkennt Fehlermeldungen:

  • stage.regex: Extrahiert das Log-Level (ERROR oder INFO) mit einem regulären Ausdruck.
  • stage.labels: Fügt das extrahierte Log-Level als Label hinzu.
  • forward_to: Leitet die verarbeiteten Logs zur Label-Hinzufügung weiter.

Label-Hinzufügung:

   loki.relabel "add_labels" {
     forward_to = [loki.write.package.receiver]

     rule {
       target_label = "hostname"
       replacement = sys.env("HOSTNAME")
     }

     rule {
       target_label = "job"
       replacement = "package"
     }
   }

Dieser Abschnitt fügt weitere Labels hinzu:

  • target_label = "hostname": Setzt den Hostnamen aus der Umgebungsvariable.
  • target_label = "job": Setzt das Job-Label auf „package“.

UniFi-Logs-Sammlung: (nur für Unifi Besitzer interessant, bei denen die Controller-Software auf dem Raspberry läuft)

   local.file_match "unifi" {
     path_targets = [
       {"__path__" = "/var/log/unifi/access.log", "log" = "unifi_access"},
       {"__path__" = "/var/log/unifi/tasks.log", "log" = "unifi_tasks"},
       {"__path__" = "/var/log/unifi/mongod.log", "log" = "unifi_mongod"},
       {"__path__" = "/var/log/unifi_package.log", "log" = "unifi_package"},
       ]
     sync_period = "10s"
   }

Dieser Abschnitt konfiguriert das Sammeln von UniFi-Logs, ähnlich wie die Paket-Logs.

Loki-Schreibkonfiguration:

   loki.write "unifi" {
     endpoint {
       url = "http://loki_traefik:3100/loki/api/v1/push"
     }
   }

   loki.write "package" {
     endpoint {
       url = "http://loki_traefik:3100/loki/api/v1/push"
     }
   }

   loki.write "grafana_loki" {
     endpoint {
       url = "http://loki_traefik:3100/loki/api/v1/push"
     }
   }

Diese Abschnitte definieren, wohin die Logs gesendet werden:

  • endpoint: Definiert den Loki-Endpunkt (URL), an den die Logs gesendet werden.
  • Bei dieser Konfiguration werden die Logs an den lokalen Loki-Container gesendet.

Die Alloy-Konfiguration ist modular aufgebaut und ermöglicht es, verschiedene Log-Quellen zu definieren und zu verarbeiten, bevor sie an Loki gesendet werden.

Container starten

Nachdem alle Konfigurationsdateien erstellt wurden, starten wir die Container:

cd ~/docker/logging
docker compose up -d

Überprüfe, ob die Container erfolgreich gestartet wurden:

docker ps | grep -E 'loki|alloy'

Du solltest zwei laufende Container sehen: loki_traefik und alloy_traefik.

Überprüfen der Logs

Überprüfe die Logs beider Container, um sicherzustellen, dass sie fehlerfrei gestartet wurden:

# Loki-Logs prüfen
docker logs loki_traefik | grep -E 'error|fail|ready'

# Alloy-Logs prüfen
docker logs alloy_traefik | grep -E 'error|fail|running'

Achte auf Fehlermeldungen oder Warnungen. Im Normalfall sollten beide Dienste ohne kritische Probleme starten.

Konfiguration von Grafana und Verwendung des Dashboards

Nachdem Loki und Alloy erfolgreich installiert sind, richten wir Grafana ein, um die gesammelten Logs anzuzeigen. Ich zeige dir, wie du das mitgelieferte Dashboard importierst und optimale Abfragen für dein Log-Monitoring erstellst.

Loki als Datenquelle in Grafana hinzufügen

  1. Öffne Grafana unter http://grafana.local
  2. Navigiere zu „Configuration“ > „Data Sources“ (oder direkt zu http://grafana.local/connections/datasources)
  3. Klicke auf „Add data source“
  4. Wähle „Loki“ aus der Liste
  5. Konfiguriere folgende technische Parameter:
    • Name: Loki
    • URL: http://loki_traefik:3100 (bei gleichem Docker-Netzwerk) oder http://loki.local (über Traefik)
    • Access: Server (default)
    • HTTP Method: GET
    • TLS/SSL Auth: Deaktiviert
    • Skip TLS Verify: Aktiviert für lokale Entwicklung
    • Forward OAuth Identity: Deaktiviert
    • Timeout: 30 (Standard)
  6. Erweiterte HTTP-Einstellungen: Belasse auf Standardwerten
  7. Klicke auf „Save & Test“

Bei erfolgreicher Verbindung erscheint die Meldung „Data source connected and labels found“.

Dashboard importieren

Ich habe ein einfaches Dashboard speziell für Raspberry Pi Log-Monitoring erstellt.
So importierst du es:

  1. Navigiere zu „Dashboards“ > „+ Import“ (oder direkt zu http://grafana.local/dashboard/import)
  2. Verwende entweder:
  3. Konfiguriere:
    • Name: Raspberry Pi Log Monitoring
    • Folder: Logging (oder erstelle einen neuen Ordner)
    • Loki data source: Wähle die eben erstellte Loki-Datenquelle
  4. Klicke auf „Import“

Das Dashboard sollte nun verfügbar sein und direkt deine Logs anzeigen, nachdem Alloy ausreichend Zeit hatte, Logs zu sammeln.

Erklärung des Dashboards

Das importierte Dashboard bietet eine umfassende Übersicht über deine Systemlogs mit folgenden Bereichen:

Übersichtsbereich:

  • Log-Volumina nach Schweregrad (INFO, WARN, ERROR)
  • Zeitreihen der Log-Aktivitäten
  • Top-Log-Produzenten nach Host/Service

Detailpanels:

  • Logs nach Schweregrad gefiltert
  • Suchfunktion für spezifische Log-Inhalte
  • Drill-down-Möglichkeiten für Detailanalysen

Logs nach Systemkomponenten:

  • Systemd-Logs (Kernel, Dienste)
  • Paket-Management (apt, dpkg)
  • Optional: UniFi-Controller (falls konfiguriert)

Anpassung des Dashboards

Das Dashboard kann nach Bedarf angepasst werden:

  1. Klicke auf das Zahnrad-Symbol oben rechts, um das Dashboard zu bearbeiten
  2. Einzelne Panels können durch Klicken auf den Panel-Titel und „Edit“ angepasst werden
  3. Um ein neues Panel hinzuzufügen, klicke auf „+ Add panel“ oben rechts
  4. Speichere Änderungen mit „Save“ in der oberen rechten Ecke

Praktische Anwendungen und Beispiele

Hier sind einige praktische Anwendungsfälle für dein neues Logging-System direkt in Grafana.
Du kannst die Abfragen zum Testen bei „Entdecken -> Queries -> Code“ eingeben:

DarkWolfCave - Logging mit Grafana Alloy - Queries

Überwachung von System-Updates

Mit unserem Setup werden automatisch alle Paketoperationen überwacht. So kannst du feststellen, wann und welche Pakete installiert oder aktualisiert wurden:

{job="package"} |= "upgrade" or {job="package"} |= "install"

Diese Abfrage in Grafana zeigt dir alle Paketinstallationen und -upgrades.

Erkennung von Systemabstürzen und -neustarts

Systemabstürze und unerwartete Neustarts hinterlassen Spuren im systemd-Journal:

{job="systemd"} |= "Startup finished" | json | line_format "System startup completed in {{.MESSAGE}}"

Diese Abfrage hilft, Bootzeiten zu identifizieren und nach unerwarteten Neustarts zu suchen.

Fehleranalyse für UniFi-Controller (falls vorhanden)

Wenn du UniFi-Geräte in deinem Netzwerk hast, sammelt Alloy bereits die UniFi-Controller-Logs:

{job="unifi"} |~ "(?i)error|fail|exception|terminated"

Diese Abfrage zeigt alle Fehler im UniFi-Controller, was bei der Fehlersuche in deinem Netzwerk hilft.

Sicherheitsrelevante Ereignisse überwachen

{job="systemd"} |~ "(?i)authentication|sudo|permission|authorized|refused"

Diese Abfrage findet sicherheitsrelevante Ereignisse wie Authentifizierungsversuche oder Berechtigungsänderungen.

Benachrichtigungen für kritische Ereignisse einrichten

Grafana-Benachrichtigungen können auf Basis deiner Log-Daten konfiguriert werden:

  1. Navigiere zu „Alerting“ > „Alert rules“ > „New alert rule“
  2. Konfiguriere eine Regel mit:
    • Data source: Loki
    • Query: sum(count_over_time({level="ERROR"} [5m])) > 5
    • Name: Excessive Error Detection
    • Folder: Logging
    • Evaluation interval: 1m
    • For: 5m (Zeitraum, für den die Bedingung erfüllt sein muss)
  3. Konfiguriere Benachrichtigungskanäle nach Bedarf (Email, Slack, Discord, etc.)

Diese Regel löst einen Alarm aus, wenn mehr als 5 Fehler innerhalb von 5 Minuten auftreten.

Best Practices für Alloy-Konfigurationen

Modularität:

  • Teile deine Konfiguration in logische Gruppen (z.B. nach Log-Quelle)
  • Benenne Komponenten sinnvoll (nginx_parser statt parser1)

Ressourcennutzung:

  • Setze tail_from_end = true für neue Deployments, um nicht sofort alle historischen Logs zu verarbeiten
  • Verwende exclude-Direktiven, um unnötige Logs zu filtern

Labels vs. Loginhalt:

  • Extrahiere häufig abgefragte Werte als Labels (z.B. level, service)
  • Behalte die Detailinformationen im Logtext
  • Beachte: Zu viele Labels erhöhen den Speicherbedarf in Loki

Effiziente Regex:

  • Verwende benannte Capture-Gruppen ((?P<name>pattern))
  • Optimiere Ausdrücke für Leistung (vermeide Backtracking)
  • Teste deine Regex mit Tools wie regex101.com

Sicherheit:

  • Filtere sensible Informationen (Passwörter, Tokens) vor dem Senden an Loki
   stage.replace {
     expression = "(password|token|secret)=\\S+"
     replace = "${1}=REDACTED"
   }

Durch das Verständnis dieser Grundkonzepte kannst du deine Alloy-Konfiguration erweitern und anpassen, um verschiedene Log-Quellen zu integrieren und wertvolle Erkenntnisse aus deinen Logs zu gewinnen.

Mein Fazit

Bild KI-generiert
Firefly Erstelle eine einfache stilisierte Wolfsfigur die in einem klassischen Comicstil gezeichne

Grafana Loki und Alloy bieten ein leistungsfähiges, aber ressourceneffizientes Logging-System für den Raspberry Pi. Die modulare Konfiguration von Alloy ermöglicht es, den Log-Sammelprozess genau an deine Bedürfnisse anzupassen – von einfachen Datei-Logs bis hin zu komplexer Verarbeitung und Anreicherung.

Mit dem bereitgestellten Dashboard erhältst du sofort einen umfassenden Überblick über den Zustand deines Systems. Die Integration mit Pi-hole für die DNS-Verwaltung vereinfacht zudem den Zugriff auf deine Services im Heimnetzwerk.

Für weitere Anpassungen kannst du die vorgestellten Konzepte und Beispiele nutzen, um neue Log-Quellen hinzuzufügen oder die bestehende Verarbeitung zu optimieren.

Du wirst hier einen groben Überblick finden.
Allerdings biete ich dir auch noch etwas mehr Support an:

  • Du benötigst persönlichen Support
  • Du möchtest von Beginn an Unterstützung bei deinem Projekt
  • Du möchtest ein hier vorgestelltes Plugin durch mich installieren und einrichten lassen
  • Du würdest gerne ein von mir erstelltes Script etwas mehr an deine Bedürfnisse anpassen

Für diese Punkte und noch einiges mehr habe ich einen limitierten
VIP-Patreon Tarif
eingerichtet. Falls er dir dort zurzeit nicht angeboten wird,
kontaktiere mich bitte über Discord und wir finden eine Lösung!

Avatar-Foto

Ich bin ein 1977 geborener Technik-Nerd. Mein erster Gefährte in der digitalen Welt war ein C64, der den Grundstein für meine Leidenschaft für Technologie legte. So wurde mein Hobby zum Beruf, und ich begann eine Ausbildung zum IT-Systemelektroniker. Selbst in meiner knappen Freizeit widme ich mich weiterhin meiner Leidenschaft fürs Gaming, verschiedene Programmiersprachen und andere IT-bezogene Themen. Ansonsten mag ich Hunde und bin fasziniert von Wölfen!

Gefällt dir der Beitrag?
Hinterlasse gerne ein paar Sterne!

Wie hilfreich war dieser Beitrag für Dich?

Klicke auf die Sterne um zu bewerten!

Durchschnittliche Bewertung 5 / 5. Anzahl Bewertungen: 1

Bisher keine Bewertungen! Sei der Erste, der diesen Beitrag bewertet.

Es tut uns leid, dass der Beitrag für dich nicht hilfreich war!

Lasse uns diesen Beitrag verbessern!

Wie können wir diesen Beitrag verbessern?

Abonnieren
Benachrichtige mich bei
guest
0 Kommentare
Neueste
Älteste
Inline Feedbacks
Alle Kommentare anzeigen

Inhalt

Inhalt