ADG Оставить заявку
Блог Системное администрирование 4 мин чтения

journald и rsyslog: почему они работают параллельно и как это использовать для ELK

После перехода на systemd обнаружили: journald и syslog не заменяют друг друга. Настраиваем форвардинг в rsyslog, разбираемся с ротацией и сохраняем совместимость с ELK.

Контекст момента

Переход на systemd меняет практику работы с логами: journald пишет бинарный журнал, но rsyslog при этом продолжает работать параллельно

Когда мы переводили первые серверы на CentOS 7, про journald написали вскользь: мол, journalctl -u nginx удобнее grep, но /var/log/messages никуда не делся. Разобраться глубже руки не доходили - работало, и ладно. Но после того как мы развернули ELK-стек для централизованных логов и начали переводить туда серверы на Debian 8 и CentOS 7, вопрос встал конкретнее: а что именно попадает в Logstash, из journald или из rsyslog, и одно и то же ли это?

Оказалось - не совсем одно и то же. И разобраться стоило заранее.

Два журнала живут рядом

На свежем CentOS 7 или Debian 8 с systemd одновременно работают два механизма сбора логов.

journald - часть systemd, пишет бинарный журнал в /var/log/journal/. Собирает stdout/stderr всех сервисов, управляемых через unit-файлы, плюс сообщения ядра, плюс то что приложения шлют через syslog-сокет. Читается через journalctl. Формат бинарный - руками не откроешь, зато хранит структурированные поля, приоритет, юнит-источник, PID, метку времени с микросекундами.

rsyslog - тот же rsyslog что был до systemd. На CentOS 7 он стоит и запущен по умолчанию. Читает сообщения из того же сокета /run/systemd/journal/syslog, который journald специально предоставляет для совместимости, и пишет текстовые файлы в /var/log/.

То есть схема такая: приложение пишет в сокет -> journald принимает и сохраняет в бинарный журнал -> параллельно форвардит в rsyslog через /run/systemd/journal/syslog -> rsyslog пишет в /var/log/messages и всё остальное. Это не дублирование ошибки в архитектуре, это осознанная совместимость. Но несколько вещей из этой схемы неочевидны.

Что теряется при форвардинге

Journald хранит структурированные поля: _SYSTEMD_UNIT, _PID, PRIORITY, SYSLOG_IDENTIFIER и ещё десяток. Когда rsyslog получает эти сообщения через syslog-сокет, он видит только то, что умещается в стандартный syslog-формат - приоритет, метку времени, имя хоста, тег и текст сообщения. Остальные поля journald теряются.

Для большинства задач это не критично. Но если нужно в ELK фильтровать по конкретному systemd-юниту через rsyslog - это поле уже не придёт. Придётся парсить тег или имя процесса.

Второй момент: по умолчанию в journald настройка ForwardToSyslog=yes в /etc/systemd/journald.conf. Значит форвардинг включён. Но это можно выключить, и тогда rsyslog перестанет получать системные события вообще. Проверить текущее состояние:

grep ForwardToSyslog /etc/systemd/journald.conf

Форвардинг из rsyslog в Logstash

Для ELK мы используем rsyslog на хостах как форвардер: он читает системные логи и шлёт в Logstash по TCP. Конфиг простой, добавляем файл в /etc/rsyslog.d/:

# /etc/rsyslog.d/50-logstash.conf
*.* @@logstash.internal:5514;RSYSLOG_SyslogProtocol23Format

@@ - TCP (одна @ - UDP), RSYSLOG_SyslogProtocol23Format - RFC 5424, который Logstash понимает из коробки через встроенный syslog-input.

На стороне Logstash input-секция:

input {
  syslog {
    port => 5514
    type => "syslog"
  }
}

Всё. Работает. Единственная тонкость которую поймали: если на хосте rsyslog форвардит через UDP и Logstash на другом конце перегружен, сообщения просто теряются без ошибок. На TCP хотя бы будет очередь и backpressure. Для логов которые важны - только TCP.

journald как источник напрямую

Есть альтернатива rsyslog - читать из journald напрямую через journalbeat или systemd-journal-gatewayd. Мы пробовали journalbeat (неофициальный, написан сообществом) - работает, но инструмент молодой и без нормальной документации. На нескольких хостах поставили как эксперимент, на остальных остался rsyslog - надёжнее и предсказуемее.

Ротация: logrotate или journald - не одно и то же

Это отдельная история. logrotate управляет текстовыми файлами в /var/log/ - это rsyslog-мир. journald управляет своим бинарным журналом сам, через параметры в journald.conf.

Типичная ошибка: настроить logrotate для /var/log/journal/ - это не работает так как ожидается. journald не следит за этой директорией через inotify в смысле «кто-то ротировал файл, давай переоткроем». Ротация journald делается через:

journalctl --vacuum-size=500M   # удалить старые файлы пока журнал не станет <= 500M
journalctl --vacuum-time=30d    # удалить записи старше 30 дней

Или настраивается постоянно через journald.conf:

[Journal]
SystemMaxUse=500M
MaxRetentionSec=30day

После изменения конфига - systemctl restart systemd-journald. Мы это прописали в Ansible-роль для базового провизионирования сразу: без ограничения journald может спокойно занять 10% диска - это дефолт, и на сервере с 50 ГБ под /var это 5 ГБ под логи без предупреждения.

logrotate при этом никуда не уходит - он продолжает ротировать /var/log/messages, /var/log/secure, nginx-логи, postgresql-логи. Просто это два отдельных инструмента для двух отдельных хранилищ.

Наша текущая схема на серверах с CentOS 7:

  • journald: SystemMaxUse=500M, MaxRetentionSec=14day - оперативная диагностика через journalctl
  • rsyslog: форвардит всё в Logstash по TCP, плюс пишет локальные файлы
  • logrotate: ротирует текстовые файлы в /var/log/ по старой схеме - daily, 7 копий, gzip
  • ELK: получает логи через rsyslog-форвардинг, хранит 30 дней

Дублирование? Немного. Зато journald доступен локально без сетевых зависимостей - если ELK недоступен или Logstash упал, journalctl на хосте всё равно показывает что происходило. Это не лишнее.

Что осталось неудобным

Честно: journald как чёрный ящик всё ещё немного раздражает. Текстовый файл можно открыть, передать по scp, проанализировать любым инструментом. С бинарным журналом без journalctl делать нечего. На хостах где нет доступа к сети и надо передать логи - экспорт через journalctl --output=export или --output=json, потом уже работаешь с текстом.

Привыкаем постепенно. Пока - rsyslog остаётся как страховка.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.