H Ещё раз о хранении логов в Zabbix в черновиках

Тема сбора и хранения логов в Zabbix поднималась уже не раз. И не два. Если не учитывать, что это не вполне корректный подход, серьёзно нагружающий базу, у таких способов есть еще один существенный недостаток они хранят логи целиком. И если в случае с логами роутеров или Linux с этим можно как-то смириться, то event-log Windows начинает доставлять много страданий, как серверу Zabbix, так и системному администратору, который решится его собирать и хранить. Ниже — о решении этой проблемы.

Лирическое отступление

Всех технарей уже ждут в следующем кабинете, а мы немного приостановимся, переведём дух, вынырнем из нашего уютного пушистого IT-мирка с единорогами и попытаемся определить, стоит ли овчинка выделки. Ведь есть же специализированные решения, best practices и прочие слова, напрочь убивающие фантазию и любовь к своему колхозику с заборами из костылей. Я искренне рад за людей, у которых полный ELK стек, шарды, отказоустойчивость и миллионы строк лога в секунду. Эти полубоги редко снисходят со своих сияющих вершин до нас, простых смертных. А потому им не понять простого желания мониторить всю свою инфраструктуру и при этом не быть задушенным жабой. А в мониторинг входят не только числовые показатели. Например, подсистема безопасности Windows Server манипулирует практически только логами. И если нет необходимости стрелять из пушки по воробьям, и уже есть налаженный мониторинг на основе Zabbix, то почему бы не расширить его возможности? Возможно, я сейчас скажу банальность, но мониторинг инфраструктуры краеугольный камень своевременной реакции на инциденты, так что необходимость иметь у себя в арсенале такой инструмент как сборщик и анализатор логов, совместимый с Zabbix и потребляющий минимум ресурсов, не должна обсуждаться.

За дело!

Обычно при обработке Event-лога придерживаются следующей схемы.

EvtSys — крохотный сервис, который преобразует сообщения EventLog в стандарт Syslog.
У этой связки есть, как минимум, 2 недостатка:

  • Microsoft не особенно церемонится с размерами сообщений лога, зачастую превышающих 4 кб, в которых есть и сообщение об ошибке, и справка по решению, и ссылки на развернутое решение, и кони, и цыгане, и медведи… И все такое прочее. И это при том, что, кроме самого сообщения, больше ничего не надо. В итоге, мы храним в базе тонны бесполезной информации, а место на дисках нерезиновое.
  • На каждое новое сообщение RSyslog создаёт новый форк для zabbix_sender и при большом количестве поступающих данных можно запросто заддосить себе сервер сбора логов, что тоже неприятно.

Общая концепция

У нашего нового транспортного средства будет треугольное колесо следующая схема работы.

Heka это сердце нашего пепелаца. Она почти, как Logstash, только труба пониже и дым пожиже. Зато без JRuby, а, значит, не так требовательна к ресурсам и, к тому же, потрясающе шустра. Спокойно переваривает и обрабатывает несколько тысяч строк лога в секунду. Примерно так:

При этом легко и непринужденно расширяется с помощью плагинов, что в дальнейшем и будет проделано. Общая логика работы системы такова. Поступающие сообщения EvtSys приводит к формату Syslog и передает на обработку Heka. Та парсит syslog-сообщение, выделяет внутреннюю часть сообщения (payload) и парсит далее регулярным выражением, формируя новую строку лога. Эта строка передаётся напрямую в Zabbix с помощью самописного плагина. Размещается всё необходимое на Zabbix-сервере, отдельной машине или, как в нашем случае, на Zabbix-прокси. Такой подход к работе системы устраняет оба ранее озвученных недостатка. Разберёмся подробнее, как всё это устроено внутри.

Настройка EvtSys

Не буду детально останавливаться на настройке EvtSys, это было неоднократно сделано до меня, например, тут. Отмечу лишь основные моменты, важные для работы решения. Версия EvtSys должна быть не ниже 4.5. Это связано с тем, что при инсталляции будет использоваться ключ -t. Рекомендуется брать LP версию, потому что она может отправлять сообщения больше 2 кб, что для нас актуально. Команда установки EvtSys:

