26 ноября 2018 г.

Приветствую всех! Я работаю системным инженером в компании «Онланта». На одном из наших проектов я занимался внедрением и сопровождением Elastic Stack. Мы прошли путь от сбора логов фактически вручную до централизованного, автоматизированного процесса. Вот уже два года мы практически не меняем архитектуру решения и планируем использовать удобный инструмент в других проектах. Нашей историей его внедрения, а также некоторыми сильными и слабыми сторонами делюсь с вами в этом посте.

buev1.png

В начале 2016 года логи у наших администраторов и разработчиков были, что называется, «на кончиках пальцев», то есть инженер для работы с ними подключался с помощью SSH к хосту, где располагался интересующий его сервис, расчехлял универсальный набор из tail/grep/sed/awk и надеялся, что нужные данные удастся найти именно на этом хосте. 


buev2.png

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

Всё это даже работало, но ровно до тех пор, пока не требовалось быстро обработать большой объем данных, а требовалось это чаще всего в моменты, когда в проде уже что-нибудь свалилось.

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

Словом, всё это было весьма медленно, навевало уныние и недвусмысленно намекало на то, что пора бы озаботиться централизованным хранением логов.

Если честно, никакого сложного процесса отбора кандидатов на роль технологического стека, который бы нам это обеспечил, тогда не было: связка ELK на тот момент уже была популярна, обладала хорошей документацией, в интернете по всем компонентам имелось большое количество статей. Решение было незамедлительным: нужно пробовать.

buev3.png

Самую первую инсталляцию стека сделали после просмотра вебинара «Logstash: 0-60 in 60» на трёх виртуальных машинах, на каждой из которых запустили по экземпляру Elasticsearch, Logstash и Kibana.

Дальше мы столкнулись с некоторыми проблемами с доставкой логов с конечных хостов на серверы Logstash. Дело в том, что в то время Filebeat (штатное решение стека для доставки логов из текстовых файлов) гораздо хуже работал с большими и быстро обновляемыми файлами, регулярно протекал в RAM и в нашем случае в целом не справлялся со своей задачей.

К этому добавлялась необходимость найти способ доставлять логи серверов приложений с машин под управлением IBM AIX: основная часть приложений у нас тогда запускалась в WebSphere Application Server, работавшем именно под этой ОС. Filebeat написан на Go, более-менее работоспособного компилятора Go для AIX в 2016 году не существовало, а использовать Logstash в качестве агента для доставки очень не хотелось.

Мы протестировали несколько агентов для доставки логов: Filebeat, logstash-forwarder-java, log-courier, python-beaver и NXLog. От агентов мы ожидали высокой производительности, низкого потребления системных ресурсов, легкой интеграции с Logstash и возможности выполнять базовые манипуляции с данными силами агента (например, сборку многострочных событий).

Про сборку многострочных (multiline) событий стоит сказать отдельно. Эффективно ее можно выполнять только на стороне агента, который читает конкретный файл. Несмотря на то, что Logstash когда-то имел multiline-фильтр, а сейчас обладает multiline-кодеком, все наши попытки совместить балансировку событий по нескольким серверам Logstash с обработкой multiline на них же провалились. Такая конфигурация делает эффективную балансировку событий практически невозможной, поэтому для нас чуть ли не самым важным фактором при выборе агентов была поддержка multiline.

Победители распределились так: log-courier для машин с Linux, NXLog для машин с AIX. С такой конфигурацией мы и прожили почти год без особых проблем: логи доставлялись, агенты не падали (ну почти), все были довольны.

В октябре 2016 года была выпущена пятая версия компонентов Elastic Stack, в том числе и Beats 5.0. В этой версии над всеми агентами Beats была проделана большая работа, и мы смогли заменить log-courier (у которого к тому времени обнаружились свои проблемы) на Filebeat, который мы и используем до сих пор.

