Вступление

Мониторинг сложных распределенных систем может стать настоящей головной болью как с точки зрения первичной настройки метрик и поддержания их актуальности, так и с точки зрения производительности. Легче всего предотвратить большинство проблем заранее, ещё на стадии проектирования. 

Наиболее распространенные проблемы:

  • Производительность – при обработке большого количества метрик со многих узлов система мониторинга может не справляться с обработкой входящего потока данных.

  • Влияние мониторинга на работу системы – сбор метрик может быть достаточно затратен для конечной системы.

  • Излишняя сложность – система мониторинга должна быть той частью, которой вы доверяете. Чем сложнее решение, тем выше вероятность отказа, особенно в случае каких-либо изменений.

Общие рекомендации при построении системы мониторинга: 

  • Проще – лучше.

  • Уменьшайте нагрузку на сервер сбора метрик – при большом количестве узлов сложные вычисления лучше проводить на них и передавать серверу готовые значения.

  • Уменьшайте частоту сбора метрик – она должна быть минимально достаточной для выявления проблем, особенно это актуально для “тяжелых” метрик.

  • Автоматизируйте регулярно выполняемые действия – ручные действия при увеличении количества узлов неминуемо приведут к ошибкам.

Используя эти рекомендации, создадим шаблон и настроим мониторинг тестового кластера. Полученный в итоге шаблон доступен в репозитории zabbix.

Создание шаблона

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

Apache Ignite – это in-memory computing platform, платформа используемая как кэш, распределённая вычислительная система и база данных. Начать более подробное изучение продукта можно с официальной документации. Ключевые внешние показатели производительности  системы – это практически стандартный набор:

  • Загрузка CPU

  • Утилизация RAM

  • Утилизация дисков в случае persistence

  • Сеть

 Шаблоны для мониторинга данных метрик уже содержатся в zabbix, а для расширенных метрик наподобие утилизации диска есть готовые решения, доступные в репозитории zabbix, например, такое

Снижение внешних показателей, до предельных значений, будет говорить о сбоях в аппаратной части, которые распределённые системы, как правило, переживают без последствий или о полной недоступности системы, когда сервис уже недоступен. Для того, чтобы обнаруживать опасные ситуации заранее, до момента возникновения инцидента, необходимо контролировать и внутренние показатели продукта. На момент написания статьи готовых шаблонов для Apache Ignite не было, поэтому напишем свой.

Так как Ignite написан на Java, основным способом мониторинга для него будет являться JMX. Если мы просто скачаем и запустим Ignite, jmx-порт будет открыт на первом свободном порту между 49112 и 65535. Для мониторинга нас такой подход не устраивает, так как, как правило, порт настраивается заранее и способов его автоматического определения по умолчанию нет. После ознакомления со скриптом запуска становится понятно, что для того, чтобы самому указать необходимый порт, можно использовать переменную окружения IGNITE_JMX_PORT. Таким образом, выполнив команду export IGNITE_JMX_PORT=49112 и запустив узел, мы получим доступ к JMX на известном нам статическом порту.

Начиная с версии Ignite 2.10, jmx-порт задаётся по другому

Начиная с версии 2.10, это поведение изменено и в будущих версиях необходимо использовать переменную JVM_OPTS. Открыть  jmx-порт можно следующим образом: 

export JVM_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=49112 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

Особенность, на которую стоит обратить внимание, – по умолчанию в пути к mbean присутствует classloader, который будет меняться после каждого перезапуска узла. Он добавлялся для возможности запуска нескольких инстансов Ignite в рамках одной JVM, чтобы избежать конфликта метрик, но сейчас это не наш случай. Для нас же это будет значить, что zabbix будет обнаруживать метики заново после каждого перезапуска. Решить эту проблему можно, добавив JMX-опцию -DIGNITE_MBEAN_APPEND_CLASS_LOADER_ID=false, она уберёт classloader из пути. 

mbean с classloader
mbean с classloader