Для Windows-логов я использую facility local1, вы же можете использовать то, что больше подходит именно вам. Особое внимание следует уделить параметру -t. В нём надо указать имя узла сети именно так, как оно указано в Zabbix. Это поле Heka может быть использовано для отправки сообщений правильным узлам сети в Zabbix.

Настройка конвейера обработки сообщений

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

Splitter и Filter могут отсутствовать в конвейере. У нас в конечном итоге так и будет. Какой путь пройдет строка лога, через какие фильтры и как в результате станет выглядеть, определяется условиями, основывающимися на полях внутреннего представления сообщения в Heka. Подробнее об этом можно почитать в документации, а нам сейчас надо сформировать следующий алгоритм работы Heka.

  1. Принять syslog-сообщение через UDP порт.
  2. Декодировать syslog-сообщение, выделить дополнительный тег.
  3. Распарсить текст строки лога (payload) и выделить из него ключевые параметры и значения.
  4. Сформировать на основе выделенных значений новую информативную строку лога.
  5. Закодировать строку лога в виде json-сообщения для Zabbix.
  6. Отправить закодированное сообщение в Zabbix.

Для реализации алгоритма выстраиваем функциональные блоки конвейера Heka следующим образом:

Отдельных пояснений заслуживает MultiDecoder. Он представляет собой контейнер для декодеров, которые могут выполняться либо все последовательно (именно таким образом настроено в syslog-decoder), так и до первого успешного декодирования (в events-decoder). Теперь посмотрим, как это реализовано в конфиге Heka. Чтобы не засорять основной конфиг, выносим всю конфигурацию в отдельный файл. У меня это /etc/heka/conf.d/20-eventlog.toml.

Конфиг Heka

Рассмотрим настройки каждого компонента по отдельности.

Здесь в настройках указываем, что слушать будем на всех интерфейсах и порт берём больше 1024, чтобы не иметь проблем с правами доступа к порту. Именно этот порт надо указывать в EvtSys как порт syslog-сервера. Также сразу указываем декодер, которому будем передавать принятые сообщения.

Как уже писалось выше, этот декодер является контейнером для других декодеров с двумя типами поведения (выполнить все декодеры или выполнять до первого успешного декодирования). Тип поведения задается параметром cascade_strategy и в данном случае он указывает, что надо выполнить все декодеры в порядке, указанном в параметре subs. Для отладки мультидекодера полезно использовать опцию log_sub_errors = true. При её указании Heka будет записывать ошибки декодирования sub-декодеров в свой лог.

Events-decoder сам по себе является мультидекодером, но стратегия поведения у него уже другая — first-wins. Она заставляет декодер выполняться, пока один из внутренних декодеров не вернёт успешно декодированные данные. Это помогает обрабатывать данные по нескольким шаблонам, что и будет продемонстрировано далее.

Один из стандартных декодеров, который входит в поставку Heka, по словам автора, поддерживает шаблоны логов от RSyslog. Но мне показалось, что не полностью. Обратите внимание на двойной параметр %HOSTNAME% в шаблоне лога. Это не опечатка, просто мне не удалось настроить шаблон так, чтобы параметр, который передается через -t в EvtSys, не слипался с текстом сообщения. А так мы получаем практически то, что надо, кроме одного маленького пустячка в конце имени хоста стоит двоеточие. Мы его уберём при кодировании сообщения. Вы спросите: а как же парсится значение поля Hostname? А очень просто новое значение просто перезаписывает старое.

Event-декодеры все похожи один на другой, как братья-близнецы, потому я рассмотрю только один. Отличия в остальных касаются только regexpдля парсинга и выходной строки лога.

Этот декодер прогоняет строку через регулярное выражение и при этом выделяет отдельные её части, которые можно использовать для создания дополнительных полей сообщения. Такие поля потом нам пригодятся для создания выходного сообщения. Также здесь выставляется тип сообщений (поле Type), чтобы направить их на соответствующий выход (связанный с соответствующим encoder-ом).

