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

Syslog-ng PE и Elasticsearch: переводим централизованный syslog с rsyslog

Как мы перевели крупного клиента с rsyslog на syslog-ng PE 3.3, подружили JSON-события с Elasticsearch и на что наступили в процессе.

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

Syslog-ng 3.3 добавил встроенную поддержку MongoDB и JSON-формат для структурированных логов

У клиента - сеть примерно из трёх сотен серверов под CentOS и RHEL, россыпь сетевых железок и несколько Windows-машин с nxlog. Логи собирались на rsyslog-агрегатор, писались в файлы, дальше периодически скриптами перекладывались куда придётся. Поиска как такового не было: когда что-то случалось, инженер шёл с grep по архивам. Нас позвали разобраться.

Задача сформулировалась так: структурированные логи, нормальный поиск, никаких лишних посредников. Elasticsearch к тому моменту уже работал у них для другой задачи, так что вопрос «куда писать» снялся сам.

Почему именно syslog-ng PE, а не rsyslog дальше. rsyslog умеет JSON и умеет elasticsearch через плагин, но конфигурация у него превращается в страшный сон довольно быстро. Syslog-ng PE 3.3 дал встроенный format-json() прямо в destination и нормальную читаемую грамматику конфига. Плюс поддержка MongoDB вышла в том же релизе - на случай если клиент захочет ещё и NoSQL-хранилище. Enterprise-версия нужна была из-за поддержки и SLA: open-source syslog-ng тут тоже заработал бы, но клиент хотел вендорскую поддержку.

Конфиг-ядро выглядит примерно так:

source s_network {
    udp(ip("0.0.0.0") port(514));
    tcp(ip("0.0.0.0") port(514) max-connections(300));
};

template t_json {
    template("$(format-json --scope rfc5424 --key .* --rekey .* --upper-case NO)");
    template-escape(no);
};

destination d_elastic {
    http(
        url("http://es-node:9200/syslog-$(year)-$(month)-$(day)/_bulk")
        method("POST")
        headers("Content-Type: text/plain")
        body("{ \"index\": {} }\n$(t_json)\n")
        flush-lines(100)
    );
};

log {
    source(s_network);
    destination(d_elastic);
    flags(flow-control);
};

Это упрощённо; в реальном конфиге добавился парсинг syslog-сообщений через syslog-parser(), несколько веток с фильтрами по facility и program, и отдельный поток для Windows-хостов, где поле MESSAGE было в другой кодировке.

Первый подводный камень - кодировка. Windows через nxlog слал UTF-16LE в поле сообщения. syslog-ng аккуратно передавал это как есть в JSON, Elasticsearch индексировал, но при поиске половина кириллицы расходилась. Добавили rewrite с set-charset("UTF-8") перед передачей - помогло, но не на всех хостах. На некоторых nxlog был настроен отдавать уже в UTF-8, а принудительная конвертация ломала их сообщения. Пришлось разбить на два source с разными обработчиками, идентифицируя Windows-хосты по HOST.

Второй камень - объём и bulk API. Elasticsearch принимает документы через bulk-интерфейс пакетами. syslog-ng PE 3.3 умеет http() destination, но тогда bulk-формат нужно собирать вручную через шаблон. Мы промахнулись с форматом на старте: забыли \n после каждого action-объекта, и Elasticsearch молчаливо отбрасывал пакеты. Дебаггинг был нервным - в ответе ES возвращал 200 OK с errors: true внутри тела, а syslog-ng это за ошибку не считал. Добавили отдельный лог bulk-ответов через curl-скрипт и тогда увидели картину.

Третий камень - ротация индексов. Мы сразу делали индексы по дням (syslog-2012-03-19), что правильно. Но template в Elasticsearch нужно было создать заранее - иначе ES сам угадывал типы полей, и одно поле priority попало как string на первый день и как long на второй, после чего поиск по нему рассыпался. Шаблон с явной маппингом поправил это.

Что в итоге. После двух недель пилота логи пошли в ES стабильно, поиск работает, команда клиента за полчаса нашла корреляцию между событиями на трёх разных хостах - то, что раньше требовало дня работы с grep. Агрегатор syslog-ng PE держит нагрузку без видимого напряжения.

Открытый вопрос - аутентификация на Elasticsearch: сейчас кластер смотрит только во внутреннюю сеть и без TLS. Для регулируемой среды это придётся закрывать отдельно, и встроенного решения в базовом ES на тот момент нет - надо либо nginx-прокси с basic auth, либо коммерческие плагины.

Подобная работа - часть того, чем мы занимаемся в рамках сопровождения инфраструктуры. Если rsyslog в вашей инфраструктуре уже превратился в коллекцию скриптов-обёрток - стоит смотреть в сторону syslog-ng или logstash, пока объём ещё управляем.

Контакт

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

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