Ignite находится в opensource, поэтому если вы уверены, что какая-то функциональность должна работать по-другому, то вы можете принять участие в разработке. В данном случае я так считаю и сразу завёл задачу в JIRA ASF.

В результате дерево метрик будет выглядеть следующим образом:

Интерфейс jconsole
Интерфейс jconsole

Чтобы облегчить процесс добавления новых метрик себе и упростить процесс их изменения в дальнейшем, в первую очередь определим, какие объекты имеют схожую сущность. В Java для этого, как правило, используется реализация интерфейса. В нашем случае, изучая, например, метрики в разделе Thread pool, можно увидеть, что все объекты реализуют интерфейс ThreadPoolMXBean.

Описание объекта
Описание объекта

В рамках решаемой задачи нас интересует тот факт, что каждый из этих объектов будет иметь один базовый набор метрик. Применительно к шаблонам zabbix это означает, что мы можем настроить discovery rule для этих метрик, после чего сервер мониторинга будет обнаруживать все идентичные объекты на основе нашего правила и применять к ним шаблон.

Например, правило для обнаружения всех dataRegion будет выглядеть следующим образом:

Создание правила обнаружения
Создание правила обнаружения

В качестве значения {HOST.CONN}:{HOST.PORT} zabbix будет подставлять адрес, по которому доступен узел, с применённым шаблоном и указанное в качестве jmx-порта значение.

Дебаг jmx discovery

Если возникнет необходимость отдебажить обнаружение в JMX, это можно сделать с помощью команды zabbix_get. Пример discovery-запроса списка дата-регионов:

zabbix_get -s localhost -p 10052 -k '{"request":"java gateway jmx","jmx_endpoint":"service:jmx:rmi:///jndi/rmi://HOST:49112/jmxrmi","keys":["jmx.discovery[beans,\"org.apache:group=DataRegionMetrics,name=*\"]"]}' 

Результат будет выглядеть следующем образом:

{
   "{#JMXDOMAIN}":"org.apache",
   "{#JMXOBJ}":"org.apache:group=DataRegionMetrics,name=sysMemPlc",
   "{#JMXNAME}":"sysMemPlc",
   "{#JMXGROUP}":"DataRegionMetrics"
},{
   "{#JMXDOMAIN}":"org.apache",
   "{#JMXOBJ}":"org.apache:group=DataRegionMetrics,name=default",
   "{#JMXNAME}":"default",
   "{#JMXGROUP}":"DataRegionMetrics"
},{
   "{#JMXDOMAIN}":"org.apache",
   "{#JMXOBJ}":"org.apache:group=DataRegionMetrics,name=TxLog",
   "{#JMXNAME}":"TxLog",
   "{#JMXGROUP}":"DataRegionMetrics"
}

Пример шаблона метрики:

Создание метрики на основе правила обнаружения
Создание метрики на основе правила обнаружения

