ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Централизованные логи на малом VDS: Promtail + Loki и ретеншн без боли

Нужны централизованные логи без тяжёлых стэков и лишних затрат? Loki в одиночном узле плюс Promtail — оптимально для малого VDS. Разбираем архитектуру, конфигурацию, ретеншн, контроль меток, безопасность, лимиты и типовые ошибки с упором на практику, чтобы быстро внедрить и не тратить ресурсы зря.
Централизованные логи на малом VDS: Promtail + Loki и ретеншн без боли

Когда на небольшом VDS крутится несколько сервисов, вопрос логов встаёт быстро: grep по файлам неудобен, ротация хаотична, а поиск по ошибкам — боль. Полноценные ELK/Opensearch-стэки слишком прожорливы. Нужен лёгкий центр логирования, который выдержит «боевую» нагрузку, не съест всё место на диске и не потребует постоянного шаманства. Разумный компромисс — Loki в одном процессе плюс Promtail на источниках. В этой статье собраны проверенные практики, готовые конфиги и «страховка» от классических проблем с ретеншном и кардинальностью меток.

Зачем Loki на малом VDS и что получится

Loki принципиально дешевле по ресурсам: он индексирует не сам текст строк, а метки (labels), а содержимое хранит в сжатых чанках. Это даёт ощутимую экономию CPU и диска. В едином процессе Loki спокойно работает на 1–2 vCPU и 1–2 ГБ RAM при сотнях событий в секунду и ретеншне 7–30 дней, если не раздувать метки.

Цель этого гайда:

  • Развернуть Loki в однопроцессном режиме с хранением на локальном диске и включённым ретеншном.
  • Запустить Promtail на том же VDS (и, при необходимости, на удалённых хостах) с аккуратными метками и позициями чтения.
  • Настроить безопасную публикацию приёма логов (варианты с привязкой к localhost и через обратный прокси).
  • Дать минимальные, но достаточные лимиты, чтобы «не уронить» машину при всплеске логов.

Архитектура без излишеств

Минимальная схема:

  • Один Loki в режиме «single process». Хранение на локальном диске: индексы через boltdb-shipper, чанки в файловой системе. Включён compactor для ретеншна.
  • Promtail на каждом источнике. Для самого узла с Loki — локальный Promtail, который читает /var/log и контейнерные логи (если нужны).
  • При необходимости приёма логов с внешних машин — публикация порта через обратный прокси с базовой аутентификацией и ограничениями, плюс межсетевой экран.

Почему не отправлять напрямую в Loki без прокси? Можно, но прокси помогает ограничивать размер запросов и скорость, давать базовую аутентификацию и скрывать внутренние детали, а также упростить ротацию сертификатов и иметь единую точку входа.

Жизненный цикл чанков Loki и работа compactor при ретеншне.

Оценка ресурсов: диски, CPU и память

Грубая прикидка диска под логи: возьмите средний объём логов в сутки (в несжатом виде) и умножьте на коэффициент 0.3–0.5 — это ориентир с учётом сжатия Loki. Например, при 1 ГБ/сутки и ретеншне 14 дней требуется 1 ГБ × 0.4 × 14 ≈ 5.6 ГБ под чанки плюс 10–20% на индексы и служебные файлы. Заложите запас ×1.5 на всплески и неравномерность.

CPU: 1 vCPU хватает для десятков-сотен событий/сек. RAM: 1–2 ГБ достаточно при умеренной кардинальности меток и разумных лимитах. Для выбора железа и ОС на малых серверах см. обзор производительности на ARM в материале ARM VDS: производительность PHP/Node.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Контроль меток: как не устроить взрыв кардинальности

В Loki дорого индексируются не строки логов, а метки. Чем больше уникальных наборов меток (streams), тем больше индексов и RAM. Не превращайте каждую строку в отдельный поток.

Рекомендации:

  • Оставьте короткий и стабильный набор меток: job, host, app, env. Этого обычно достаточно.
  • Не включайте в метки динамические значения: request_id, user_id, path, pod_uid, container_hash и т. п. Если они нужны в поиске — оставляйте в тексте строки.
  • Если собираете контейнерные логи, жёстко отфильтруйте лишние Docker/Kubernetes-метки через relabeling.
  • Ставьте лимиты: max_streams_per_user, ingestion_rate_mb, ingestion_burst_size_mb, max_label_names_per_series, max_line_size.

