Когда проект работает на трёх-пяти VDS, поиск нужной строки в логах превращается в обход серверов по SSH один за другим. Grafana Loki собирает логи со всех серверов в одно место и даёт искать по ним через тот же интерфейс Grafana, где уже смотрят метрики. Разберём установку Loki, агента Promtail и типичные запросы LogQL.
Зачем нужен централизованный сбор логов и чем Loki отличается от ELK
Elasticsearch индексирует полный текст каждой строки лога, поэтому кластер ELK требует много памяти и диска даже на средних объёмах. Loki устроен иначе: он индексирует только метки (labels) — имя сервера, имя сервиса, уровень лога, — а сам текст хранит сжатым блоками. Поиск по меткам почти мгновенный, полнотекстовый поиск внутри найденных блоков чуть медленнее, зато инфраструктура для Loki требует в разы меньше ресурсов, чем для Elasticsearch.
Для парка из нескольких VDS с обычной нагрузкой это разумный компромисс: не нужен отдельный кластер из трёх узлов только под логи.
Установка Loki на VDS через Docker Compose
Минимальный стек — Loki для хранения, Promtail для сбора и Grafana для просмотра — поднимается одним файлом:
services:
loki:
image: grafana/loki:3.1.0
ports:
- "3100:3100"
volumes:
- ./loki-data:/loki
command: -config.file=/etc/loki/local-config.yaml
grafana:
image: grafana/grafana:11.1.0
ports:
- "3000:3000"
volumes:
- ./grafana-data:/var/lib/grafana
После docker compose up -d Loki принимает данные на порту 3100, а Grafana доступна на порту 3000 для настройки дашбордов и запросов.
Promtail: сбор логов с серверов и отправка в Loki
Promtail ставится на каждый сервер, откуда нужны логи, читает файлы из /var/log и docker-контейнеров, добавляет метки и отправляет батчами в Loki. Конфиг агента:
server:
http_listen_port: 9080
clients:
- url: http://loki.internal:3100/loki/api/v1/push
scrape_configs:
- job_name: nginx
static_configs:
- targets: ["localhost"]
labels:
job: nginx
host: web-01
__path__: /var/log/nginx/*.log
Метка host здесь критична: без неё в общем потоке логов с пяти серверов невозможно понять, откуда пришла конкретная строка.
Настройка меток для быстрого поиска
В Loki важно не превращать в метку то, что часто меняется, — например, ID запроса или временную метку внутри строки. Каждое уникальное значение метки создаёт отдельный поток (stream), и тысячи уникальных значений превращают Loki в подобие того же Elasticsearch по нагрузке на индекс.
- В метки выносят стабильные значения: имя сервера, имя сервиса, окружение (prod/staging)
- ID запроса, email, IP-адрес ищут полнотекстовым запросом внутри уже отобранного потока, а не через метку
- Количество уникальных комбинаций меток держат в пределах нескольких сотен на инсталляцию
Подключение Loki как источника данных в Grafana
В Grafana источник данных добавляется в разделе Connections → Data sources → Loki, URL указывается как http://loki:3100 при общей Docker-сети. После сохранения логи ищутся во вкладке Explore тем же интерфейсом, что уже используют для графиков Prometheus.
Запросы LogQL: примеры
LogQL сочетает выбор потока по меткам в фигурных скобках и фильтр по тексту после вертикальной черты:
{host="web-01", job="nginx"} |= "500"
{job="nginx"} | json | status >= 500
sum(rate({job="nginx"} |= "500" [5m])) by (host)
Первый запрос ищет строку "500" в логах nginx на конкретном сервере, второй разбирает JSON-лог и фильтрует по числовому полю status, третий считает частоту ошибок 500 в минуту по каждому серверу — удобно для алертов и дашбордов.
Хранение и ротация логов
По умолчанию Loki хранит логи локально на диске без ограничения по времени, поэтому retention настраивают отдельно параметром retention_period в конфиге, иначе диск сервера рано или поздно заполнится. Для долгого архива логов свежие блоки можно выгружать в S3-совместимое хранилище — подробности в статье про сравнение S3-провайдеров.
Сам стек Loki плюс Promtail плюс Grafana логично разворачивать рядом с уже настроенным мониторингом Uptime Kuma: метрики доступности и логи ошибок дополняют друг друга при разборе инцидента. Если серверов много и они объединены в Docker Swarm, Promtail разворачивают как глобальный сервис на каждом узле кластера.
Итог: чек-лист запуска Loki
Централизованные логи экономят часы поиска по инцидентам, если стек настроен с самого начала правильно, а не собирается на скорую руку после первого сбоя.
- Loki для хранения, Promtail на каждом сервере, Grafana для запросов
- Метка
hostобязательна на каждом источнике логов - В метки — только стабильные значения, остальное — в текст лога
- Параметр retention настроен явно, а не оставлен по умолчанию