Loki — система агрегации логов от Grafana Labs, которая индексирует только метки потоков, а сами строки складывает сжатыми блоками в объектное хранилище. Из-за этого она дешевле Elasticsearch по диску и памяти, но поиск по тексту идёт полным перебором подходящих потоков. Для домашней лаборатории, небольшой команды или сотни гигабайт логов в месяц этого более чем достаточно. Ниже — рабочая установка, сбор логов Nginx через Grafana Alloy и практические запросы LogQL.

Чем Loki отличается от Elasticsearch

Elasticsearch строит инвертированный индекс по каждому слову, поэтому мгновенно ищет произвольные фразы, но требует много RAM и диска. Loki хранит индекс только для меток: job, host, container, namespace. Чем меньше уникальных комбинаций меток, тем эффективнее запросы. Плата за простоту — необходимость сначала сузить поток метками, а уже потом фильтровать текст.

  • Метки — это не поля лога, а способ быстро найти нужный поток.
  • Высокая кардинальность (идентификатор запроса, IP, user_id) убивает производительность.
  • Хранение в S3-совместимом хранилище позволяет держать логи месяцами.
  • Grafana выступает единой точкой входа для логов, метрик и трассировок.

Установка через Docker Compose

Для одного сервера подойдёт режим с файловым хранилищем. Конфигурация ниже включает TSDB-индекс, файловое хранилище и удержание логов 30 дней. Каталоги монтируем на диск, где достаточно места: сжатые чанки занимают немного, но метаданные и индекс тоже растут.

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

  alloy:
    image: grafana/alloy:v1.7.5
    volumes:
      - ./config.alloy:/etc/alloy/config.alloy:ro
      - /var/log:/var/log:ro
    command: run --server.http.listen-addr=0.0.0.0:12345 /etc/alloy/config.alloy

  grafana:
    image: grafana/grafana:11.5.0
    ports:
      - "3000:3000"
    volumes:
      - ./data/grafana:/var/lib/grafana

Файл loki.yaml задаёт схему, хранилище и политику удержания. Компактор включаем сразу: без него старые чанки не удаляются, даже если срок хранения указан.

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: 2024-04-01
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

limits_config:
  retention_period: 720h

compactor:
  working_directory: /loki/compactor
  retention_enabled: true
  delete_request_store: filesystem

Сбор логов с помощью Grafana Alloy

Promtail официально завершил жизненный цикл в 2025 году, поэтому новые установки собираем на Alloy. Агент находит файлы, читает их с текущей позиции и отправляет поток в Loki. Метки job и host должны быть стабильными: именно по ним строятся запросы.

local.file_match "nginx" {
  path_targets = [{
    __path__ = "/var/log/nginx/*.log",
    job      = "nginx",
    host     = "web-01",
  }]
}

loki.source.file "nginx" {
  targets    = local.file_match.nginx.targets
  forward_to = [loki.write.local.receiver]
}

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

Для контейнеров вместо local.file_match используют discovery.docker и loki.source.docker, но принцип тот же: метки из конфигурации, текст из stdout. Не добавляйте в метки имя контейнера с хешем — оно меняется при каждом перезапуске и создаёт новый поток.

Запросы LogQL

Сначала выбираем поток в фигурных скобках, затем фильтруем строки операторами |= (содержит), !~ (не совпадает с регулярным выражением) и | json. Метрические запросы считают скорость и количество событий.

{job="nginx"} |= "error"
{job="nginx"} |~ " 50[0-9] "
{job="nginx"} | json | status >= 500
sum by (host) (rate({job="nginx"} |= "error" [5m]))
topk(5, sum by (path) (count_over_time({job="nginx"} | json [1h])))

Оператор | json разбирает JSON-строки и делает поля доступными для фильтров. Для логов в формате key=value есть | logfmt. Если поле встречается редко, сначала сузьте поток по метке и времени, иначе Loki просканирует лишние гигабайты.

Диагностика и обслуживание

Проверка готовности, метрики и список меток помогают быстро понять, где оборвалась цепочка: агент, сеть или сама Loki. Утилита logcli удобна для проверки запросов без браузера.

curl -s http://localhost:3100/ready
curl -s http://localhost:3100/metrics | grep -E 'loki_ingester_memory_streams|loki_request_duration'
logcli query '{job="nginx"} |= "timeout"' --since=2h --limit=50
curl -s http://localhost:3100/loki/api/v1/labels

Если Grafana показывает «No data», проверьте три вещи: совпадает ли метка в запросе с реальной, не истёк ли срок хранения и видит ли агент файл. Права на /var/log/nginx у контейнера часто недостаточны — монтируйте каталог только для чтения и запускайте агент от пользователя с доступом.

Отдельного внимания требует удержание. Параметр retention_period действует только вместе с включённым компактором и корректным delete_request_store. Проверить фактический объём можно через API и размер каталога: если чанки растут, а старые не исчезают, скорее всего компактор не запустился из-за прав или несовместимой схемы. Для больших объёмов вместо файловой системы подключают S3-совместимое хранилище и выносят индекс на отдельный диск.

Кардинальность, безопасность и резервные копии

  • Держите число потоков в пределах десятков тысяч, а не миллионов.
  • Не открывайте порт 3100 в интернет: Loki не имеет встроенной авторизации при auth_enabled: false.
  • Ставьте перед Loki reverse proxy с Basic Auth или ограничьте доступ по сети.
  • Резервируйте каталог data/loki вместе с конфигурацией; для больших объёмов используйте S3-совместимое хранилище.
  • Проверяйте loki_ingester_memory_streams и размер чанков после изменения формата логов.

Итог

Loki выигрывает там, где нужен недорогой централизованный поиск по логам без кластера Elasticsearch. Секрет стабильной работы — дисциплина меток: минимальный набор измерений, никаких идентификаторов в лейблах и обязательное сужение по времени. Связка Loki, Alloy и Grafana разворачивается за вечер и закрывает типовые задачи диагностики: найти ошибки за последний час, посчитать пятисотые по хостам и посмотреть контекст вокруг сбоя.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте