Запускаем кластер OpenSearch для централизованного хранения логов (2024)

Привет, Хабр! Я Максим Чудинов, инженер команды мониторинга в Cloud.ru. Одно из направлений нашей работы — обеспечение сбора логов с элементов инфраструктуры компании и их длительного хранения. Логи у нас хранятся в кластерах — их много и становится всё больше. Запускать новые и расширять существующие нужно быстро. Поэтому я разработал решение по автоматизации развертывания стека OpenSearch на виртуальных машинах с Ubuntu 20.04. О нем и расскажу в статье.

Запускаем кластер OpenSearch для централизованного хранения логов (1)

Почему мы выбрали OpenSearch


Зачем понадобилась автоматизация и именно OpenSearch? В начале 2022 года в Cloud.ru было уже 18 кластеров Elasticsearch для хранения логов — об этом я подробно рассказывал на Big Monitoring Meetup 9. Все кластеры работали на устаревшей версии 7.9, а перейти на более свежую версию, по сумме обстоятельств, мы не могли. В качестве альтернативы выбрали OpenSearch 1.3, поскольку это полный open source и форк Elasticsearch 7.10 без серьезных отличий в работе.

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

Как форк, OpenSearch повторяет стек Elastic: кластер хранилища, фронтенд, коллектор. Для прода производитель рекомендует конфигурацию кластера от трех нод.

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

Запускаем кластер OpenSearch для централизованного хранения логов (2)

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

Описание решения

Ansible де-факто уже давно стандартный инструмент автоматизации в IT. Так что я взял его и написал две роли с плейбуком — для настройки нод кластера роль opensearch, для фронтенда роль opensearch_dashboards. Плейбук и описание кластеров сделал в отдельном репозитории.

Основой для применения ролей служит инвентарь. Как пример, в нем перечислены хосты для двух кластеров:

Запускаем кластер OpenSearch для централизованного хранения логов (3)

Сами роли применяются к группам logsearch_node и logsearch_frontend, описанным в отдельном файле.

Запускаем кластер OpenSearch для централизованного хранения логов (4)

Группы mon_logsearch_os1_dev и mon_logsearch_os2_dev являются объединением хостов соответствующих кластеров. Для каждой группы в переменных group_vars задаются специфичные для кластера значения. Также группы можно использовать для работы с отдельным кластером при выполнении плейбука с ключом –limit. Группа logsearch_logstash заложена на перспективу использования инвентаря для развертывания коллектора logstash. Вы можете развернуть в своей среде желаемые кластеры, указав соответствующие имена и адреса хостов.

Конфигурация, хотя и предполагается к применению в закрытом контуре, должна быть безопасной. Поэтому между элементами кластера устанавливаются SSL-соединения. Для них нужны предварительно сгенерированные сертификаты безопасности. О том, как самому сгенерировать сертификаты, подробно описано в документации Opensearch.

Сертификаты я вынес в групповые переменные и в будущем планирую перенести их в корпоративный Vault.

Запускаем кластер OpenSearch для централизованного хранения логов (5)

Для каждого кластера по умолчанию используются сертификаты из общих переменных. По желанию их можно переопределить в описании кластера в словаре clusters. Словарь содержит параметры всех разворачиваемых кластеров.

Запускаем кластер OpenSearch для централизованного хранения логов (6)

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

Куски для конфигурационных файлов internal_users.yml и roles_mapping.yml описаны в виде plain text и используются в шаблонах «как есть». В internal_users указаны дефолтные пользователи из коробочной установки, их можно полностью заменить на свои предпочтения. К сожалению, прекрасный способ настройки пользователей через API появился только в последних релизах второй версии Opensearch. Из-за этого потребуется предварительно где-то выполнить установку пакета opensearch или вытащить из tar-архива opensearch скрипты plugins/opensearch-security/tools, чтобы по этой инструкции сгенерировать hash пароля для каждого пользователя.

А дальше магия Gitlab CI/CD 😀. При merge в основную ветку запускается ansible docker container. В нём выкачиваются зависимости согласно requirements.yml и выполняется плейбук от имени пользователя из переменной ${SSH_USER} с ключом из переменной ${SSH_PRIVATE_KEY}. Переменные определяются в CI/CD Settings проекта.

Сначала применяется роль opensearch к хостам группы logsearch_node. Выполняется тюнинг системных параметров целевого хоста (согласно рекомендациям разработчика), установка и настройка opensearch на целевом хосте.

Первым таском установки выполняется скачивание дистрибутива в директорию /tmp целевого хоста. Это действие пришлось добавить после ситуации, когда модуль apt не смог выполнить установку из указанного url по причине таймаута. Площадки размещения бывают разные и не всегда с хорошими каналами связи. Поэтому сначала скачивание с помощью get_url, а затем локальная установка.

Затем создаются директории для индексов и снапшотов и из шаблонов копируются конфигурационные файлы. Файлы с демосертификатами удаляются и из шаблонов копируются сертификаты, заданные в переменных описания кластера. Размер java heap автоматически вычисляется как половина от фактической памяти хоста (но не более 30 ГБ) и записывается в jvm.options. Затем ждет 10 секунд для запуска сервиса и удаляет из конфигурационного файла строку с указанием хостов для выбора мастер-ноды. Этот перечень нужен только один раз для процесса cluster bootstrapping и в дальнейшей жизни кластера не пригодится. Еще при первом запуске кластер сам инициализирует внутренних пользователей и роли, используя конфигурацию плагина безопасности.