При переходе на версию 5.0 мы стали собирать не только логи, но и некоторые метрики: Packetbeat у нас начал кое-где использоваться как альтернатива записи логов HTTP-запросов в файлы, а Metricbeat собирал системные метрики и метрики некоторых сервисов.

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

В какой-то момент мы начали использовать утилиту ElastAlert от компании Yelp для рассылки алертов инженерам. А потом подумали: почему бы не интегрировать ее с нашим Zabbix, чтобы все алерты имели стандартный формат и отправлялись централизованно? Решение нашлось довольно быстро: ElastAlert позволяет вместо отправки, собственно, оповещений выполнять любые команды, что мы и использовали.

Сейчас наши правила ElastAlert при срабатывании выполняют bash-скрипт на несколько строк, которому в аргументах передают необходимые данные из события, вызвавшего срабатывание правила, а из скрипта, в свою очередь, вызывается zabbix_sender, который и отправляет данные в Zabbix для нужного узла.

Так как вся информация о том, кто и где сгенерировал событие, в Elasticsearch всегда есть, никаких сложностей с интеграцией не возникло. Например, у нас и раньше существовал механизм автоматического обнаружения серверов приложений WAS, а в событиях, которые они генерируют, всегда записывается имя сервера, кластера, ячейки и т.д. Это позволило нам использовать в правилах ElastAlert опцию query_key, чтобы условия правил обрабатывались для каждого сервера отдельно. Скрипту с zabbix_sender затем уходят точные «координаты» сервера и данные отправляются в Zabbix для соответствующего узла.

Еще одно решение, которое нам очень нравится и которое стало возможным благодаря централизованному сбору логов, – это скрипт для автоматического заведения тасков в JIRA: раз в сутки он выгребает все ошибки из логов и, если по ним еще нет тасков, заводит их. При этом из разных индексов по уникальному ID запроса в таск подтягивается вся информация, которая может пригодиться при расследовании. В результате получается эдакая стандартная заготовка с необходимым минимумом информации, которую потом инженеры могут дополнять при необходимости.

Разумеется, перед нами вставал вопрос мониторинга самого стека. Частично это реализовано с помощью Zabbix, частично с помощью все того же ElastAlert, а основные performance-метрики по Elasticsearch, Logstash и Kibana мы получаем с помощью штатного мониторинга, встроенного в стек (компонент Monitoring в X-Pack). Также на самих серверах с сервисами стека у нас установлена netdata от Firehol. Она бывает полезна, когда нужно посмотреть, что происходит с конкретной нодой прямо сейчас, в реальном времени и с высоким разрешением.

Когда-то в ней была немного поломан модуль для мониторинга Elasticsearch, мы это обнаружили, починили, добавили всяких полезных метрик и сделали пулл-реквест. Так что теперь netdata умеет мониторить последние версии Elasticsearch, включая базовые метрики JVM, показатели производительности индексации, поиска, статистику по логу транзакций, сегментам индексов и так далее. Netdata нам нравится, и нам приятно, что мы смогли сделать небольшой вклад в неё.

Сегодня, спустя почти три года, наш Elastic Stack выглядит примерно таким образом:


buev4.png

Инженеры работают со стеком тремя основными способами:

  • просмотр и анализ логов и метрик в Kibana;

  • дашборды в Grafana и Kibana;

  • прямые запросы к Elasticsearch с использованием SQL или встроенного query DSL.


Суммарно на всё это выделены такие ресурсы: 146 CPU, 484GB RAM, под хранилище данных Elasticsearch выделено 17TB.

Всего у нас в составе Elastic Stack сейчас трудятся 13 виртуальных машин: 4 машины под «горячие» ноды Elasticsearch, 4 – под «тёплые», 4 машины с Logstash и одна машина-балансировщик. На каждой горячей ноде Elasticsearch запущено по экземпляру Kibana. Так сложилось с самого начала, и пока что у нас не было необходимости перемещать Kibana на отдельные машины.

