Grafana Loki and Promtail Log Pipeline Setup - 夜莺博客

Grafana Loki and Promtail Log Pipeline Setup

Loki takes the opposite architectural bet to a full-text log database: it indexes labels, not log content, and stores compressed chunks of the raw lines. The result is far cheaper ingestion and storage, at the cost of depending on disciplined labelling. This guide builds a working pipeline - Loki server configuration and storage schema, Promtail as the collector, scrape configurations for files and the systemd journal, pipeline stages to extract labels from unstructured lines, and the LogQL queries that make the labelled data useful.

Loki server configuration

# loki-config.yml
auth_enabled: false

server:
  http_listen_port: 3100

common:
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

schema_config:
  configs:
    - from: 2026-01-01
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

limits_config:
  retention_period: 744h

The schema block defines where the index lives and its period; the retention period is what stops a filesystem-backed Loki from filling the disk. For anything beyond a lab, move chunks to an object store - the local filesystem is for evaluation and small single-node deployments.

docker run -d --name loki --restart unless-stopped -p 3100:3100 \
  -v /opt/loki:/mnt/config grafana/loki:latest --config.file=/mnt/config/loki-config.yml
curl localhost:3100/ready

Promtail as the collector

# promtail-config.yml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

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

scrape_configs:
  - job_name: system
    static_configs:
      - targets: [localhost]
        labels:
          job: varlogs
          host: node01
          __path__: /var/log/*log

  - job_name: journal
    journal:
      max_age: 12h
      labels:
        job: systemd-journal
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: unit

The positions file is how Promtail knows where it stopped reading; losing it means re-shipping every log line, so treat it as state that must survive container restarts. The journal scrape configuration is often the more valuable one on modern systems, and the relabel rule promoting the systemd unit to a label is what makes journal queries usable instead of one giant undifferentiated stream.

Pipeline stages: turning text into labels

scrape_configs:
  - job_name: nginx
    static_configs:
      - targets: [localhost]
        labels:
          job: nginx
          __path__: /var/log/nginx/access.log
    pipeline_stages:
      - regex:
          expression: '^(?P<ip>\S+) - - \[(?P<ts>[^\]]+)\] "(?P<method>\S+) (?P<path>\S+)'
      - labels:
          method:
      - timestamp:
          source: ts
          format: '02/Jan/2006:15:04:05 -0700'
      - metrics:
          status_2xx:
            type: Counter
            source: status
            config:
              action: inc

Labels extracted here become part of Loki's index, so keep cardinality low. HTTP method is fine; user ID or full URL path is not - that is what turned people's first Loki deployment into a memory problem. Parse high-cardinality data into the log line or into a metric, not into a label.

Query with LogQL

{job="nginx"} |= "500"
{job="systemd-journal", unit="sshd"} != "Accepted"
sum by (host) (rate({job="varlogs"} |= "error" [5m]))

The stream selector comes first, then line filters, then optional parsers and metric aggregations. Query patterns are cheap when they are label-selective; a query that scans every stream for a substring will work but will not be fast.

Fits alongside

Loki handles logs; metrics stay in Prometheus - see Prometheus Alertmanager routing on the alerting side and OpenTelemetry Collector pipelines if you would rather have one agent emit all three signals. For a different logs-to-search pipeline, see Fluent Bit to Elasticsearch.

原文链接:https://parithosh.com/2021/06/29/2021-06-29-logging-with-loki