Привет, Хабр! Я Максим Чудинов, инженер команды мониторинга в Cloud.ru. Одно из направлений нашей работы — обеспечение сбора логов с элементов инфраструктуры компании и их длительного хранения. Логи у нас хранятся в кластерах — их много и становится всё больше. Запускать новые и расширять существующие нужно быстро. Поэтому я разработал решение по автоматизации развертывания стека OpenSearch на виртуальных машинах с Ubuntu 20.04. О нем и расскажу в статье.
Почему мы выбрали 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: кластер хранилища, фронтенд, коллектор. Для прода производитель рекомендует конфигурацию кластера от трех нод.
Ноды — это хранилище данных и основа стека. Также частью стека являются фронтенд — для удобного поиска по индексам, и коллекторы — при необходимости предобработки и работы в распределенной инфраструктуре.
События из журналов систем и оборудования отправляются в кластер и складываются в индексы. Индексы имеют один основной шард от нуля до нескольких его реплик. Количество реплик зависит от количества нод. Кластер сам распределяет шарды таким образом, чтобы на одной ноде в один момент времени не находились основной шард и его реплика. За счет этого обеспечивается надежность хранения, а шардирование ускоряет выполнение поисковых запросов.
Описание решения
Ansible де-факто уже давно стандартный инструмент автоматизации в IT. Так что я взял его и написал две роли с плейбуком — для настройки нод кластера роль opensearch, для фронтенда роль opensearch_dashboards. Плейбук и описание кластеров сделал в отдельном репозитории.
Основой для применения ролей служит инвентарь. Как пример, в нем перечислены хосты для двух кластеров:
Сами роли применяются к группам logsearch_node и logsearch_frontend, описанным в отдельном файле.
Группы mon_logsearch_os1_dev и mon_logsearch_os2_dev являются объединением хостов соответствующих кластеров. Для каждой группы в переменных group_vars задаются специфичные для кластера значения. Также группы можно использовать для работы с отдельным кластером при выполнении плейбука с ключом –limit. Группа logsearch_logstash заложена на перспективу использования инвентаря для развертывания коллектора logstash. Вы можете развернуть в своей среде желаемые кластеры, указав соответствующие имена и адреса хостов.
Конфигурация, хотя и предполагается к применению в закрытом контуре, должна быть безопасной. Поэтому между элементами кластера устанавливаются SSL-соединения. Для них нужны предварительно сгенерированные сертификаты безопасности. О том, как самому сгенерировать сертификаты, подробно описано в документации Opensearch.
Сертификаты я вынес в групповые переменные и в будущем планирую перенести их в корпоративный Vault.
Для каждого кластера по умолчанию используются сертификаты из общих переменных. По желанию их можно переопределить в описании кластера в словаре clusters. Словарь содержит параметры всех разворачиваемых кластеров.
Кроме сертификатов для каждого кластера указываются дистрибутив, имя кластера, имя и пароль административной учетной записи, имя и пароль учетной записи для подключения фронтенда к кластеру и т. д. Пароли заданы в открытом виде для примера. В своей инфраструктуре я указываю пароли в зашифрованном с помощью 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.
Если все переменные заданы правильно, то плейбук выполняется без ошибок и мы получаем рабочий кластер. Или набор рабочих кластеров, описанных в словаре 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: можно сразу увидеть сколько места в байтах занимают события того или иного продукта и при резком росте значения сразу понятно, в какую команду идти за разъяснениями.
Еще я добавил в шаблон метрику Estimated time, которая через прогнозную функцию timeleft вычисляет, сколько времени остается до 15% свободного места в кластере. Такой прогноз позволяет проактивно в рабочем порядке расширить кластер.
Если не мешают обстоятельства, то мои метрики оказываются в коробочном шаблоне Zabbix.
Визуализацию я настроил средствами Grafana — во-первых, потому что Grafana основной рабочий инструмент дежурной смены. Во-вторых, потому что метрики разных кластеров снимаются разными инстансами Zabbix.
С помощью разных источников данных и шаблонных наименований хостов naming convention у меня получилось сделать один динамический шаблон, который отображает SLI по каждому кластеру. Кластер выбирается из выпадающего списка. Дашборд не требует изменений при добавлении или удалении кластера.
Выводы
Автоматизация — это здорово! Теперь с помощью плейбука я могу развернуть несколько кластеров в течение часа. И большую часть времени займет заполнение инвентаря и всех нужных переменных. Добавление нод в кластер — дело 10 минут. Внедренное решение сильно сократило время на деплой, а также привело конфигурацию всех кластеров к одному виду. Единообразие сильно сокращает временные затраты на траблшутинг.
Реализация деплоя через CI/CD принесла пользу команде. Раньше только я знал все нюансы установки и мог развернуть кластер. Теперь добавив описание нового кластера в переменных и выполнив merge request это может сделать каждый.
Конечно, роли не идеальны. К ним хотелось бы добавить валидацию переменных, автогенерацию документации и установку под другие операционные системы. Будем считать это домашним заданием?.
В планах на будущее: перенести все секреты и сертификаты в Vault, разработать и подключить роль logstash, собрать логи всех кластеров в один индекс и настроить предупреждения по аварийным событиям. Также предстоит договориться с командами разработки внутренних продуктов о формате событий приложений (contract), чтобы избежать ошибок несовпадения типов данных при индексировании.
Интересное в блоге:
Комментарии (3)
CTPEJIKuH
23.05.2024 12:12+3Это playbook для OpenSearch, зачем в него добавлять настройку ВМ и т.д.?
А ВМ как развертываются? Руками?
Монорепа -___-
Отвечаю, очень шустро будет отрабатывать CI/CD, когда кластеров станет десятки :)
Автор очень сильно радуется, что написал playbook для OpenSearch, при этом playbook сильно завязан на инфраструктуру cloud.ru и, соответственно, для большинства пользователей он бесполезен.
D1abloRUS
Брали бы лучше qryn + clickhouse + vector...