> Как организовать подключение к Zabbix (Python)

Уровень: senior · Роль: backend · Язык: Python · Категория: Технические вопросы

Компании: Международный аэропорт Шереметьево

Стек: Python

> Пример ответа

Короткий ответ

Подключение к Zabbix из Python обычно выполняется через JSON-RPC API. Основной подход - использовать официальную библиотеку py-zabbix или реализовать тонкий клиент на requests. Ключевые моменты: аутентификация через user.login, получение токена, вызов методов с параметрами и обязательная обработка ошибок API. Для production-сценариев стоит обернуть клиент в класс с retry-логикой и таймаутами, а токен хранить в защищённом хранилище, а не в коде.

Подробное объяснение

Zabbix предоставляет HTTP API на базе JSON-RPC 2.0. Endpoint по умолчанию - /api_jsonrpc.php на веб-сервере Zabbix. Протокол требует POST-запросы с заголовком Content-Type: application/json и телом вида:

JSON
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {"username": "...", "password": "..."},
"id": 1
}

После успешного логина возвращается result - строка auth-токена. Этот токен передаётся в поле auth для всех последующих вызовов. Важно: токен имеет срок жизни (по умолчанию 15 минут), поэтому для длительных операций нужно либо перелогиниваться, либо использовать API-токены Zabbix (создаются в UI, не истекают).

Основные методы для работы: host.get, item.get, trigger.get, history.get, problem.get. Параметры запросов - это словарь с фильтрами, например {"filter": {"host": ["web01"]}, "output": ["hostid", "name"]}.

Для Python есть две популярные библиотеки:

  • py-zabbix - обёртка над API, поддерживает sync и async режимы.
  • zabbix-api - более простая, но менее гибкая.

Если нужен тонкий контроль, можно написать свой клиент на requests - это оправдано, когда требуется нестандартная обработка ошибок или интеграция с существующей инфраструктурой.

На практике

В реальном проекте подключение к Zabbix обычно инкапсулируется в отдельный сервисный класс. Это позволяет:

  • централизованно управлять конфигурацией (URL, credentials, таймауты);
  • переиспользовать токен между вызовами;
  • логировать запросы и ответы для отладки;
  • добавлять кэширование результатов для часто запрашиваемых данных (например, списка хостов).

Типичный сценарий - получение истории метрик для алертинга или аналитики. Здесь важно учитывать лимиты API: history.get возвращает максимум 1000 записей за раз, поэтому нужна пагинация через параметры limit и offset или фильтрация по времени.

Для асинхронных приложений (FastAPI, asyncio) стоит использовать httpx.AsyncClient или aiohttp вместо requests, чтобы не блокировать event loop. Библиотека py-zabbix поддерживает async из коробки.

Пример кода

PYTHON
import requests
from typing import Any, Optional
class ZabbixClient:
def __init__(self, url: str, username: str, password: str, timeout: int = 10):
self.api_url = url.rstrip("/") + "/api_jsonrpc.php"
self.username = username
self.password = password
self.timeout = timeout
self.auth_token: Optional[str] = None
self.request_id = 0
def _call(self, method: str, params: dict[str, Any]) -> Any:
if not self.auth_token and method != "user.login":
self.login()
payload = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": self._next_id(),
}
if self.auth_token:
payload["auth"] = self.auth_token
response = requests.post(
self.api_url,
json=payload,
timeout=self.timeout,
headers={"Content-Type": "application/json"},
)
response.raise_for_status()
data = response.json()
if "error" in data:
raise RuntimeError(
f"Zabbix API error: {data['error'].get('message')} "
f"({data['error'].get('code')})"
)
return data.get("result")
def _next_id(self) -> int:
self.request_id += 1
return self.request_id
def login(self) -> str:
result = self._call(
"user.login",
{"username": self.username, "password": self.password},
)
self.auth_token = result
return result
def logout(self) -> None:
if self.auth_token:
self._call("user.logout", {})
self.auth_token = None
def get_hosts(self, host_names: list[str]) -> list[dict[str, Any]]:
return self._call(
"host.get",
{
"filter": {"host": host_names},
"output": ["hostid", "host", "name", "status"],
},
)
def get_history(self, item_id: str, time_from: int, time_till: int) -> list[dict[str, Any]]:
return self._call(
"history.get",
{
"itemids": [item_id],
"history": 0, # 0 - numeric float
"time_from": time_from,
"time_till": time_till,
"output": "extend",
"sortfield": "clock",
"sortorder": "ASC",
"limit": 1000,
},
)
# Использование
client = ZabbixClient("https://zabbix.example.com", "api_user", "secret")
hosts = client.get_hosts(["web01"])
print(hosts)
client.logout()

Как отвечать на собеседовании

Начни с краткого описания протокола: JSON-RPC 2.0, endpoint /api_jsonrpc.php, аутентификация через user.login. Затем переходи к практической реализации: библиотеки, структура клиента, обработка ошибок. Упомяни нюансы: срок жизни токена, лимиты пагинации, разница между sync и async подходами.

Если спросят про альтернативы - скажи, что можно использовать официальный CLI zabbix-cli или прямой SQL к базе, но это не рекомендуется для production из-за рисков и отсутствия валидации. Подчеркни, что API - единственный поддерживаемый способ интеграции.

Хорошо показать понимание безопасности: не хранить пароли в коде, использовать переменные окружения или секрет-менеджеры, для сервисных аккаунтов - API-токены вместо пароля.

Что проверяет интервьюер

  • знание протокола JSON-RPC и особенностей Zabbix API;
  • умение проектировать клиентский код с учётом повторного использования и обработки ошибок;
  • понимание ограничений API (лимиты, пагинация, таймауты);
  • способность выбрать подходящий инструмент (библиотека vs собственный клиент);
  • навыки работы с асинхронностью, если это релевантно для позиции.

Типичные ошибки

  • не обрабатывать ошибки API - полагаться только на HTTP-статус;
  • хранить токен в глобальной переменной без учёта истечения срока;
  • игнорировать лимит в 1000 записей для history.get - получать неполные данные;
  • использовать requests в async-коде, блокируя event loop;
  • не закрывать сессию (logout) - оставлять токены активными;
  • хардкодить URL и credentials в коде вместо конфигурации;
  • не проверять error поле в ответе, считая, что HTTP 200 - гарантия успеха.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью