MAATRIX / Блог / Сбор логов с нескольких серверов: с чего начать

Сбор логов с нескольких серверов: с чего начать

MAATRIX

Инфраструктура выросла с одного сервера до пяти-десяти, а логи как лежали локально на каждой машине, так и лежат. Пока всё работает — это не мешает. Но в момент реального инцидента, когда нужно понять, какой из серверов отвечает медленно или на каком из них упала служба, приходится вручную заходить по SSH на каждый и вручную же листать journalctl или /var/log. Разберём, как собрать логи со всех серверов в одном месте и почему это стоит сделать раньше, чем вы думаете.

Проблема: логи разбросаны, а инцидент один

Пока у вас один сервер, tail -f /var/log/nginx/error.log решает любую проблему за секунды. Как только серверов становится несколько — а тем более когда за приложением стоит балансировщик и запрос может уйти на любой из трёх бэкендов — картина меняется.

Типичный сценарий: пользователи жалуются, что сайт иногда отдаёт 502. Вы не знаете заранее, на каком именно сервере это произошло — балансировщик распределяет нагрузку, и упасть могла любая из нод. Приходится:

  1. Подключаться по SSH к серверу №1, смотреть логи nginx и приложения за нужный промежуток времени.
  2. Ничего не найти, подключаться к серверу №2.
  3. Повторить для серверов №3, №4 — и так, пока не найдётся тот самый, где реально что-то сломалось.
  4. При этом на каждом сервере свой часовой пояс в логах, свой формат, и сопоставлять записи из разных источников приходится вручную, в голове.

Каждый такой обход — это 5-15 минут потерянного времени, а инцидент тем временем продолжается. Проблема не в том, что логов нет — они есть, и подробные. Проблема в том, что они физически разбросаны, и добраться до нужной строчки означает сначала угадать, на какой машине она лежит.

Это же касается менее драматичных задач: посчитать, сколько всего было ошибок определённого типа за сутки по всей инфраструктуре, разом посмотреть все обращения одного IP-адреса ко всем серверам, найти, с какого момента на всех нодах разом начали расти тайм-ауты к базе данных. Без централизации каждый такой вопрос — это N ручных проверок вместо одной.

Принцип: агент на каждом сервере, хранилище — одно

Решение не требует изобретения велосипеда, схема стандартная и работает одинаково что для трёх серверов, что для тридцати:

  • На каждом сервере, где есть логи, ставится лёгкий агент сбора — процесс, который следит за локальными файлами логов (или журналом systemd) и пересылает новые записи дальше по сети.
  • Все агенты отправляют данные в одно центральное хранилище — отдельный сервер (или сервис), где логи со всех источников складываются вместе и индексируются для поиска.
  • Доступ к логам идёт не через SSH на каждую машину, а через один веб-интерфейс, где можно искать сразу по всей инфраструктуре: «покажи все ошибки уровня error на любом сервере за последний час» — это один запрос, а не десять сессий SSH.

Агент — это не сборщик логики и не парсер бизнес-данных, это просто транспорт. Он читает файл, добавляет метаданные (имя хоста, имя сервиса, время) и отправляет пакет по сети — обычно по TCP/UDP на syslog-совместимый порт, по HTTP на API, либо через специализированный протокол вроде gRPC у Loki. Нагрузка на CPU и память у таких агентов минимальна: promtail или vector в режиме простого чтения файлов обычно занимают единицы-десятки мегабайт памяти.

Разница между инструментами — в том, что происходит на стороне хранилища и как строится поиск, но сам принцип «источник → агент → сеть → центральное хранилище» одинаков что для Graylog, что для Grafana Loki, что для ELK-стека.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Шаг 1. Выбор центрального хранилища логов

Первое решение — куда именно будут стекаться логи. Здесь не нужно сразу строить отказоустойчивый кластер на три ноды: если у вас 3-10 серверов и логов немного (условно, до нескольких гигабайт в день), с задачей справится один выделенный сервер под хранилище логов, а не сложная распределённая система.

Три реалистичных варианта на конец 2026 года:

ВариантКогда подходитТребования к ресурсам
Grafana LokiЛоги + метрики уже в Grafana, хочется единого дашборда, не нужен полнотекстовый поиск по всему телу сообщенияЛегче остальных, экономит диск за счёт индексации только по меткам
GraylogНужен полноценный поиск по содержимому логов, готовые дашборды, ролевой доступ для командыТребует Elasticsearch/OpenSearch и MongoDB под капотом, ресурсоёмче Loki
ELK/OpenSearch напрямуюУже есть опыт с Elasticsearch, нужна максимальная гибкость запросовСамый прожорливый по памяти вариант из трёх

Если у вас уже развёрнут связанный стек наблюдаемости, который объединяет метрики, трейсы и логи в одном инструменте — часто такая платформа уже включает приём и хранение логов «из коробки», и заводить для этого отдельный сервис не требуется. Проверьте, что уже стоит в инфраструктуре, прежде чем поднимать новый компонент с нуля.

Для старта на 3-5 серверов достаточно одной VPS с 4 ГБ RAM под Loki либо 8 ГБ под Graylog — это не производственная нагрузка на тысячи запросов в секунду, а разумный первый шаг. Расширять хранилище (диск, память, при необходимости — вынос на отдельный кластер) можно позже, когда объём логов реально это потребует.

Практический пример: поднимаем Loki в Docker Compose на выделенном сервере.

# docker-compose.yml на центральном сервере логов
version: "3.8"
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.2.0
    ports:
      - "3000:3000"
    volumes:
      - ./grafana-data:/var/lib/grafana
    depends_on:
      - loki

После docker compose up -d порт 3100 должен принимать записи от агентов с других серверов, а Grafana на порту 3000 — служить единым интерфейсом для поиска. Порт 3100 стоит закрыть файрволом от внешнего мира и открывать только для IP-адресов ваших серверов-источников (или заворачивать через VPN/WireGuard между машинами — так трафик логов не идёт через открытый интернет).

Шаг 2. Установка агента сбора на каждом существующем сервере

Второй шаг — на каждом сервере, логи которого нужно видеть централизованно, ставится агент, настроенный слать данные на адрес хранилища из шага 1. Это единственное действие, которое повторяется на всех машинах — и его удобно выполнить через любой инструмент управления конфигурацией (Ansible, простой shell-скрипт по SSH), чтобы не настраивать каждый сервер вручную заново.

Пример для связки с Loki — агент Promtail, который читает системные логи и логи nginx:

# /etc/promtail/config.yml — ставится на КАЖДОМ сервере-источнике
server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://IP_ЦЕНТРАЛЬНОГО_СЕРВЕРА:3100/loki/api/v1/push

scrape_configs:
  - job_name: nginx-error
    static_configs:
      - targets: [localhost]
        labels:
          job: nginx
          host: web-01          # уникальное имя каждого сервера
          __path__: /var/log/nginx/error.log

  - job_name: app-error
    static_configs:
      - targets: [localhost]
        labels:
          job: app
          host: web-01
          __path__: /var/log/myapp/error.log

Ключевой момент — метка host должна быть уникальной для каждого сервера (web-01, web-02, db-01 и так далее). Именно по ней потом в интерфейсе поиска отличают, откуда пришла конкретная запись, и строят фильтры вида «покажи ошибки только с серверов группы web-*».

Если стек — Graylog, вместо Promtail на каждом сервере обычно ставится Filebeat или rsyslog с пересылкой по GELF/syslog:

# /etc/rsyslog.d/60-forward.conf — минимальный вариант через системный rsyslog
*.* @@IP_ЦЕНТРАЛЬНОГО_СЕРВЕРА:5140

Двойной @@ означает TCP (надёжнее, чем UDP с одним @, при пересылке по сети — пакеты не теряются молча). Это самый простой способ начать без установки дополнительного агента, если сервер уже использует rsyslog — но он ограничен возможностями самого rsyslog и подходит скорее для системных логов, чем для логов конкретного приложения.

После установки агента на первом сервере стоит сразу проверить, что записи доходят до хранилища, и только потом тиражировать конфиг на остальные — отличаться между серверами должна только метка host, всё остальное можно сохранить как единый шаблон.

Шаг 3. Структурированный формат вместо простого текста

Когда логи только начинают собираться в одном месте, они часто остаются в том виде, в каком писались изначально — свободным текстом вроде:

2026-08-29 14:32:07 ERROR Failed to connect to database: timeout after 5000ms

Такую строку можно найти по подстроке, но сложно фильтровать и агрегировать: нельзя одним запросом вычленить только ошибки конкретного типа отдельно от таймаутов конкретной длительности — придётся парсить текст регулярками уже на стороне поиска.