А вот решение вынести Logstash на отдельные машины оказалось, наверное, одним из самых правильных и результативных за время эксплуатации стека: высокая конкуренция за процессорное время между JVM Elasticsearch и Logstash приводила к не очень приятным спецэффектам во время всплесков нагрузки. Больше всех страдали сборщики мусора.

buev5.jpg

Мы храним в кластере данные за последние 30 дней: сейчас это около 12 млрд. событий. В сутки «горячие» ноды записывают на диск 400-500ГБ новых данных с максимальной степенью сжатия (включая данные шардов-реплик). Наш кластер Elasticsearch имеет архитектуру hot/warm, но перешли мы на неё сравнительно недавно, поэтому на «тёплых» нодах пока что хранится меньше данных, чем на «горячих».


Наша типичная нагрузка для рабочего времени:

  • индексация – в среднем 13000 rps с пиками до 30000 (без учета индексации в шарды-реплики);

  • поиск – 5200 rps.


Мы стараемся поддерживать запас по использованию CPU в 40-50% на горячих нодах Elasticsearch, чтобы без проблем переживать внезапные всплески количества индексируемых событий и тяжелые запросы от Kibana/Grafana или внешних систем мониторинга. Около 50% RAM на хостах с нодами Elasticsearch всегда доступно для page cache и off-heap нужд JVM.

За время, прошедшее с запуска первого кластера, мы успели для себя определить некоторые положительные и отрицательные стороны Elastic Stack как средства агрегации логов и поисково-аналитической платформы.

Что нам особенно нравится в стеке:

  • Единая экосистема хорошо интегрированных друг с другом продуктов, в которой есть практически всё необходимое. Beats когда-то были не очень хороши, но сейчас претензий к ним у нас никаких нет.

  • Logstash, при всей его монструозности, очень гибкий и мощный препроцессор и позволяет делать с сырыми данными очень многое (а если чего-то не позволяет, всегда можно написать сниппет на Ruby).

  • Elasticsearch с плагинами (а с недавних пор и «из коробки») поддерживает SQL в качестве языка запросов, что упрощает его интеграцию с другим софтом и людьми, которым SQL как язык запросов ближе.

  • Качественная документация, которая позволяет быстро вводить новых сотрудников на проекте в курс дела. Эксплуатация стека, таким образом, не становится делом одного человека, обладающего каким-то специфическим опытом и «тайными знаниями».

  • Отсутствие необходимости заранее знать о структуре получаемых данных многое для начала их сбора: можно начать агрегировать события как есть, а затем, по мере появления понимания, какую полезную информацию можно из них извлечь, менять подход к их обработке, не теряя «обратную совместимость». В стеке для этого есть много удобных инструментов: алиасы полей в индексах, scripted fields и т. д. 

buev6.png

Что нам не нравится:

  • Компоненты X-Pack распространяются только по модели подписок и никак иначе: если из Gold, к примеру, только поддержка RBAC или PDF-отчетов, то платить придется за всё, что в Gold есть. Это особенно расстраивает, когда, например, из Platinum нужен только Graph, а в довесок приобрести предлагается Machine Learning и ещё пачку другой функциональности, которая вам, может быть, не очень-то и нужна. Наши попытки около года назад пообщаться с отделом продаж Elastic насчёт лицензирования отдельных компонентов X-Pack ни к чему не привели, но, возможно, с тех пор что-то изменилось.

  • Довольно частые релизы, в которых каким-нибудь образом (каждый раз новым) ломают обратную совместимость. Приходится очень внимательно читать чейнжлог и готовиться к обновлениям заранее. Каждый раз нужно выбирать: остаться на старой версии, которая работает стабильно или попробовать обновиться ради новых фич и прироста производительности.


В целом же мы очень довольны нашим выбором, сделанным в 2016 году, и планируем переносить опыт эксплуатации Elastic Stack на другие наши проекты: инструменты, предоставляемые стеком, очень плотно вошли в наш рабочий процесс и отказаться от них сейчас было бы очень сложно.