🟡 Intermediate

Grafana Loki — Log Aggregation pre Cloud-Native

Loki je horizontálne škálovateľný log aggregation systém od Grafana Labs, inšpirovaný Prometheom. Jeho hlavná myšlienka je jednoduchá — neindexovať obsah logov, ale iba metadáta (labels), a samotné logy ukladať komprimované na objektové úložisko (S3, GCS, Azure Blob, local filesystem).

Dôsledok: prevádzka Loki je rádovo lacnejšia než klasický Elasticsearch/OpenSearch stack, najmä pri veľkom objeme logov. Grafana Labs ho spúšťa na produkcii s desiatkami TB logov denne.


Prečo Loki a nie Elastic?

Aspekt Elasticsearch (ELK) Loki
Indexovanie Full-text inverted index nad celým obsahom Iba labels (metadata), obsah neindexovaný
Úložisko Disk (SSD) v ES klastri Object storage (S3, GCS, MinIO)
Query model DSL (Query DSL) alebo KQL LogQL (Prometheus-like)
Cena/GB Vysoká (RAM + SSD + index) Nízka (lacné object storage)
Škálovateľnosť Komplexná (shards, replicas) Microservices mód + object storage
Typ vyhľadávania Full-text, rýchle aj na starých dátach Grep-like nad časovým oknom

Hlavný kompromis: full-text search nad celou historickou databázou je v Loki pomalý, pretože obsah nie je indexovaný. Preto Loki cielí na use-case, kde sa viete zúžiť pomocou labels (service, pod, namespace, level) a až potom hľadať v obsahu.

Ak v ELK hľadáte error za posledný rok bez žiadneho filtra, dostanete výsledok v sekundách. V Loki toto bude pomalé — ale rovnaká otázka so zúžením {namespace="production",app="api"} je rýchla a desaťkrát lacnejšia.


Architektúra Loki

Loki má dva módy nasadenia:

1. Monolitický (single binary)

Všetky komponenty v jednom binary. Ideálne na laboratórium, lab, malé klastre do ~100 GB/deň.

2. Microservices / SSD (scalable)

Komponenty bežia ako samostatné pody, škálujú sa nezávisle. Produkčný setup.

               ┌─────────┐
  Logs ───►    │Distributor│─┐
               └─────────┘ │
                           ▼
                       ┌─────────┐
                       │Ingester │──► Chunks → S3/GCS
                       └─────────┘
                           ▲
                           │
               ┌─────────┐ │
  Query ◄──    │ Querier │─┘
               └─────────┘
                    ▲
               ┌─────────┐
               │Query Fr.│
               └─────────┘
  • Distributor — prijíma logy cez HTTP (/loki/api/v1/push), validuje, rozdistribuuje do ingesterov pomocou consistent hashing nad labels.
  • Ingester — drží logy v pamäti (in-memory chunks), pravidelne ich flushuje ako komprimované chunks na objekt storage.
  • Querier — obsluhuje query a query_range HTTP endpointy, číta chunks z objektového storage + z ingesterov (pre recent data).
  • Query Frontend — cacheuje a paralelizuje dotazy, rozdeľuje ich do sub-queries podľa času.
  • Compactor — merguje a deduplikuje staré chunks, aplikuje retention policy.

LogQL — query language

LogQL je úmyselne podobný PromQL. Má dve hlavné časti:

1. Log stream selector

Vyberie streamy podľa labels:

{namespace="production", app="api"}

Regex tiež funguje:

{namespace=~"prod-.*", app!="sidecar"}

2. Log pipeline

Filtruje a parsuje riadky streamu. Operátory:

  • |= — obsahuje reťazec
  • != — neobsahuje
  • |~ — regex match
  • !~ — regex no-match
  • | json — parsuje JSON logy
  • | logfmt — parsuje logfmt (key=value)
  • | pattern — custom pattern parser

Príklady:

# Error logy z API v produkcii
{namespace="production", app="api"} |= "error"

# 5xx HTTP chyby z nginx
{app="nginx"} | json | status >= 500

# Latencia nad 1s
{app="api"} | logfmt | latency > 1s

# Extrakcia user_id z pattern logu
{app="auth"} | pattern `<_> user_id=<user> <_>` | user="42"

3. Metric queries

LogQL umožňuje robiť metriky zo samotných logov (čo ELK samostatne neponúka):

