Grafana: дашборды, понятные и руководству, и эксплуатации

Как NexTool внедряет и сопровождает Grafana рядом с GLPI: архитектура с источником данных только для чтения, реальный запрос по нарушенным SLA, разделение операционных и управленческих панелей и правило оповещений без дублирования.

В этой статьеРазделов: 5

Grafana приносит пользу только тогда, когда панели отвечают на вопросы тех, кто эксплуатирует, и тех, кто принимает решения. В рамках сопровождения GLPI и инфраструктуры для B2B-клиентов мы используем её как слой визуализации рядом со службой поддержки: она читает метрики SLA и заявок прямо из базы GLPI, сопоставляет их с рядами доступности из Zabbix или Prometheus и выводит всё на экран, который NOC и руководство могут понять без выгрузки в таблицы.

Как мы размещаем Grafana рядом с GLPI

Архитектура, которую мы используем, намеренно компактна: контейнер Grafana на том же хосте, где уже работает GLPI, за тем же reverse proxy с TLS, с тремя разными источниками данных. Первый — сама база MariaDB/MySQL GLPI под пользователем только для чтения, для показателей службы поддержки (открытые заявки, нарушенные SLA, среднее время обслуживания). Второй — Zabbix или Prometheus для доступности и мощностей инфраструктуры. Третий, если у клиента есть плагин NexTool, — метрики синхронизации и интеграций, которые предоставляет экосистема.

Типичная ошибка тех, кто собирает это самостоятельно, — подключать Grafana под административным пользователем GLPI. Мы так никогда не делаем. Панели нужно только читать, а скомпрометированный источник данных не должен становиться дверью для записи в рабочую базу. Мы создаём отдельного пользователя с SELECT, ограниченным нужными таблицами, и Grafana никогда не получает больше прав, чем требуется для отрисовки графика.

Артефакт: пользователь только для чтения и источник данных

Эту пару мы настраиваем при каждом внедрении. Сначала пользователь для чтения в базе GLPI с минимальными привилегиями:

-- read-only user for Grafana to read GLPI
CREATE USER 'grafana_ro'@'%' IDENTIFIED BY '${STRONG_PASSWORD}';
GRANT SELECT ON glpi.glpi_tickets           TO 'grafana_ro'@'%';
GRANT SELECT ON glpi.glpi_slas              TO 'grafana_ro'@'%';
GRANT SELECT ON glpi.glpi_tickets_users     TO 'grafana_ro'@'%';
GRANT SELECT ON glpi.glpi_itilcategories    TO 'grafana_ro'@'%';
FLUSH PRIVILEGES;
-- no GRANT ALL: the panel only draws, it never writes

Затем настройка источника данных через файл, чтобы панель поднималась под версионным контролем вместе с контейнером и не зависела от ручных кликов в интерфейсе:

# /etc/grafana/provisioning/datasources/glpi.yaml
apiVersion: 1
datasources:
  - name: GLPI (read-only)
    type: mysql
    access: proxy
    url: glpidb:3306
    database: glpi
    user: grafana_ro
    secureJsonData:
      password: ${STRONG_PASSWORD}   # injected via environment variable
    jsonData:
      maxOpenConns: 5                # does not choke the production database
      timeInterval: "1m"

Реальный запрос: нарушенные SLA по категориям

Управленческая панель, которую мы поставляем всегда, — заявки с просроченным SLA на решение, сгруппированные по категориям. Именно её руководство открывает в понедельник утром. Запрос выполняется прямо по базе GLPI в формате, который ожидает Grafana:

SELECT
  c.completename                             AS category,
  COUNT(*)                                   AS breached_tickets
FROM glpi_tickets t
JOIN glpi_itilcategories c ON c.id = t.itilcategories_id
WHERE t.status NOT IN (5, 6)                 -- excludes solved and closed
  AND t.time_to_resolve IS NOT NULL
  AND t.time_to_resolve < NOW()             -- resolution deadline already passed
  AND t.is_deleted = 0
GROUP BY c.completename
ORDER BY breached_tickets DESC;

Деталь, которую знают только те, кто эксплуатирует GLPI: статусы 5 и 6 в стандартной схеме — это «решена» и «закрыта», а is_deleted = 0 обязателен, потому что GLPI выполняет логическое удаление — если игнорировать этот столбец, число раздувается за счёт заявок, которые уже лежат в корзине. В практике сопровождения мы видели, как сторонняя панель показывала вдвое больше нарушенных SLA только из-за забытого is_deleted. Такой баг подрывает доверие руководства ко всему дашборду.

Дашборды по аудиториям: что мы разделяем

Мы не смешиваем NOC и дирекцию на одном экране. Эксплуатации нужна детализация, чтобы действовать прямо сейчас; руководству нужен тренд, чтобы принимать решения. Разделение, которое мы стандартизировали:

ИзмерениеОперационная панель (NOC)Управленческая панель (руководство)
ДетализацияПо сервису, хосту и заявкеПо организации, договору и периоду
Типичное окноПоследние часы / реальное времяНеделя, месяц, квартал
Ключевая метрикаЗадержки, ошибки, очередь заявокСоблюдение SLA, тренд, мощности
Ожидаемое действиеВмешаться в инцидентРасставить приоритеты, нанять, пересмотреть договор
Частота обновленияОт 30 с до 1 минОт 15 мин до 1 ч

Оповещения: где срабатывать без дублирования

Правило, которое мы применяем, простое и предотвращает худшую проблему наблюдаемости — одно и то же событие, оповещающее по двум путям. Доступность и мощности инфраструктуры оповещают в источнике (Zabbix или Prometheus), где уже есть история и контекст хоста. Grafana оповещает только о бизнес-показателях, которые существуют лишь на пересечении источников, — например, когда SLA конкретного договора вот-вот будет нарушен. Каждая поставляемая нами панель содержит в описании определение метрики и ожидаемое действие при отклонении. Панель без такой документации превращается в украшение, а на украшения никто не смотрит.

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

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

Если ваша эксплуатация GLPI всё ещё зависит от выгрузки в таблицу, чтобы понять состояние SLA, NexTool внедрит и будет сопровождать этот слой наблюдаемости рядом с вашей службой поддержки, с панелями, уже интегрированными с GLPI и инфраструктурой. Поговорите с нами о сопровождении GLPI со встроенной наблюдаемостью.


Проверено командой NexTool Solutions.

Часто задаваемые вопросы

Мы настраиваем источник данных MySQL/MariaDB, указывающий на базу GLPI, с пользователем только для чтения (лишь SELECT на нужные таблицы). Grafana запрашивает такие таблицы, как glpi_tickets и glpi_slas, и строит панели, никогда не получая права на запись в рабочую базу.

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

Доступность и мощности инфраструктуры должны оповещать в источнике, где есть история и контекст хоста. Grafana должна оповещать только о бизнес-показателях, которые существуют лишь на пересечении источников, например о SLA конкретного договора. Так одно и то же событие не будет оповещать по двум путям.

Потому что GLPI выполняет логическое удаление: удалённые заявки остаются в таблице с is_deleted = 1. Без фильтра is_deleted = 0 панель учитывает заявки, которые уже лежат в корзине, и завышает число нарушенных SLA, подрывая доверие руководства к дашборду.

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

Нужна помощь?