В этой статье мы рассмотрим возможности новых асинхронных модулей библиотеки 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_URLZABBIX_TOKENZABBIX_USERZABBIX_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 станет незаменимым инструментом для разработчиков и администраторов, помогая им создавать более эффективные, гибкие и надежные мониторинговые решения, которые лучше всего соответствуют их требованиям и ожиданиям.

Подписаться
Уведомить о
0 Comments
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x