Файловое хранение и ретеншн «без боли»

Для одного узла идеальный вариант — схема boltdb-shipper для индексов и filesystem для чанков. Ретеншн включается в секции compactor и limits_config. compactor периодически сжимает и удаляет устаревшие чанки согласно срокам хранения. Это работает надёжно и не требует внешнего объектного хранилища.

Обратите внимание на границы времени: retention_period — верхний предел. При пиковых нагрузках и активной компрессии фактическое удаление старых чанков может происходить с небольшой задержкой (в пределах интервала компактинга).

Обзор стека Docker Compose: Loki, Promtail и обратный прокси Nginx.

Шаги внедрения (вариант с контейнерами)

Ниже — последовательность действий в стиле «минимум магии», которую удобно восстанавливать и переносить между серверами. Пример используется как шаблон: версии образов и пути подстраивайте под себя.

1) Каталоги и права

Создайте рабочие директории под конфиги и данные. Важно заранее выделить отдельный путь для данных Loki, чтобы удобнее контролировать диск и бэкапы.

mkdir -p /opt/logs-stack/loki
mkdir -p /opt/logs-stack/promtail
mkdir -p /opt/logs-stack/nginx
mkdir -p /var/lib/loki

2) Конфиг Loki с ретеншном

Конфигурация для одиночного процесса с хранением в файловой системе и включённым compactor. В примере задан ретеншн 14 дней, адекватный для небольшого VDS.

# /opt/logs-stack/loki/loki.yml
server:
  http_listen_port: 3100
  http_listen_address: 127.0.0.1
  grpc_listen_port: 0
  log_level: info

auth_enabled: false

common:
  path: /var/lib/loki
  replication_factor: 1
  ring:
    instance_addr: 127.0.0.1

storage_config:
  boltdb_shipper:
    active_index_directory: /var/lib/loki/index
    cache_location: /var/lib/loki/index-cache
    shared_store: filesystem
  filesystem:
    directory: /var/lib/loki/chunks

schema_config:
  configs:
  - from: 2024-01-01
    store: boltdb-shipper
    object_store: filesystem
    schema: v12
    index:
      prefix: index_
      period: 24h

limits_config:
  retention_period: 336h         # 14 дней
  ingestion_rate_mb: 8
  ingestion_burst_size_mb: 16
  max_streams_per_user: 2000
  max_entries_limit_per_query: 5000
  max_line_size: 256kb
  max_label_names_per_series: 20
  reject_old_samples: true
  reject_old_samples_max_age: 168h

chunk_store_config:
  max_look_back_period: 336h

ingester:
  chunk_idle_period: 10m
  chunk_target_size: 1048576     # ~1 МБ
  max_transfer_retries: 0

compactor:
  working_directory: /var/lib/loki/compactor
  shared_store: filesystem
  compaction_interval: 5m
  retention_enabled: true

3) Конфиг Promtail для локальных логов

Promtail будет читать системные логи и, при необходимости, контейнерные. Важно: минимум меток и фильтрация динамических значений.

# /opt/logs-stack/promtail/promtail.yml
server:
  http_listen_port: 9080
  http_listen_address: 127.0.0.1
positions:
  filename: /var/lib/promtail-positions.yaml
clients:
  - url: http://127.0.0.1:3100/loki/api/v1/push
    batchwait: 1s
    backoff_config:
      min_period: 500ms
      max_period: 5s
      max_retries: 10
scrape_configs:
  - job_name: syslog
    static_configs:
      - targets: [localhost]
        labels:
          job: syslog
          host: ${HOSTNAME}
          env: prod
          __path__: /var/log/*.log
    pipeline_stages:
      - drop_multiline: false
  - job_name: journal
    journal:
      path: /var/log/journal
      max_age: 12h
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: 'app'
    static_configs:
      - targets: [localhost]
        labels:
          host: ${HOSTNAME}
          env: prod
  - job_name: docker
    static_configs:
      - targets: [localhost]
        labels:
          job: docker
          host: ${HOSTNAME}
          env: prod
          __path__: /var/lib/docker/containers/*/*.log
    pipeline_stages:
      - json:
          expressions:
            stream: stream
            attrs: attrs
      - labels:
          stream:
      - drop:
          source: attrs
          expression: '.*'

