Zabbix из коробки обладает большим многообразием интеграций с различными системами. Недавно этот список расширился добавлением в него Event-Driven Ansible. Благодаря совместному использованию этих двух систем Вы можете настроить полную автоматизацию ИТ процессов. Zabbix в данном случае будет являться источником событий, а Ansible в свою очередь их исполнителем. В этой статье будет рассмотренно как настроить отправку событий из Zabbix в Event-Driven Ansible.
Table of Contents
В настоящее время Event-Driven Ansible доступен в виде предварительной версии для разработчиков. Это решение для автоматизации, где основанием для выполнения каких-либо действий является получение события. Каждое новое событие будет автоматически сопоставлено с указанными условиями. Если они выполняются, то rulebook запустит указанное действие. Это поистине удобно, когда рутинные задачи выполняются без вашего участия. Вы можете позволить себе уделить внимание более важным, возможно даже творческим, вещам. Кроме того, у системы автоматизации нет обеденного перерыва, рабочих часов и выходных дней, поэтому ее работа в режиме 24/7 позволяет ускорить выполнение ключевых ИТ процессов.
Как отправить событие из Zabbix в Event-Driven Ansible?
Интеграция с Event-Driven Ansible в Zabbix реализована посредством webhook. Данное решение позволяет использовать всю гибкость возможностей по настройке оповещений со стороны Zabbix при помощи действий. Одновременно с этим webhook является уже привычным инструментом для пользователей.
Данный способ оповещения поставляется в Zabbix из коробки. Если в Вашей инсталляции его нет, Вы можете импортировать его себе по этой ссылке.
Со стороны Event-Driven Ansible используется плагин webhook из стандартной коллекции ansible.eda. Если в вашей системе нет этой коллекции, её можно получить, выполнив следующую команду:
ansible-galaxy collection install ansible.eda
Что ж, рассмотрим пошагово процесс отправки более подробно на примере из схеме ниже.
Со стороны Zabbix:
-
Прежде всего, в Zabbix возникает событие.
-
Zabbix server сверяет созданное событие на соответствие условиям в действиях. Если выполняются все условия для отправки события в Event-Driven Ansible, то происходит переход к следующему этапу: выполнение настроенных в действии операций.
-
В качестве операции настроена отправка через способ оповещения «Event-Driven Ansible». В качестве пункта назначения берется адрес, указанный у сервисного пользователя для способа оповещения «Event-Driven Ansible»
-
Вся собранная информация о событии и получателе передается скрипту для генерации JSON и отправки его на указанный адрес.
Со стороны Ansible:
-
Отправленное из Zabbix событие поступает на указанный адрес и порт. Данный порт прослушивается webhook плагином.
-
После получения события ansible-rulebook начинает по порядку проверять условия для определения: соответствует ли данное событие указанным правилам и требуется ли что-либо выполнять в связи с данным событием.
-
Если условия для какого-либо из правил соответствуют поступившему событию, то происходит запуск указанного действия. Это может быть как и одиночная команда, так и playbook.
Если у Вас возник вопрос, как же это все настроить, то не волнуйтесь, сейчас мы рассмотрим процесс настройки с каждой из сторон.
Настройка отправки оповещений подробно расписана на странице интеграции Zabbix с Ansible. Если кратко, то необходимо:
-
Импортировать способ оповещения требуемой версии, если его нет в Вашей системе.
-
Создать служебного пользователя. Метод оповещений выбрать «Event-Driven Ansible» и указать в качестве адресата в формате
xxx.xxx.xxx.xxx:port
адрес Вашего сервера и порт, который будет прослушивать webhook плагин. В данной статье в качестве порта используется значение 5001. Это значение еще понадобится при настройке ansible-rulebook. -
Настроить действие для отправки оповещений. В качестве операции указать отправку через «Event-Drive Ansible». В качестве получателя указать созданного на прошлом шаге сервисного пользователя.
Прежде всего, в Вашей системе должен быть установлен eda-server. Подробную инструкцию по установке и настройке Вы можете найти здесь.
После установки eda-server можно сделать свой первый ansible-rulebook. Для этого необходимо создать файл с расширением «yml». Назовите его zabbix-test.yml и поместите в него следующий код:
---
name Zabbix test rulebook
hosts all
sources
ansible.eda.webhook
host0.0.0.0
port5001
rules
name debug
condition event.payload is defined
action
debug
Ansible-rulebook, как Вы уже заметили, использует формат yaml. Блок имеет 4 параметра: name, hosts, source, rules.
Параметры Name и Host
Первые 2 параметра являются типичными для пользователей Ansible. Name содержит название данного rulebook. Hosts указывает к каким хостам применяется данный ansible-rulebook. Хосты обычно перечислены в inventory файле, с которым более подробно ознакомиться по этой ссылке. Однако, самыми важными являются два оставшиеся параметра: source и rules, поэтому на них можно остановиться чуть более подробно.
Параметр Source
В Source указывается источник событий для ansible-rulebook. В качестве источника событий указан плагин «ansible.eda.webhook». Это означает, что при запуске ansible-rulebook запускается webhook плагин, который начинает слушать порт и принимать входящие события. Поэтому для работы ему необходимо указать 2 параметра:
- Параметр «host». В нем указали значение 0.0.0.0, то есть прием сообщений будет идти со всех адресов.
- Параметр «port». В качестве значения указали 5001. Соответственно данный плагин будет принимать все входящие сообщения, поступившие именно на этот порт. Значение параметра «port» должно совпадать с тем, какой порт был указан при создании сервисного пользователя в Zabbix.
Параметр Rules
В Rules содержится набор правил с условиями, которые будут сопоставляться с полученным событием. Если условие соответствует поступившему событию, то будет выполнено действие, указанное в блоке actions. Поскольку данный ansible-rulebook нужен для ознакомления, достаточно указать только одно правило. Для простоты в качестве условия можно указать event.payload is defined
. Это простейшее условие означает, что правило будет проверять наличие поля «event.payload» в полученном событии. В свою очередь, в действии можно указать debug и тогда ansible-rulebook покажет полный текст полученного события. При помощи debug можно понять какие поля будут передаваться в событии и настроить необходимые для Вас условия.
Параметры name, host, source влияют только на источник событий. В данном случае в качестве источника событий всегда будет выступать webhook плагин. Соответственно, данные параметры меняться не будут и во всех последующих примерах они будут опущены. В качестве примера будут указано только значение параметра rules.
Для запуска Вашего ansible-rulebook можно использовать команду:
ansible-rulebook --rulebook /path/to/your/rulebook/zabbix-test.yml –verbose
Появление в выводе строки Waiting for events
означает успешную загрузку ansible-rulebook и готовность получать события.
Ansible-rulebook предоставляет широкие возможности по обработке поступающих событий. В статье будут рассмотрены только некоторые из возможных условий и сценариев применения ansible-rulebook. Однако, более подробно со списком всех поддерживаемых условий и примерами можно ознакомиться на официальной странице документации. Для общего понимания принципов работы с ansible-rulebook можно посмотреть документацию по этой ссылке.
Рассмотрим как построить условия для фильтрации события более подробно на нескольких примерах.
Пример №1
Необходимо запустить playbook для изменения конфигурации NGINX в филиале в Берлине при получении события от Zabbix. Узел находится в трех группах:
- Linux servers
- Web servers
- Berlin.
И имеет 3 тега:
- target: nginx
- class: software
- component: configuration.
Все указанные параметры вы можете увидеть на схеме ниже:
В левой части можно увидеть узел с настроенным мониторингом. Для определения принадлежности отправленного события к данному правилу важны два поля: группы узлов и теги. Именно по ним можно проверить, что событие связано с требуемым сервером и относится к конфигурации. Согласно рассмотренной ранее общей схеме работы, все данные о событии поступают в скрипт способа оповещения, где происходит генерация JSON и последующая отправка. На стороне Ansible событие принимает webhook и передает в rulebook для проверки условий. В случае соответствия события всем условиям будет выполнено указанное действие, в данном случае это запуск playbook.
В соответствии с указанными настройками групп узлов и тегов, событие при отправке будет содержать информацию как в блоке ниже. Однако, из вывода интересны только два поля: «host_groups» и «event_tags».
{
, "host_groups": [
"Berlin",
"Linux servers",
"Web servers"],
"event_tags": {
"class": ["os"],
"component": ["configuration"],
"target": ["nginx"]},
}
Поиск по группам узлов
Итак, прежде всего, нужно определить, что узел является веб сервером. Это можно понять по наличию у узла группы «Web servers» на схеме выше. Второй момент, который можно определить согласно схеме, что узел имеет так же и группу «Berlin». Поэтому для фильтрации события на стороне Event-Driven Ansible будут создаваться условия для проверки наличие двух групп узлов «Web servers»и «Berlin» в полученном событии. Поле «host_groups» в полученном JSON является списком. Поэтому для поиска элемента в списке будет использоваться конструкция is select
.
Поиск по значению тегов
Третьим условием для поиска является принадлежность данного события к конфигурации. Это можно понять по наличию у события тега «component» со значением «configuration». Однако, поле event_tags в полученном JSON стоит рассмотреть более подробно. Оно является словарем с именем тега в качестве ключа, поэтому в условиях на стороне ansible-rulebook можно обратиться к каждому тегу в отдельности. Кроме того, каждый тег всегда будет содержать список из значений данного тега, так как имена тегов могут дублироваться с разными значениями. В связи с этим для поиска по значению тега, всегда можно обращаться к конкретному тегу и использовать поиск элемента в списке при помощи уже знакомой конструкции is select
.
Для решения данного примера укажите следующий блок rules в ansible-rulebook:
rules
name Run playbook for office in Berlin
condition event.payload.host_groups is select("==","Web servers") and
event.payload.host_groups is select("==","Berlin") and
event.payload.event_tags.component is select("==","configuration")
action
run_playbook
name deploy-nginx-berlin.yaml
Решение
В поле condition указано 3 элемента и все эти условия Вы можете увидеть в правой части схемы. Во всех трех случаях используется конструкция is select
и проверяется наличие требуемого элемента в списке.
В первых двух условия проверяется наличие требуемых групп узлов в списке групп по пути «event.payload.host_groups». На схеме Вы можете увидеть зеленой пунктирной линией как первые два условия соотносятся с группами на узле в Zabbix. По условию задачи узел должен принадлежать обоим искомым группам и поэтому между условиями указана логическая операция and
.
В последнем условии поле event_tags является словарем. Поэтому можно обратиться к тегу, указав его имя в пути «event.payload.event_tags.component» и проверить наличие «configuration» среди значений тега. На схеме это изображено самым последним условием и при помощи пунктирной линии соотнесено с тегами на узле.
Поскольку по условию задачи требуется выполнение всех трех условий, то между ними снова указана логическая операция and
.
Блок action
В случае выполнения всех трех условий будет запущено указанное действие. В данном случае это запуск playbook при помощи конструкции run_playbook
. Ниже в блоке name указано имя запускаемого playbook: deploy-nginx-berlin.yaml
Пример №2
Рассмотрим пример с использованием стандартного шаблона Docker by Zabbix agent 2. Для событий по триггеру «Container {#NAME}: Container has been stopped with error code» администратором дополнительно настроено действие для отправки в Event-Driven Ansible. Предположим, что в случае остановки контейнера «internal_portal» со статусом «137», его перезапуск требует предварительной подготовки, логика которой указана в playbook.
Подробнее с поставленной задачей можно ознакомиться на схеме выше. В левой части находится узел с настроенным мониторингом. Созданное событие из примера будет иметь множество параметров, но для данной задачи интересны только 2: оперативные данные и все теги данного события. Согласно ранее рассмотренной общей концепции, все эти данные поступят в скрипт способа оповещения, который сформирует JSON для отправки в Event-Driven Ansible. На стороне Ansible полученное событие будет проверено на соответствие указанным условиям. В случае, если все условия выполняются, будет запущен playbook.
В блоке ниже Вы можете увидеть часть JSON, который отправляется в Event-Driven Ansible. Для решения поставленной задачи из всего вывода важны только два поля: «event_tags» и «operation_data».
{
, "event_tags": {
"class": ["software"],
"component": ["system"],
"container": ["/internal_portal"],
"scope": ["availability"],
"target": ["docker"]},
"operation_data": "Exit code: 137",
}
Поиск по значению тегов
Первым делом, надо определить, что событие связано с требуемым контейнером. Его имя отображается в теге «container». Соответственно для этого необходимо добавить условие поиска имени контейнера «/internal_portal» в теге. Однако, как рассматривалось в прошлом примере, поле event_tags в полученном JSON является словарем, содержащим в качестве ключей имена тегов. Обратившись по ключу к конкретному тегу можно получить список его значений. Поскольку теги могут повторяться с разными значениями, то в полученном JSON по ключу Вы можете получить все значения данного тега и это поле всегда будет являться списком. Поэтому для поиска по значению, всегда следует обращаться к конкретному тегу и использовать поиск элемента в списке при помощи конструкции is select
.
Поиск по полю оперативных данных
Вторым этапом нужно проверить exit code. Согласно настройкам триггера эта информация отображается в оперативных данных и передается в поле «operation_data» в Event-Driven Ansible. По своей сути это строка и необходимо проверить регулярным выражением, содержит ли это поле значение «Exit code: 137» . На стороне ansible-rulebook для поиска по регулярному выражению будет использоваться конструкция is regex
.
Для решения данного примера укажите следующий блок rules в ansible-rulebook:
rules
name Run playbook for container "internal_portal"
condition event.payload.event_tags.container is select("==","/internal_portal") and
event.payload.operation_data is regex("Exit code.*137")
action
run_playbook
name restart_internal_portal.yaml
Решение
В первом условии поле event_tags является словарем и происходит обращение к конкретному тегу, поэтому итоговый путь «event.payload.event_tags.container» будет содержать и имя тега в том числе. Далее при помощи конструкции is select
проверяется список значений тега. Таким образом Вы проверяете, что в качестве значения тега присутствует необходимый контейнер «internal_portal». Если обратиться к схеме, то не ней видна связь зеленой пунктирной линией между условием в rulebook и тегами в событии со стороны Zabbix.
Во втором условии выполняется обращение к полю event.payload.operation_data при помощи конструкции is regex
и регулярного выражения «Exit code.*137». Таким образом проверяется наличие статуса «137» в качестве значения. Вы можете также увидеть на схеме связь зеленой пунктирной линией условия на стороне ansible-rulebook и оперативных данных у события в Zabbix.
И поскольку, согласно условию задачи, необходимо выполнять действие только при совпадении обоих условий, между условиями указана логическая операция and
.
Блок action
Рассмотрим блок action. При совпадении обоих условий будет выполнено указанное действие. В данном случае это запуск playbook при помощи конструкции run_playbook. Далее в блоке name указано имя запускаемого playbook: restart_internal_portal.yaml
Заключение
Подводя итог, хочется сказать, что оба инструмента, а особенно их взаимосвязанная работа, отлично подходят для реализации автоматизации. Zabbix является мощным инструментом для мониторинга, a Ansible, в свою очередь, отличным инструментом для оркестрации. Оба этих инструмента дополняют друг друга в своей работе, создавая отличный тандем и забирая на себя все рутинные задачи. В статье рассмотрен процесс отправки событий из Zabbix в Event-Driven Ansible и настройка с каждой из сторон. В статье были использованы самые элементарные примеры для простоты восприятия. Но нет предела совершенству и все зависит лишь от Вашей фантазии.
Вопросы
В: Как узнать полный список отправляемых в событии полей?
О: Самый удобный способ — это сделать ansible-rulebook с действием “debug” и условием “event.payload is defined”. В этом случае любое поступившее от Zabbix событие будет полностью выведено на экран. Данный пример описан в пункте “Прием событий в Event-Driven Ansible” этой статьи.
В: Набор отправленных полей зависит от ситуации?
О: Нет. Набор полей в отправленном событии всегда одинаковый. Если каких-то объектов в событии нет то поле будет присутствовать, однако, будет пустым. Как пример, случай с тегами. Их может не быть в событии, но поле “event_tags” все равно будет отправлено.
В: Какие события могут быть отправлены из Zabbix в Event-Drive Ansible?
О: В текущей реализации могут быть отправлены только события, основанные на триггерах и только события проблемы.
В: Можно ли передать детали полученного события в ansible-playbook?
О: Да. На стороне absible-playbook Вы можете обратиться к событию, используя пространство имен ansible_eda. То есть для получения доступа к деталям Вам необходимо указать ansible_eda.event.
Например, для вывода всех деталей события на стороне ansible-playbook Вы можете использовать:
debug:
msg: "{{ ansible_eda.event }}"
А для получения имени контейнера из примера №2 данной статьи Вы можете использовать следующий код:
debug:
msg: "{{ ansible_eda.event.payload.event_tags.container }}"