Параметры {#JMXNAME} и аналогичные zabbix берёт из результата discovery-запроса.

В итоге я выделил несколько групп метрик, для которых стоит использовать механизм discovery:

  • Дата-регионы

  • Кэш-группы

  • Кэши

  • Пулы потоков

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

Развертывание и автоматизация

Имея все необходимые шаблоны и понимание работы продукта, настроим мониторинг тестового стенда. Для изоляции процессов я буду использовать docker.

Как это всё будет работать:

  1. Zabbix server регистрирует новый узел после получения первого запроса от zabbix agent.

  2. Zabbix server выполняет скрипт, который добавляет jmx-порт и применяет шаблоны к новому узлу.

  3. Zabbix server начинает посылать запросы на Java gateway, который, в свою очередь, опрашивает приложение и возвращает метрики.

  4. Zabbix agent получает от сервера список собираемых активных метрик и начинает их отправлять на zabbix server.

  5. Zabbix server запрашивает значения пассивно собираемых метрик у zabbix agent.

Метрики от приложения поступают по JMX, новые узлы регистрируются после первого обращения zabbix agent к серверу.

Подробнее о том почему в п.2 используется самописный скрипт
  • Изначально было желание использовать функционал zabbix, но zabbix “из коробки” не умеет присваивать jmx port новым узлам, а без этого нельзя привязать шаблон, использующий JMX. Предложение по доработке есть в jira zabbix  с 2012 года, но оно до сих пор в open.

  • Реализация данного функционала через API возможна, но потребует создания служебного пользователя и будет более тяжелой в случае необходимости регистрации большого количества узлов.

  • Вариант через базу данных, описанный в тикете, возможно, применим для postgresql, но не работает на Oracle, MySQL и MariDB, так как в этих БД нельзя настроить триггер, который будет делать вставку в ту же таблицу, на которой он сработал.

  • Вариант с добавлением в рамках скрипта только интерфейса также не увенчался успехом, так как Zabbix не позволяет управлять порядком выполняемых операций в действии. Они выполняются в порядке создания, но внешние скрипты и отправка оповещения помещаются в отдельную очередь, обрабатываемую после выполнения всех остальных операций.

Схема тестового окружения
Схема тестового окружения

Как установить:

  1. Скачиваем и устанавливаем docker и docker-compose, если они ещё не установлены.

  2. Скачиваем все необходимые файлы из репозитория.

  3. Переходим в скачанную папку.

  4. Запускаем сборку образа: docker-compose -f docker-compose-zabbix.yml build

  5. Запускаем кластер и сервер мониторинга: docker-compose -f docker-compose-zabbix.yml up

  6. Через несколько секунд zabbix будет доступен на 80 порту. Учётная запись по умолчанию – Admin / zabbix.

Как импортировать шаблоны:

  1. Идём на вкладку Configuration > Templates > Import и импортируем шаблон ignite_jmx.xml (находится в папке, скачанной ранее). Вместе с самим шаблоном будет добавлена группа ‘Templates/Ignite autoregistration’, это название будет использоваться далее для добавления шаблонов из этой группы к новым узлам.

  2. В каждом шаблоне, который должен быть применён, указываем созданную на предыдущем шаге группу. Шаблон Template App Ignite JMX в ней уже содержится, я добавил Template App Generic Java JMX и Template OS Linux by Zabbix agent.

Создаём скрипт для авторегистрации агентов:

  1. В интерфейсе zabbix переходим на вкладку Configuration->Actions, в выпадающем списке выбираем Autoregistration actions и создаём новое действие.

  2. Даем название действию. Можем настроить условия добавления узла.

  3. В операциях добавляем пункт Add host. Это создаст новый узел в zabbix  в случае выполнения условий, указанных ранее.

  4. Добавляем запуск скрипта autoreg.php, который будет добавлять jmx-порт в настройки и применять шаблоны из указанной группы к переданному узлу. Для тех, кто разворачивает тестовый кластер из образа, он будет находиться в папке /var/lib/zabbix, для тех, кто устанавливает самостоятельно, – в репозитории, указанном выше. Запускаться в моём случае он будет командой

php /var/lib/zabbix/autoreg.php {HOST.HOST} 'Templates/Ignite autoregistration' '{HOST.METADATA}'

Должно получиться так:

Добавление запуска скрипта в правило авторегистрации
Добавление запуска скрипта в правило авторегистрации

Если всё было сделано корректно, узлы должны появиться в zabbix с настроенным jmx-портом и применёнными шаблонами из группы. Если что-то пошло не так, первое, что рекомендую проверить, – Reports->Audit log.

Результаты и куда двигаться дальше

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

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

Помимо Apache Ignite в вашем решении, вероятно, будет присутствовать ещё немало компонентов, таких как клиентские приложения, фронтенды, очереди, сетевое оборудование, СХД и тому подобное, – всё это также требует мониторинга, без которого часть аварийных ситуаций не будет вовремя обнаружена.

Для многих будут актуальны вопросы безопасности. JMX и zabbix поддерживают как передачу метрик, так и работу интерфейса с использованием SSL-соединения. Но это уже отдельная большая тема.

Что почитать

  1. Site Reliability Engineering

  2. Zabbix documentation portal

  3. Готовый инструмент для мониторинга и управления Ignite и Gridgain