4) Обратный прокси (опционально)

Если надо принимать логи с других машин, публикуйте Loki через прокси. Простой вариант — Nginx с ограничениями размера запроса и базовой авторизацией. Для локального узла оставьте bind на 127.0.0.1, а внешний доступ давайте только через прокси и файрвол.

# /opt/logs-stack/nginx/loki.conf
server {
  listen 80;
  server_name _;

  client_max_body_size 10m;
  keepalive_timeout 15;

  # auth_basic "Restricted";               # включите при необходимости
  # auth_basic_user_file /etc/nginx/loki.htpasswd;

  location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_read_timeout 60s;
    proxy_send_timeout 60s;
    proxy_pass http://127.0.0.1:3100;
  }
}

5) Docker Compose для запуска

Один файл — и весь стек поднимется разом. Порт Loki «наружу» не отдаём, только локально; наружу — только Nginx (если нужен).

# /opt/logs-stack/docker-compose.yml
version: "3.8"
services:
  loki:
    image: grafana/loki:2.9.0
    command: -config.file=/etc/loki/loki.yml
    volumes:
      - /var/lib/loki:/var/lib/loki
      - ./loki/loki.yml:/etc/loki/loki.yml:ro
    network_mode: host
    restart: unless-stopped

  promtail:
    image: grafana/promtail:2.9.0
    command: -config.file=/etc/promtail/promtail.yml
    volumes:
      - /var/log:/var/log:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - ./promtail/promtail.yml:/etc/promtail/promtail.yml:ro
      - /var/lib/promtail-positions.yaml:/var/lib/promtail-positions.yaml
    network_mode: host
    restart: unless-stopped

  # Включайте только если нужен приём с внешних хостов
  nginx:
    image: nginx:stable
    volumes:
      - ./nginx/loki.conf:/etc/nginx/conf.d/default.conf:ro
    ports:
      - "80:80"
    depends_on:
      - loki
    restart: unless-stopped

6) Запуск и проверка

Запустите стек, убедитесь, что Loki принимает записи, а Promtail отдаёт.

cd /opt/logs-stack
docker compose up -d

# Проверка локи-эндпоинтов (должны отвечать 200)
curl -sS localhost:3100/ready
curl -sS localhost:3100/metrics | head -n 5

# Проверка promtail
curl -sS localhost:9080/metrics | head -n 5

Ретеншн: время хранения и «санитария» диска

Секцию limits_config.retention_period подбирайте от задач: часто хватает 7–14 дней. Для инцидент-менеджмента можно держать 30 дней, но проверяйте влияние на диск. compactor.retention_enabled обязан быть включён. Интервал компактинга 5 минут — разумный баланс для маленького узла.

Чтобы не «съесть» диск при всплеске логов:

  • Ставьте лимиты приёма: ingestion_rate_mb и ingestion_burst_size_mb.
  • Делайте мониторинг свободного места и метрик Loki: рост количества чанков, промахи по лимитам, ошибки 429/5xx.
  • Не храните неструктурированный поток «всё подряд» — фильтруйте шум на стороне Promtail (например, health-check строки).

Безопасность: минимально необходимые меры

Базовые шаги:

  • Не слушайте 0.0.0.0 у Loki, оставьте 127.0.0.1. Внешний доступ — только через прокси с аутентификацией.
  • В файрволе открывайте только порт прокси. Ограничивайте доступ по адресам источников логов.
  • В прокси ограничьте client_max_body_size и таймауты, включите keepalive в разумных пределах.
  • Для внешнего трафика используйте TLS: оформить и автоматизировать помогут SSL-сертификаты. Для доверенных агентов можно настроить mTLS на прокси.
  • В Promtail не храните чувствительные данные в метках. При необходимости редактируйте строки через pipeline_stages (маскирование секретов, удаление PII).
FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Тонкая настройка производительности

Важные «крутилки» Loki:

  • chunk_target_size: около 1 МБ — хороший старт для баланса компрессии/поиска.
  • chunk_idle_period: через сколько «закрывать» чанк при низком трафике; 10 минут — компромисс.
  • max_look_back_period: ограничивает глубину поиска и экономит ресурсы.
  • max_entries_limit_per_query: ограничивает объём выдачи, защищая узел от тяжёлых запросов.