# Počet errorov za minútu
sum(rate({app="api"} |= "error" [1m])) by (pod)

# 95. percentil latencie
quantile_over_time(0.95,
  {app="api"} | logfmt | unwrap latency [5m]
)

Výstup je časová rada, takže sa dá použiť priamo v Grafana dashboardoch a Alertmanager alerts bez nutnosti mať Prometheus metriky pre tieto hodnoty.


Log shippers — ako dostať logy do Loki

Promtail

Klasický agent od Grafana Labs. Beží ako DaemonSet v Kubernetes, číta /var/log/pods/*, enrichuje labels z K8s API:

server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

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

scrape_configs:
  - job_name: kubernetes-pods
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        target_label: app
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
    pipeline_stages:
      - docker: {}
      - match:
          selector: '{app="api"}'
          stages:
            - json:
                expressions:
                  level: level
                  msg: message
            - labels:
                level:

Grafana Alloy (budúcnosť)

Grafana Alloy je nový unified agent, ktorý nahrádza Promtail aj Grafana Agent. Podporuje Loki push, OTLP, Prometheus scrape, Pyroscope a ďalšie, všetko cez jednotný konfiguračný jazyk River. Grafana odporúča nové deploye postaviť už nad Alloy.

OpenTelemetry Collector

OTel Collector má natívny loki exporter:

exporters:
  loki:
    endpoint: http://loki:3100/loki/api/v1/push
    labels:
      resource:
        service.name: "service_name"
        k8s.namespace.name: "namespace"

Praktický príklad — docker-compose demo

Minimálny stack s Loki, Promtail a Grafana:

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

  promtail:
    image: grafana/promtail:3.1.0
    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:11.2.0
    ports:
      - "3000:3000"
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin

Po docker compose up otvoríte Grafana na localhost:3000, pridáte Loki data source (http://loki:3100) a v Explore viete skúšať LogQL.


Integrácia s Alertmanagerom

LogQL metric query môže byť zdrojom alertu — Loki beží s ruler komponentom, ktorý periodicky vyhodnocuje pravidlá a posiela alerty do Alertmanagera (Prometheus alebo vlastný Loki ruler):

groups:
  - name: api-errors
    rules:
      - alert: HighErrorRate
        expr: |
          sum(rate({app="api"} |= "error" [5m])) > 5
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "High error rate v API"

Produkčné tipy

  • Label cardinality — nikdy nedávajte high-cardinality veci ako user_id, trace_id do labels. Tie patria do log line. Každá unikátna kombinácia labels = nový stream.
  • Retention — nastavte retention_period a compactor povinne zapnite, inak staré chunks zostávajú v object storage.
  • Chunk size — default max_chunk_age: 2h, chunk_target_size: 1.5MB. Väčšie chunky = lepšia kompresia ale pomalšie queries.
  • Limits — nastavte ingestion_rate_mb, max_streams_per_user, inak jeden misbehaved tenant môže zabiť klaster.
  • Multi-tenancy — Loki podporuje X-Scope-OrgID header, vďaka čomu viete zdieľať jeden klaster medzi tímami.
  • S3 lifecycle policies — po expirácii chunks si nechajte S3 upratať, compactor iba maže pointery.

Loki vs existujúci ELK článok

Ak už máte ELK stack v KB a zvažujete Loki, neznamená to výber buď-alebo. Typický moderný setup:

  • Loki — primárny log pipeline pre všetky služby (lacný, label-based).
  • Elastic — iba pre špecifické security/audit logy, kde potrebujete full-text search nad celou históriou.

Najčastejší postup je postupná migrácia aplikačných logov do Loki a ponechanie Elastic len na niečo, čo ho naozaj vyžaduje (SIEM).


Zhrnutie

Loki je pragmatická alternatíva k Elastic pre log aggregation v prostredí, kde náklady a Kubernetes-native škálovanie rozhodujú. Nie je to drop-in replacement — stratíte full-text search nad neobmedzenou históriou — ale získate rádovo lacnejší a jednoduchší systém, ktorý sa zapája do Grafana LGTM stacku (Loki, Grafana, Tempo, Mimir) rovnakým dotazovacím štýlom ako Prometheus.

Pre väčšinu cloud-native prostredí je to dnes default voľba.

Odkazy