Пример заполнения шаблона
Рассмотрим структуру шаблона на примере: создадим шаблон модели здоровья ПАК МБД.П.
Пусть шаблон отображает следующие сведения о ПАК:
-
общий статус ПАК;
-
состояние кластера PostgreSQL;
-
состояние узлов модуля баз данных и степень утилизации их ресурсов.
По этим сведениям подсистема мониторинга построит дерево из панелей трёх видов: карточка ПАК, карточки модулей баз данных и списки их узлов.
Назначение полей, которые встречаются ниже, описано в разделе Спецификация шаблонов модели здоровья.
Шаг 1. Заголовок шаблона
Шаблон — это файл формата YAML, поэтому сначала создадим файл с расширением .yml.
Начнём с полей, которые описывают шаблон целиком: код типа ПАК (uid — для МБД.П это mbd_p), название шаблона в веб-интерфейсе (title), номер версии шаблона (version), номер версии схемы (schema_version — для новых шаблонов 1.1) и период обновления статусов панелей в секундах (refresh_interval).
Добавим эти поля в файл:
---
uid: mbd_p
title: МБД.П
version: v1.0
schema_version: "1.1"
refresh_interval: 30
|
Комбинация значений |
Шаг 2. Панель общего статуса
Первая панель — карточка ПАК. Она служит корнем дерева: остальные панели вложены в неё напрямую или через другие панели.
Общий статус ПАК будем вычислять по активным оповещениям.
Это делает запрос в поле status_query: он собирает оповещения ПАК из ALERTS, и если среди них есть оповещение уровня critical, статус панели — red, если warning — yellow, а без оповещений — green.
Состав панели определяет запрос в поле list_query: сколько рядов он вернёт, столько объектов появится на панели.
Здесь запрос возвращает единственный ряд — сам ПАК из объектной модели, поэтому карточка будет одна.
Вместо конкретных идентификаторов в запросах используются встроенные переменные: при построении модели подсистема мониторинга заменит ${pak_id} идентификатором текущего ПАК, а ${entity_id} — идентификатором текущего объекта.
Благодаря переменным один и тот же шаблон работает на любом экземпляре МБД.П.
На карточке выведем тип и описание ПАК.
Блок meta сохраняет одноимённые метки из ответа list_query, а подзаголовок карточки обращается к сохранённому значению через ${meta.type}.
Тем же способом можно сохранить и любую другую метку из ответа.
Панель отображается карточкой, поэтому тип панели — grid, тип объекта — pak, а внешний вид задаёт блок card_template.
Его поле indicator определяет, что красит карточку: индикаторы (true) или оповещения из status_query (false).
Собираем панель — допишем в конец файла блок panels с первой записью:
panels:
- id: ${pak_id}
title: ПАК ${pak_id}
type: grid
panel_type: pak
list_query: 'vision_object_pak_info{_pak_id="${pak_id}"}'
meta:
- name: type
source: type
- name: description
source: description
status_query: 'max by (_pak_id, alertname, severity, _cids) (ALERTS{_pak_id="${entity_id}", alertstate="firing"})'
card_template:
title: "ПАК ${id}"
subtitle: "Тип: ${meta.type}"
indicator: true
|
При изменении |
Шаг 3. Панель модуля баз данных
Состояние кластера PostgreSQL покажем на карточке модуля баз данных.
Поскольку модулей баз данных в ПАК может быть несколько, используем для описания панели конструкцию repeat_for: её запрос возвращает все модули типа «Модуль баз данных», и панель повторяется для каждого из них.
Значение метки, названной в id_field, при этом становится переменной ${_module_id} — она делает уникальными идентификатор и заголовок каждой карточки.
Состояние кластера оценим двумя индикаторами из блока indicators:
-
количество узлов кластера Pacemaker в статусе
online: меньше трёх — жёлтый, меньше двух — красный; -
доля использованных соединений PostgreSQL:
-
≥ 80% — жёлтый;
-
≥ 90% — красный.
-
Каждый индикатор состоит из идентификатора (id), подписи (title), PromQL-запроса показателя (query) и порогов (thresholds).
По этому же образцу можно добавить собственные индикаторы или скорректировать пороги.
|
Заключайте правило порога в кавычки, иначе YAML воспримет значение, начинающееся с |
Цвет карточки должны определять именно индикаторы, поэтому в блоке card_template параметру indicator присвоим значение true.
Если индикаторы в порядке, наличие оповещений не будет влиять на цвет карточки.
При этом числовые значения будут отображаться.
Счётчик из блока entities выведет на карточку количество узлов модуля: его поле query ссылается на идентификатор панели узлов db-nodes-${_module_id}, которую опишем на следующем шаге.
Остальное повторяет карточку ПАК: блок meta сохраняет тип и описание модуля, а status_query собирает оповещения — теперь по метке _module_id.
Собираем панель — допишем её в блок panels после карточки ПАК:
- id: module-db-${_module_id}
title: "Модуль ${_module_id}"
type: grid
panel_type: module
repeat_for:
source: ${pak_id}
id_field: _module_id
list_query: 'vision_object_module_info{_pak_id="${pak_id}", type="Модуль баз данных"}'
list_query: 'vision_object_module_info{_pak_id="${pak_id}", _module_id="${_module_id}", type="Модуль баз данных"}'
meta:
- name: type
source: type
- name: description
source: description
status_query: 'max by (_module_id, alertname, severity, _cids) (ALERTS{_module_id="${entity_id}", alertstate="firing"})'
entities:
- id: nodes
title: Ноды
query: db-nodes-${_module_id}
indicators:
- id: cluster_nodes_online
title: "Ноды кластера online (шт.)"
query: 'count(ha_cluster_pacemaker_nodes{_module_id="${_module_id}",status="online"} and on(node) ha_cluster_corosync_member_votes{_module_id="${_module_id}",local="true"})'
thresholds:
warning: "< 3"
critical: "< 2"
- id: used_connections
title: "Использовано соединений (%)"
query: 'max(label_replace(spectrum_pg_used_connections{service_name!="",node_name!=""},"_node_id","$1","node_name","(.*)") and on(_node_id) vision_object_node_info{_pak_id="${pak_id}",_module_id="${_module_id}"})'
thresholds:
warning: ">= 80"
critical: ">= 90"
card_template:
title: "Модуль ${id}"
subtitle: "Тип: ${meta.type}"
indicator: true
Шаг 4. Панель узлов
Узлы модуля баз данных выведем списком: одна строка — один узел.
Список, как и карточка модуля, повторяется для каждого модуля баз данных — правило repeat_for то же, только его поле source ссылается на панель модуля.
Состав списка определяет запрос list_query: он возвращает по одному ряду на каждый узел модуля.
Из ответа блок meta сохраняет тип узла и его адреса — обычный и BMC; адрес BMC выводится в подзаголовке строки через ${meta.bmc_address}.
Добавим показатели утилизации ресурсов:
-
CPU:
-
≥ 80% — жёлтый;
-
≥ 90% — красный;
-
-
RAM:
-
≥ 90% — жёлтый;
-
≥ 95% — красный.
-
В запросах этих индикаторов переменная ${entity_id} подставляет идентификатор текущего узла.
По умолчанию, если данные для панели не поступают, она окрашивается в серый цвет.
Однако отсутствие метрик с узла — само по себе серьёзная проблема, поэтому в поле indicator шаблона строки (row_template) — значение true: цвет строки определяют индикаторы, а отсутствие их данных поднимает статус узла до red.
Собираем панель — допишем её в блок panels после карточки модуля:
- id: db-nodes-${_module_id}
title: "Узел БД ${id}"
type: list
panel_type: node
repeat_for:
source: module-db-${_module_id}
id_field: _module_id
list_query: 'vision_object_module_info{_pak_id="${pak_id}", type="Модуль баз данных"}'
list_query: 'vision_object_node_info{_pak_id="${pak_id}", _module_id="${_module_id}"}'
meta:
- name: type
source: type
- name: address
source: address
- name: bmc_address
source: bmc_address
status_query: 'max by (_node_id, alertname, severity, _cids) (ALERTS{_node_id="${entity_id}", alertstate="firing"})'
indicators:
- id: cpu_usage
title: "Исп. ЦПУ (%)"
query: '(1 - avg(rate(node_cpu_seconds_total{_target_type="NODE",_pak_id="${pak_id}",_node_id=~"${entity_id}",mode="idle"}[5m])) by (_node_id)) * 100'
thresholds:
warning: ">= 80"
critical: ">= 90"
- id: ram_usage
title: "Занято RAM (%)"
query: '100 - node_memory_MemAvailable_bytes{_target_type="NODE",_pak_id="${pak_id}",_node_id=~"${entity_id}"} / node_memory_MemTotal_bytes{_target_type="NODE",_pak_id="${pak_id}",_node_id=~"${entity_id}"} * 100'
thresholds:
warning: ">= 90"
critical: ">= 95"
row_template:
title: "Узел БД ${id}"
subtitle: "BMC: ${meta.bmc_address}"
indicator: true
Шаг 5. Связи между панелями
Панели описаны — построим из них дерево.
Вложенность панелей задаёт блок relationships: в каждой записи from — идентификатор родительской панели, to — дочерней.
Свяжем карточку ПАК с карточками модулей, а модули — со списками узлов:
relationships:
- from: ${pak_id}
to: module-db-${_module_id}
- from: module-db-${_module_id}
to: db-nodes-${_module_id}
Шаг 6. Правила агрегации
Чтобы проблемы поднимались вверх по дереву, зададим правила агрегации: статус ПАК зависит от карточек модулей, а статус модуля — от его списка узлов.
В каждом правиле target — панель, для которой действует правило, depends_on — список панелей, от которых она зависит.
Условие condition: ANY означает, что панель из target меняет цвет при проблеме хотя бы в одной панели из depends_on; при ALL — только когда проблема во всех панелях одновременно.
Значение поля type всегда dependency — других типов правил нет.
Допишем блок в конец файла:
aggregations:
- target: ${pak_id}
type: dependency
condition: ANY
depends_on:
- module-db-${_module_id}
- target: module-db-${_module_id}
type: dependency
condition: ANY
depends_on:
- db-nodes-${_module_id}
Итоговый шаблон
Собранный из всех шагов шаблон готов к загрузке.
---
uid: mbd_p
title: МБД.П
version: v1.0
schema_version: "1.1"
refresh_interval: 30
panels:
- id: ${pak_id}
title: ПАК ${pak_id}
type: grid
panel_type: pak
list_query: 'vision_object_pak_info{_pak_id="${pak_id}"}'
meta:
- name: type
source: type
- name: description
source: description
status_query: 'max by (_pak_id, alertname, severity, _cids) (ALERTS{_pak_id="${entity_id}", alertstate="firing"})'
card_template:
title: "ПАК ${id}"
subtitle: "Тип: ${meta.type}"
indicator: true
- id: module-db-${_module_id}
title: "Модуль ${_module_id}"
type: grid
panel_type: module
repeat_for:
source: ${pak_id}
id_field: _module_id
list_query: 'vision_object_module_info{_pak_id="${pak_id}", type="Модуль баз данных"}'
list_query: 'vision_object_module_info{_pak_id="${pak_id}", _module_id="${_module_id}", type="Модуль баз данных"}'
meta:
- name: type
source: type
- name: description
source: description
status_query: 'max by (_module_id, alertname, severity, _cids) (ALERTS{_module_id="${entity_id}", alertstate="firing"})'
entities:
- id: nodes
title: Ноды
query: db-nodes-${_module_id}
indicators:
- id: cluster_nodes_online
title: "Ноды кластера online (шт.)"
query: 'count(ha_cluster_pacemaker_nodes{_module_id="${_module_id}",status="online"} and on(node) ha_cluster_corosync_member_votes{_module_id="${_module_id}",local="true"})'
thresholds:
warning: "< 3"
critical: "< 2"
- id: used_connections
title: "Использовано соединений (%)"
query: 'max(label_replace(spectrum_pg_used_connections{service_name!="",node_name!=""},"_node_id","$1","node_name","(.*)") and on(_node_id) vision_object_node_info{_pak_id="${pak_id}",_module_id="${_module_id}"})'
thresholds:
warning: ">= 80"
critical: ">= 90"
card_template:
title: "Модуль ${id}"
subtitle: "Тип: ${meta.type}"
indicator: true
- id: db-nodes-${_module_id}
title: "Узел БД ${id}"
type: list
panel_type: node
repeat_for:
source: module-db-${_module_id}
id_field: _module_id
list_query: 'vision_object_module_info{_pak_id="${pak_id}", type="Модуль баз данных"}'
list_query: 'vision_object_node_info{_pak_id="${pak_id}", _module_id="${_module_id}"}'
meta:
- name: type
source: type
- name: address
source: address
- name: bmc_address
source: bmc_address
status_query: 'max by (_node_id, alertname, severity, _cids) (ALERTS{_node_id="${entity_id}", alertstate="firing"})'
indicators:
- id: cpu_usage
title: "Исп. ЦПУ (%)"
query: '(1 - avg(rate(node_cpu_seconds_total{_target_type="NODE",_pak_id="${pak_id}",_node_id=~"${entity_id}",mode="idle"}[5m])) by (_node_id)) * 100'
thresholds:
warning: ">= 80"
critical: ">= 90"
- id: ram_usage
title: "Занято RAM (%)"
query: '100 - node_memory_MemAvailable_bytes{_target_type="NODE",_pak_id="${pak_id}",_node_id=~"${entity_id}"} / node_memory_MemTotal_bytes{_target_type="NODE",_pak_id="${pak_id}",_node_id=~"${entity_id}"} * 100'
thresholds:
warning: ">= 90"
critical: ">= 95"
row_template:
title: "Узел БД ${id}"
subtitle: "BMC: ${meta.bmc_address}"
indicator: true
relationships:
- from: ${pak_id}
to: module-db-${_module_id}
- from: module-db-${_module_id}
to: db-nodes-${_module_id}
aggregations:
- target: ${pak_id}
type: dependency
condition: ANY
depends_on:
- module-db-${_module_id}
- target: module-db-${_module_id}
type: dependency
condition: ANY
depends_on:
- db-nodes-${_module_id}
Загрузите файл и сделайте его активным, как описано в разделе Добавление шаблона.
Готовые шаблоны из поставки можно скачать и посмотреть в них описания остальных панелей: базового модуля, модуля резервного копирования, виртуальных машин и коммутаторов.