Log Aggregatie met Grafana Loki: Lightweight Alternatief voor ELK

Hoe Grafana Loki log aggregatie simpel en schaalbaar maakt zonder de overhead van Elasticsearch.

Jean-Pierre Broeders

Freelance DevOps Engineer

4 maart 20266 min. leestijd

Log Aggregatie met Grafana Loki

De meeste teams beginnen met kubectl logs of docker logs en denken: dit is genoeg. Tot er iets misgaat op vrijdagmiddag en niemand kan achterhalen welke service de cascade van errors veroorzaakte. Logs verspreid over twintig containers doorzoeken via SSH is geen strategie — dat is paniek.

Waarom niet gewoon ELK?

Elasticsearch, Logstash en Kibana. De klassieke stack. Werkt prima, maar de operationele overhead is fors. Elasticsearch vreet geheugen. Clusters moeten beheerd worden. Index management wordt een dagtaak. Voor een klein tot middelgroot team is dat overkill.

Grafana Loki pakt het fundamenteel anders aan. Waar Elasticsearch elke regel tekst indexeert, indexeert Loki alleen de metadata — labels zoals app=payment-service of env=production. De logregels zelf worden als compressed chunks opgeslagen in goedkope object storage. Dat scheelt enorm in resources.

Architectuur in het kort

Een typische Loki-setup bestaat uit drie componenten:

  • Promtail — agent die logs verzamelt en naar Loki stuurt
  • Loki — de log aggregation engine
  • Grafana — visualisatie en querying

Het mooie: als Grafana al draait voor metrics (Prometheus), hoeft er geen extra UI opgezet te worden. Logs en metrics leven in dezelfde interface.

Docker Compose setup

version: "3.8"

services:
  loki:
    image: grafana/loki:2.9.4
    ports:
      - "3100:3100"
    volumes:
      - ./loki-config.yaml:/etc/loki/local-config.yaml
      - loki-data:/loki
    command: -config.file=/etc/loki/local-config.yaml

  promtail:
    image: grafana/promtail:2.9.4
    volumes:
      - /var/log:/var/log:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - ./promtail-config.yaml:/etc/promtail/config.yaml
    command: -config.file=/etc/promtail/config.yaml

  grafana:
    image: grafana/grafana:10.3.1
    ports:
      - "3000:3000"
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=true
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  loki-data:
  grafana-data:

Promtail configuratie

Promtail moet weten waar logs staan en welke labels eraan hangen. Een configuratie voor Docker containers:

server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: docker
    static_configs:
      - targets:
          - localhost
        labels:
          job: docker
          __path__: /var/lib/docker/containers/*/*-json.log
    pipeline_stages:
      - docker: {}
      - match:
          selector: '{job="docker"}'
          stages:
            - json:
                expressions:
                  output: log
                  stream: stream
            - output:
                source: output

Die pipeline_stages zijn cruciaal. Docker schrijft logs als JSON met metadata. De pipeline pelt dat af en haalt de eigenlijke logregel eruit.

Structured logging maakt het verschil

Loki wordt pas echt krachtig in combinatie met structured logging vanuit de applicatie. Stel, een .NET service logt dit:

{
  "timestamp": "2026-03-04T08:23:11Z",
  "level": "error",
  "message": "Payment processing failed",
  "orderId": "ORD-88412",
  "provider": "stripe",
  "duration_ms": 3201,
  "error": "timeout"
}

Met een Promtail pipeline die JSON-velden als labels extraheert, wordt filteren triviaal:

{app="payment-service"} | json | provider="stripe" | level="error"

Vergelijk dat met grep door ongestructureerde tekstlogs. Nacht en dag.

LogQL: de querytaal

LogQL lijkt op PromQL (voor wie Prometheus kent) maar dan voor logs. Een paar praktische queries:

# Alle errors van de laatste 5 minuten
{env="production"} |= "error" | line_format "{{.message}}"

# Rate van errors per service
sum(rate({env="production"} |= "error" [5m])) by (app)

# Top 10 traagste requests
{app="api-gateway"} | json | duration_ms > 1000 | sort_desc | limit 10

Die rate() functie is goud waard. Hiermee worden log-gebaseerde metrics gemaakt zonder dat er aparte instrumentatie nodig is. Een alert op "meer dan 50 errors per minuut" is één query.

Alerting op logs

In Grafana kunnen alerts rechtstreeks op LogQL queries gezet worden:

groups:
  - name: log-alerts
    rules:
      - alert: HighErrorRate
        expr: |
          sum(rate({env="production"} |= "error" [5m])) by (app) > 0.5
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "Hoge error rate in {{ $labels.app }}"

Twee minuten lang meer dan 0.5 errors per seconde? Dan gaat de alert af. Simpel, effectief, geen aparte tooling nodig.

Kosten en schaling

Hier zit de echte winst. Een concrete vergelijking voor een setup met ~50GB logs per dag:

| | ELK | Loki | |---|---|---| | RAM | 32-64 GB | 4-8 GB | | Storage | SSD vereist | S3/MinIO (goedkoop) | | Operationeel | Cluster management | Bijna niks | | Kosten (cloud) | €400-800/maand | €50-100/maand |

Die cijfers zijn geen marketingpraatjes. In production omgevingen met tientallen microservices is dit het verschil tussen "we moeten de logging terugschroeven" en "we loggen gewoon alles."

Valkuilen

Niet alles is rozengeur. Een paar dingen om op te letten:

Hoge kardinaliteit labels vermijden. Labels zoals user_id of request_id als Loki-label zetten is een recept voor problemen. Dat soort waarden horen in de logregel zelf, niet in de index. Loki waarschuwt hier niet altijd voor, maar de performance klapt in elkaar.

Retention instellen. Standaard bewaart Loki alles. Voor production is een retention policy van 30-90 dagen meestal genoeg:

table_manager:
  retention_deletes_enabled: true
  retention_period: 720h  # 30 dagen

Promtail vs Alloy. Grafana duwt richting Alloy (hun nieuwe collector). Promtail werkt nog prima, maar voor nieuwe setups is Alloy het overwegen waard — het combineert metrics en logs collection in één agent.

Conclusie

Log aggregatie hoeft geen megaproject te zijn. Loki met Promtail en Grafana draait binnen een uur, kost een fractie van ELK, en schaalt moeiteloos mee. De combinatie met structured logging en LogQL maakt debugging van distributed systems drastisch sneller. Geen excuus meer om logs niet centraal te hebben.

Wil je op de hoogte blijven?

Schrijf je in voor mijn nieuwsbrief of neem contact op voor freelance projecten.

Neem Contact Op