А теперь жемчужина нашей коллекции самописный плагин на Lua. Его работу я рассмотрю в свое время (ниже по течению текста). Здесь же достаточно написать, что он кодирует сообщение для Zabbix-а.

Выход для пересылки сообщений в Zabbix. Пропускает через себя не всё, а только сообщения с соответствующим значением в поле Type. Каждое сообщение пропускает через Encoder, который мы описали выше.

Особое внимание рекомендую обратить на параметр reconnect_after = 1. Это очень важный параметр. Дело в том, что TcpOutput содержит в себе баг и не может долго поддерживать TCP сессию. Выглядит это примерно так: в определённый момент Zabbix вместо полноценных сообщений лога начинает получать какие-то ощипки, а потом прекращается и это. Если посмотреть обмен между Heka и Zabbix через Wireshark, можно увидеть, что TcpOutput начинает бить пакеты и связь обрывается. В итоге, чтобы это не происходило, выставляется вышеуказанный параметр, который заставляет TcpOutput переподключаться после каждой отправки сообщения на Zabbix. Да, естественно, это создаёт оверхед, но я не заметил сколь-нибудь значительного роста нагрузки и на хост с Heka, и на Zabbix-прокси. Может просто сообщений мало отправляю? 😉

Отладка обработки сообщений

Для отладки конвейера я рекомендую две вещи: RstEncoder и вывод в файл. RstEncoder кодирует каждое поле сообщения текстовой строкой, что позволяет видеть, из каких полей состоит сообщение и чему они равны. Вывод в файл помогает отслеживать, что кодируется, а что пропускается и как оно кодируется. Организовать вывод в файл можно так:

Все параметры здесь понятны, поясню только назначение параметра flush_operator = OR. Он указывает, что новые порции сообщений должны дописываться к уже существующему файлу лога. Меняя encoder, можно проверять формат записываемых сообщений, а message_matcher поможет удостовериться, что сообщения имеют нужный тип. Отключая его, мы начинаем записывать всё. Иногда это помогает обнаружить ошибку в фильтре message_matcher или то, что сообщения не создаются.

Zabbix Trapper

И вот мы подошли к описанию того, как устроен кастомный encoder. Все дополнительные плагины должны лежать в /usr/share/heka/. Так как у нас это encoder, то кладем его сюда /usr/share/heka/lua_encoders/zabbix_trapper.lua. Посмотрим, что за шестерёнки крутятся у него внутри.

Библиотека CJSON должна лежать в месте, доступном Lua, поэтому я расположил её в /usr/share/heka/lua_modules/cjson.so.

Шаблон для Zabbix

Из особенностей шаблона следует отметить, что элементы данных должны быть типа Zabbix Trapper, с типом информации Журнал (лог) и ключами вида eventlog.1102.

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

И что же в итоге?

Система получилась из разряда настроил и забыл. Усердно трудится на ниве эксплуатации уже несколько месяцев, не требуя никакого обслуживания. Конечно, как и у любой хорошей системы, потенциал расширения у нее есть. Из того, что планируется в будущем:

  • Больший спектр событий.
  • Оптимизация шаблона.
  • Поддержка отправки событий пакетами (будет хорошо при большом потоке).
  • Более оптимальное открытие и закрытие TCP соединения (уменьшить оверхед).

Ну, и под занавес капельку аналитики графики очереди Zabbix-сервера при прямой записи лога в базу и после оптимизации.

Жалкая попытка включить прямое логирование видно, как очередь ненормированно растет, а потом Zabbix трескается пополам, больного едва удалось спасти. Логировался один хост с достаточно высокой нагрузкой на security-лог.

Так уже больше похоже на правду. Да, некоторое количество сообщений по-прежнему торчит в очереди, но это не проблема Windows-логов, и в целом, по общей длине очереди можно оценить прирост производительности. Вдобавок, тут мониторятся два хоста, сообщений меньше не стало, но нагрузка именно этой подсистемы мониторинга успешно теряется на общем фоне.


Источник: sohabr.net