В этой статье мы рассмотрим возможности новых асинхронных модулей библиотеки zabbix_utils. Благодаря асинхронному выполнению пользователи могут рассчитывать на повышение эффективности, снижение задержек и повышенную гибкость взаимодействия с Zabbix, что в конечном итоге даст им возможность создавать эффективные и надежные решения для мониторинга, соответствующие их конкретным требованиям.
Мы видим высокий спрос на Python-библиотеку zabbix_utils. С момента релиза и до момента написания этой статьи, zabbix_utils была скачана с PyPI более чем 15 000 раз. За последнюю неделю библиотека была скачана более чем 2 700 раз. У нашей первой статьи про библиотеку zabbix_utils уже порядка 3 000 просмотров. Среди множества доступных инструментов наша библиотека стала популярным выбором, предлагая разработчикам и администраторам полный набор функций для взаимодействия с компонентами Zabbix.
Видя запрос со стороны пользователей, а также потенциал асинхронного программирования для оптимизации взаимодействия с Zabbix, мы с радостью представляем новую версию библиотеки с новыми асинхронными модулями. Новые модули zabbix_utils призваны обеспечить значительный прирост производительности за счет использования присущих асинхронному программированию преимуществ для ускорения связи между Zabbix и вашим сервисом или скриптом.
Вы можете ознакомиться с вводной статьей о zabbix_utils для получения более полного представления о работе с библиотекой.
Преимущества и сценарии использования
Асинхронное программирование позволяет создавать высокоэффективные, гибкие и надежные решения для мониторинга, адаптированные к вашим конкретным потребностям и задачам, от ускоренного поиска данных и мониторинга событий в реальном времени до улучшенной масштабируемости.
Новая версия zabbix_utils и ее асинхронные компоненты могут быть полезны в следующих сценариях:
- Массовый сбор данных с нескольких хостов: когда необходимо одновременно получить данные с большого количества хостов, асинхронное программирование позволяет выполнять запросы параллельно, что значительно ускоряет этот процесс;
- Массовый экспорт ресурсов: когда шаблоны, хосты или список проблем необходимо экспортировать параллельно. Такое параллельное выполнение сокращает общее время экспорта, особенно при работе с большим количеством ресурсов;
- Отправка оповещений из/в вашу систему: когда на основе условий мониторинга необходимо выполнить определенные действия, например отправку оповещений или запуск сценариев, асинхронное программирование обеспечивает максимально оперативную обработку условий и выполнение соответствующих действий;
- Масштабирование системы мониторинга: с увеличением количества отслеживаемых ресурсов или объема собираемых данных асинхронное программирование обеспечивает лучшую масштабируемость и эффективность системы мониторинга.
Установка и настройка
Если Вы уже используете библиотеку zabbix_utils, то достаточно просто обновить библиотеку до последней версии и установить все необходимые зависимости для асинхронной работы. Если нет — установить библиотеку с поддержкой асинхронной работы можно следующими способами:
- С помощью pip:
~$ pip install zabbix_utils[async]
Использование [async] позволяет установить дополнительные зависимости, необходимых для работы асинхронных модулей.
- С помощью клонирования с Github:
~$ git clone https://github.com/zabbix/python-zabbix-utils ~$ cd python-zabbix-utils/ ~$ pip install -r requirements.txt ~$ python setup.py install
Процесс работы с асинхронной версией библиотеки zabbix_utils аналогичен синхронной, за исключением некоторых особенностей асинхронной работы в Python.
Работа с Zabbix API
Для работы с Zabbix API в асинхронном режиме необходимо импортировать класс AsyncZabbixAPI библиотеки zabbix_utils:
from zabbix_utils import AsyncZabbixAPI
Аналогично синхронному ZabbixAPI, новый AsyncZabbixAPI может использовать следующие переменные окружения: ZABBIX_URL, ZABBIX_TOKEN, ZABBIX_USER, ZABBIX_PASSWORD. Однако при создании экземпляра класса AsyncZabbixAPI, в отличие от синхронной версии, нельзя указать токен или имя пользователя и пароль. Их можно передать только при вызове метода login(). Доступны следующие сценарии использования:
- Использовать заданные ранее значения переменных окружения, т.е. не передавать на вход AsyncZabbixAPI никаких параметров:
~$ export ZABBIX_URL="https://zabbix.example.local"
api = AsyncZabbixAPI()
- Передать на вход только адрес Zabbix API, причем он может быть указан и как просто IP/FQDN адрес сервера или DNS имя (в таком случае будет использован протокол HTTP) и как URL к Zabbix API:
api = AsyncZabbixAPI(url="127.0.0.1")
После объявления экземпляра класса AsyncZabbixAPI необходимо вызвать метод login() чтобы выполнить аутентификацию в Zabbix API. Здесь, как и в случае выше, есть два варианта:
- Использовать значения переменных окружения:
~$ export ZABBIX_USER="Admin" ~$ export ZABBIX_PASSWORD="zabbix"
или
~$ export ZABBIX_TOKEN="xxxxxxxx"
а затем:
await api.login()
- Передать данные для аутентификации при вызове login():
await api.login(user="Admin", password="zabbix")
Аналогично ZabbixAPI новый класс AsyncZabbixAPI поддерживает получение версии и сравнение:
# Поле версии Zabbix API ver = api.version print(type(ver).__name__, ver) # APIVersion 6.0.29 # Метод получения версии Zabbix API ver = api.api_version() print(type(ver).__name__, ver) # APIVersion 6.0.29 # Дополнительные методы работы print(ver.major) # 6.0 print(ver.minor) # 29 print(ver.is_lts()) # True # Сравнение версий print(ver < 6.4) # True print(ver != 6.0) # False print(ver != "6.0.24") # True
После аутентификации можно выполнять любые запросы к API, описанные в документации Zabbix для всех поддерживаемых версий.
Формат вызова методов API выглядит следующим образом:
await экземпляр_класса.объект_zabbix.метод(параметры)
Например:
await api.host.get()
После выполнения всех необходимых запросов к API необходимо выполнить logout(), чтобы закрыть сессию к API если аутентификация была выполнена при помощи логина и пароля, а также закрыть асинхронные сессии:
await api.logout()
Больше примеров использования можно найти здесь.
Отправка значений в Zabbix server/proxy.
Аналогично синхронному Sender добавлен асинхронный класс AsyncSender, который также помогает отправлять значения на Zabbix server или proxy для элементов данных типа Zabbix Trapper.
Импорт AsyncSender, выполняется следующим образом:
from zabbix_utils import AsyncSender
Значения могут быть отправлены группой, для чего необходимо также импортировать ItemValue:
import asyncio from zabbix_utils import ItemValue, AsyncSender items = [ ItemValue('host1', 'item.key1', 10), ItemValue('host1', 'item.key2', 'Test value'), ItemValue('host2', 'item.key1', -1, 1702511920), ItemValue('host3', 'item.key1', '{"msg":"Test value"}'), ItemValue('host2', 'item.key1', 0, 1702511920, 100) ] async def main(): sender = AsyncSender('127.0.0.1', 10051) response = await sender.send(items) # обработка полученного ответа asyncio.run(main())
Как и в синхронной версии, возможно указать размер фрагментов (чанков) при групповой отправке значений с помощью параметра chunk_size:
sender = AsyncSender('127.0.0.1', 10051, chunk_size=2) response = await sender.send(items)
В примере размер чанка установлен равным 2. В этом случае 5 значений из кода выше будут отправлены тремя запросами по 2, 2 и 1 значение соответственно.
Также возможна отправка отдельных значений по одному:
sender = AsyncSender(server='127.0.0.1', port=10051) resp = await sender.send_value('example_host', 'example.key', 50, 1702511920))
Если на Вашем сервере несколько сетевых интерфейсов, а значения необходимо отправлять с какого-то определенного, то AsyncSender предоставляет возможность указать source_ip для отправляемых значений:
sender = AsyncSender( server='zabbix.example.local', port=10051, source_ip='10.10.7.1' ) resp = await sender.send_value('example_host', 'example.key', 50, 1702511920)
AsyncSender поддерживает и чтение параметров подключения к серверу из файла конфигурации Zabbix agent/agent2. Для этого необходимо установить соответствующий флаг и путь к файлу конфигурации, если он отличается от стандартного /etc/zabbix/zabbix_agentd.conf:
sender = AsyncSender( use_config=True, config_path='/etc/zabbix/zabbix_agent2.conf' )
Больше примеров использования можно найти здесь.
Получение значений с Zabbix agent/agent2 по ключу элемента данных.
В случаях, когда необходим функционал нашей утилиты zabbix_get, но в рамках вашего проекта на Python и работающий асинхронно, обратите внимание на класс AsyncGetter. Простой пример его использования выглядит следующим образом:
import asyncio from zabbix_utils import AsyncGetter async def main(): agent = AsyncGetter('10.8.54.32', 10050) resp = await agent.get('system.uname') print(resp.value) # Linux zabbix_server 5.15.0-3.60.5.1.el9uek.x86_64 asyncio.run(main())
Как и в случае с AsyncSender, класс AsyncGetter поддерживает указание адреса source_ip:
agent = AsyncGetter( host='zabbix.example.local', port=10050, source_ip='10.10.7.1' )
Больше примеров использования можно найти здесь.
Заключение
Новая версия библиотеки zabbix_utils предоставляет пользователям возможность реализовывать эффективные и масштабируемые решения для мониторинга, обеспечивая быструю и надежную связь с компонентами Zabbix. Асинхронное взаимодействие открывает двери для более гибкого управления задачами и улучшает производительность в случае обработки большого объема запросов к таким компонентам как Zabbix API и другим.
Мы не сомневаемся, что новая асинхронная версия zabbix_utils станет незаменимым инструментом для разработчиков и администраторов, помогая им создавать более эффективные, гибкие и надежные мониторинговые решения, которые лучше всего соответствуют их требованиям и ожиданиям.