В Promtail контролируйте пакетирование (batchwait), ретраи (backoff_config) и берегите диск: файл позиций храните на отдельном томе, не на перегруженном корневом разделе.

Типовые ошибки и быстрые фиксы

  • Пустой индекс при больших объёмах и коротких чанках. Увеличьте chunk_target_size и chunk_idle_period, уменьшите количество потоков (меток).
  • Большой расход RAM на индексы: проверьте кардинальность — вероятно, в метках «протекли» динамические значения. Урезайте через relabel_configs.
  • HTTP 429 (rate limit). Источник «льёт» слишком быстро. Увеличивайте лимиты аккуратно либо зажимайте шум на стороне Promtail. Иногда помогает увеличить batchwait.
  • Диск заполняется не по плану. Проверьте, включён ли compactor и верно ли стоит retention_period. Убедитесь, что пути хранения чанков и индексов те, что вы планировали.
  • Проблемы с правами/SELinux/AppArmor. Promtail должен иметь доступ на чтение. Проверьте монтирование, контексты и группы.

Наблюдаемость и бэкапы

Loki и Promtail публикуют полезные метрики: статус готовности, объём принятых записей, количество активных потоков, результаты ретраев, состояние компактора. Снимайте их и стройте алерты: переполнение диска, рост ошибок 5xx, всплески 429, падение количества записей.

Бэкап локального хранилища: индексы (index, index-cache) и чанки. На малом VDS практично делать регулярные снепшоты тома или файловый бэкап вне пиков. Согласуйте с ретеншном: нет смысла тянуть в бэкап то, что завтра удалит compactor. При ресторе соблюдайте целостность каталогов.

Как масштабировать дальше

Если нагрузка растёт, а место и retention хочется увеличивать, есть два пути:

  • Вертикально: побольше CPU/RAM/диска, более быстрый SSD, пересмотр лимитов и фильтров.
  • Горизонтально: переход к объектному хранилищу для чанков и распределённой топологии Loki. Но это уже другой класс сложности и выходит за рамки «малого VDS».

Чек-лист внедрения

  • Определите целевой ретеншн (7–14 дней) и дневной объём логов.
  • Подготовьте диск и каталоги данных для Loki.
  • Настройте Loki с boltdb-shipper, filesystem, включите compactor и лимиты.
  • Настройте Promtail с аккуратными метками и файлами позиций.
  • При внешнем приёме — прокси, файрвол, аутентификация, лимиты тела и таймаутов.
  • Проверьте готовность эндпоинтов, метрики, первые записи в индексе.
  • Поставьте мониторинг свободного места и ключевых ошибок.

Итоги

Одиночный Loki с Promtail — практичное решение для централизованных логов на малом VDS. Оно экономно по ресурсам, даёт быстрый поиск, прозрачное хранение на файловой системе и предсказуемый ретеншн через compactor. Основные «секреты» успеха — дисциплина в метках, умеренные лимиты приёма и регулярный контроль диска. Запустив такой стек однажды, вы перестанете «grep-ить» ротации и сосредоточитесь на сервисах.

Поделиться статьей

Вам будет интересно

Loki 429: too many outstanding requests при ingestion — причины и пошаговое исправление OpenAI Статья написана AI (GPT 5)

Loki 429: too many outstanding requests при ingestion — причины и пошаговое исправление

Loki 429 too many outstanding requests (ingestion) означает, что контур приёма логов не успевает: упёрлись в лимиты, взорвали labe ...
Nginx: как перестать отдавать старый контент после деплоя (cache, open_file_cache, CDN purge) OpenAI Статья написана AI (GPT 5)

Nginx: как перестать отдавать старый контент после деплоя (cache, open_file_cache, CDN purge)

После деплоя часть пользователей видит старые CSS/JS или HTML: виноваты open_file_cache, proxy/fastcgi cache, заголовки Cache-Cont ...
HTTPS timeout на мобильных: MTU/PMTUD, blackhole MTU и MSS clamping в Linux OpenAI Статья написана AI (GPT 5)

HTTPS timeout на мобильных: MTU/PMTUD, blackhole MTU и MSS clamping в Linux

Если HTTPS работает с ПК, но в LTE/5G «висит» или таймаутится, часто виноват MTU/PMTUD: крупные пакеты теряются, ICMP блокируют, п ...