Вторым этапом применяется роль opensearch_dashboards к хостам группы logsearch_frontend. Аналогично предыдущей роли выполняется тюнинг системных параметров целевого хоста согласно рекомендациям разработчика, установка и настройка opensearch-dashboards на целевом хосте. Так же и по тем же причинам, что и в роли opensearch, первым таском установки выполняется скачивание дистрибутива в директорию /tmp целевого хоста и затем локальная установка. После из шаблонов копируются конфигурационные файлы и сертификаты.

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

Из-за отсутствия DNS в некоторых сегментах инфраструктуры в инвентаре мы используем параметр ansible_host с IP-адресом. С molecule в контейнерах такой возможности нет — адреса выдаются произвольно и сетевой доступ выполняется по именам. А мне для конфигурации каждой ноды нужно было собрать массив IP-адресов всех нод.

Чтобы роли работали и в тесте, и на виртуальных машинах, я написал код с формированием списка хостов в зависимости от значения ansible_host. Нативными командами ansible реализовать не получилось, поэтому я написал код на jinja2.

Запускаем кластер OpenSearch для централизованного хранения логов (7)

Если все переменные заданы правильно, то плейбук выполняется без ошибок и мы получаем рабочий кластер. Или набор рабочих кластеров, описанных в словаре clusters.

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

Мониторинг

Я определил несколько ключевых метрик (SLI) для верхнеуровневого мониторинга состояния кластера:

  • Health status — доступность кластера и его способность принимать новые данные;

  • Indexing rate — скорость поступления событий;

  • Indexing latency — задержка записи событий;

  • Storage utilization — величина использования хранилища кластера;

  • Product Index size — размер индексов каждого продукта источника;

  • Estimated time to 15% free space — прогнозное время до достижения 15% остатка хранилища.

Для сбора метрик я использовал Zabbix и коробочный шаблон Elasticsearch, немного доработанный для целей capaсity management. Метрики собираются штатным образом через Elastisearch API. Дополнительно выполняется поиск индексов и вычисление занимаемого места на диске (через группировку по алиасу) — Product Index size. Продукт включает в себя множество источников событий, и каждый в любой момент может значительно увеличить количество генерируемых событий. Например, корпоративный кластер Confluence, Gitlab или кластер K8s для облачных сервисов.

Мы не применяем жестких ограничений и не фильтруем события — так можно потерять действительно важные данные. Что отправить в хранилище кластера — решает команда каждого продукта. Обычно отправляют всё😀. События от каждого продукта я направляю в отдельный индекс.

Поскольку хранилище не бесконечное, важно отслеживать, какой продукт и сколько места занимает. Теперь через метрику Product Index size у меня есть Logging budget: можно сразу увидеть сколько места в байтах занимают события того или иного продукта и при резком росте значения сразу понятно, в какую команду идти за разъяснениями.

Запускаем кластер OpenSearch для централизованного хранения логов (8)

Еще я добавил в шаблон метрику Estimated time, которая через прогнозную функцию timeleft вычисляет, сколько времени остается до 15% свободного места в кластере. Такой прогноз позволяет проактивно в рабочем порядке расширить кластер.

Если не мешают обстоятельства, то мои метрики оказываются в коробочном шаблоне Zabbix.

Запускаем кластер OpenSearch для централизованного хранения логов (9)

Визуализацию я настроил средствами Grafana — во-первых, потому что Grafana основной рабочий инструмент дежурной смены. Во-вторых, потому что метрики разных кластеров снимаются разными инстансами Zabbix.

С помощью разных источников данных и шаблонных наименований хостов naming convention у меня получилось сделать один динамический шаблон, который отображает SLI по каждому кластеру. Кластер выбирается из выпадающего списка. Дашборд не требует изменений при добавлении или удалении кластера.

Выводы

Автоматизация — это здорово! Теперь с помощью плейбука я могу развернуть несколько кластеров в течение часа. И большую часть времени займет заполнение инвентаря и всех нужных переменных. Добавление нод в кластер — дело 10 минут. Внедренное решение сильно сократило время на деплой, а также привело конфигурацию всех кластеров к одному виду. Единообразие сильно сокращает временные затраты на траблшутинг.

Реализация деплоя через CI/CD принесла пользу команде. Раньше только я знал все нюансы установки и мог развернуть кластер. Теперь добавив описание нового кластера в переменных и выполнив merge request это может сделать каждый.

Конечно, роли не идеальны. К ним хотелось бы добавить валидацию переменных, автогенерацию документации и установку под другие операционные системы. Будем считать это домашним заданием😀.

В планах на будущее: перенести все секреты и сертификаты в Vault, разработать и подключить роль logstash, собрать логи всех кластеров в один индекс и настроить предупреждения по аварийным событиям. Также предстоит договориться с командами разработки внутренних продуктов о формате событий приложений (contract), чтобы избежать ошибок несовпадения типов данных при индексировании.

Интересное в блоге:

  • Как внедрить двухфакторную аутентификацию в веб-приложения, не предусматривающие ее изначально

  • Бороздим облака будущего: впечатления айтишника о конференции GoCloud

  • Как разработать браузерное расширение в Chrome на React: разбираем на примере Cloudhood

Запускаем кластер OpenSearch для централизованного хранения логов (2024)

References

Top Articles
Latest Posts
Article information

Author: Annamae Dooley

Last Updated:

Views: 5955

Rating: 4.4 / 5 (45 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Annamae Dooley

Birthday: 2001-07-26

Address: 9687 Tambra Meadow, Bradleyhaven, TN 53219

Phone: +9316045904039

Job: Future Coordinator

Hobby: Archery, Couponing, Poi, Kite flying, Knitting, Rappelling, Baseball

Introduction: My name is Annamae Dooley, I am a witty, quaint, lovely, clever, rich, sparkling, powerful person who loves writing and wants to share my knowledge and understanding with you.