Там, где это возможно — в первую очередь в собственном приложении — стоит перейти на структурированные логи в формате JSON с явными полями:

{"timestamp":"2026-08-29T14:32:07Z","level":"error","service":"api","event":"db_connect_failed","timeout_ms":5000,"host":"web-01"}

Разница на практике: вместо поиска по подстроке "Failed to connect" вы получаете возможность фильтровать точно — level=error AND event=db_connect_failed AND timeout_ms>3000 — и строить агрегации (сколько таких ошибок за час, на каких хостах чаще). Большинство современных логирующих библиотек (zap и zerolog для Go, structlog для Python, встроенный JSON-форматтер в Winston для Node.js) умеют писать в этом формате из коробки — обычно это вопрос смены форматтера, а не переписывания логики логирования.

Для системных логов и логов сторонних сервисов (nginx, PostgreSQL) полная структуризация не всегда реалистична и не обязательна с первого дня — можно включить JSON-формат логов там, где это конфигурируется одной строкой (например, log_format json_combined в nginx), а остальное оставить как есть и парсить на стороне хранилища через готовые парсеры (grok-паттерны, конвейеры обработки в Loki/Graylog).

С чего начать на практике: не всё и сразу

Соблазн — сразу построить идеальную систему, которая с первого дня охватывает все логи со всех серверов: системные журналы, логи всех приложений, логи баз данных, логи сетевого оборудования. На практике это растягивает внедрение на недели и часто заканчивается тем, что проект бросают на середине.

Более рабочий подход:

  1. Начните с самого критичного. Логи ошибок приложения и логи веб-сервера (nginx/Apache access и error) на 1-2 самых важных серверах — обычно именно там находится причина большинства реальных инцидентов.
  2. Проверьте, что это действительно работает — записи доходят до хранилища, поиск по ним быстрый и понятный, метка host корректно проставляется.
  3. Расширяйте охват по мере необходимости, а не по плану «на бумаге». Столкнулись с инцидентом, где не хватило логов конкретного сервиса — добавьте именно его на следующий день. Так система растёт вслед за реальными задачами, а не опережает их.
  4. Только после этого переходите к менее критичным источникам: логам системных служб, логам cron-задач, аудиту авторизаций.

Такой поэтапный запуск занимает часы, а не недели, и уже после первого шага даёт ощутимую пользу: диагностика проблемы на нескольких серверах перестаёт требовать обхода каждого из них по отдельности. Разница между «идти по SSH на все пять серверов» и «ввести один запрос в общем интерфейсе» — это ровно то время, которое в момент реального инцидента стоит дороже всего.

Отдельный практический момент: заведите ротацию и retention с самого начала, а не после того, как диск на сервере хранилища закончится. Логи со всех серверов в одном месте растут быстрее, чем локальные логи на одной машине — потому что суммируются данные сразу от всех источников.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Сколько ресурсов нужно центральному серверу логов на старте?

Для 3-5 серверов и умеренного трафика логов (условно, до пары гигабайт в день) хватает VPS с 4 ГБ RAM под Loki или 8 ГБ под Graylog — это ориентир, а не точная цифра, реальное потребление зависит от объёма и глубины хранения (retention).

Нужно ли сразу собирать абсолютно все логи со всех серверов?

Нет — начните с логов ошибок приложения и веб-сервера на самых важных серверах, расширяйте охват по мере реальной необходимости, а не по заранее составленному исчерпывающему списку.

Что делать, если сеть между серверами и центральным хранилищем нестабильна?

Использовать TCP вместо UDP для пересылки (агенты вроде Promtail и Filebeat это делают по умолчанию) и держать локальный буфер — большинство агентов умеют дозаписывать данные при временной недоступности хранилища и не терять их.

Обязательно ли переводить все логи в JSON сразу?

Нет — начните со своего приложения, где это дешевле всего внедрить, а логи сторонних сервисов подключайте к структурированному формату постепенно, там где это конфигурируется без переписывания кода.

Можно ли собирать логи с серверов в разных локациях (RU/US/UK) в одно хранилище?

Да, технически ограничений нет — важно защитить канал передачи (VPN или TLS между агентом и хранилищем) и учесть задержку сети при выборе TCP-таймаутов в конфиге агента.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →