Логика работы:
1. Prometheus периодически вычисляет написанные правила, если условие выполнено, формирует алерт
2. Посылает их в Alertmanager
3. Alertmanager отправляет нам сообщения (Mail, Telegram, и т.д.)
Логика правил алертов живет в отдельных файлах, часто rules.yaml
Подключаются в основной prometheus.yaml через секцию rule_files:
global:
...
rule_files:
- '/path/to/rules.yaml'
scrape_configs:
...
rules.yaml состоит из групп (groups)
groups — логическое объединение правил, у которого есть name и опционально interval
Минимальная структура rules.yaml:
groups:
- name: node
interval: 15s # опционально, переопределяет глобальный evaluation_interval
rules:
- alert: HighCPU # имя алерта
expr: <PromQL> # условие, при котором алерт сработает
for: 5m # сколько по времени условие должно выполняться, перед тем, как алерт отправится
labels: # дополнительные лейблы для маршрутизации алерта в Alertmanager
severity: warning
annotations: # краткое описание
summary: "..."
description: "..."
- name: app
interval: 10s
rules:
...
Где:
interval — интервал с которым Prometheus будет проверять написанные условия (выполнять PromQL запросы)
alert — имя алерта, указываете свое по логике
expr — условие в виде PromQL выражения
for — условие (expr) должно оставаться истинным минимум указанное время
labels — дополнительные лейблы алерта для роутинга, например:
- если у алерта severity="critical" - отправить в Telegram
- если у алерта severity="warning" - отправить по Mail
annotations — текст алерта в уведомлении
Шаблоны
Применяются к annotations и labels
Эти данные можно подставлять в текст уведомления при помощи шаблонов на Go
Доступные переменные $labels - все лейблы временного ряда, по которому сработал алерт
Пример - метрика node_cpu_seconds_total{instance="server.domain.com", mode="user"}
Доступные $labels:
{{ $labels.instance }} = server.domain.com
{{ $labels.mode }} = user
$value - значение выражения expr, вызвавшее алерт
В шаблонах можно использовать стандартные функции форматирования Go
printf - форматирование строк и чисел:
({{ printf "%.1f" $value }} округление до 1 знака после запятой)
({{ printf "%.2f" $value }} округление до 2 знака после запятой)
...
Пример в rules.yaml:
groups:
- name: node
interval: 15s
rules:
- alert: HighCPU
expr: 100 * (1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))) > 80
# expr: 100 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 > 80
for: 5m
labels:
severity: warning
annotations:
summary: "Критическая нагрузка CPU на {{ $labels.instance }}"
description: "Крайние 5 минут CPU загружен на {{ printf \"%.1f\" $value }}%"
Долю времени в idle (простой), переводим в проценты и вычитаем из 100, по итогу получая загрузку CPU
Алерт выше срабатывает, когда загрузка процессора выше 80% сохраняется более 5 минут
Где:
evaluation_interval - переопределяется параметром interval в rules.yaml, указывает, как часто Prometheus пересчитывает правила
evaluation_interval ниже scrape_interval не имеет смысла, тк значение метрики будет обновляться в соответствии scrape_interval
scrape_interval: определяет интервал, на основе которого prometheus очищает отслеживаемую цель
Он определен глобально, но также может быть изменен на уровне задания
Значение по умолчанию равно 1 минуте
evaluation_interval: определяет интервал, на основе которого prometheus оценивает запрос для получения оповещения
В каждом цикле оценки prometheus выполняет выражение, определенное в каждом правиле оповещения, и устанавливает состояние оповещения
Рекомендация: Установите для обоих интервалов одинаковое значение
Alert состояния:
INACTIVE - в неактивном состоянии
PENDING - состояние, в котором находится время, указанное в for
FIRING - состояние, в котором становится после PENDING и отправляется в Alertmanager
Alertmanager
Управляет маршрутизацией алертов, условия, получатели и тд
Настраивается в alertmanager.yaml, состоит из 3 основных блоков:
global:
...
route:
...
receivers:
...
Где:
global - настройки по дефолту, таймауты\интервалы
route - правила маршрутизации, какие алерты куда уйдут
receivers - настройки получателей Email, Telegram и тд
Где:
receiver - получатель по умолчанию, если ни одно правило маршрутизации не подойдет
group_by - по каким labels группировать alerts в одно сообщение
group_wait - сколько ждать перед отправкой первой группы алертов
group_interval - как часто отправлять новые алерты из той же группы (с теми же лейблами)
repeat_interval - как часто напоминать о старых алертах, если до сих пор активен, через сколько отправить повторно
routes:
matchers - labels и их значения, которые должны быть у алерта
receiver - получатель
Поддерживаются регулярные выражения
В message у получателя Telegram используем указанный шаблон с помощью {{ template "telegram" . }}
{{ template "имя" . }} - указание шаблона с передачей данных
Alertmanager обрабатывает алерт, передает в шаблон контекст (.)
. — весь объект алерта, и через него мы получаем в telegram.tmpl - .CommonLabels, .CommonAnnotations, .Alerts
В шаблоне обращаются к ним через .CommonLabels, пример: {{ .CommonLabels.instance }} или {{ .CommonLabels.severity }}
.CommonAnnotations - аннотации, которые совпадают у всех алертов в группе Пример:
summary: "Критическая нагрузка CPU"
description: "CPU загружен на 80% в течение 5 минут"
В шаблоне используем, пример: {{ .CommonAnnotations.summary }} или {{ .CommonAnnotations.description }}
.Alerts - список всех алертов в группе, несколько алертов можно обойти циклом range:
{{ range .Alerts }}
Инстанс: {{ .Labels.instance }}
Значение: {{ .Value }}
Описание: {{ .Annotations.description }}
{{ end }}
Пример с несколькими алертами, алерты будут в одном сообщении:
{{ define "telegram" }}
{{ range .Alerts }}
Алерт: {{ .Labels.alertname }}
Инстанс: {{ .Labels.instance }}
Значение: {{ .Value }}
Описание: {{ .Annotations.description }}
{{ end }}
{{ end }}
Оповещение через Telegram
Переходим в Telegram, ищем BotFather
Создаем нового бота /newbot
Запишите <ТОКЕН_БОТА> токен аутентификации API
Создадим группу
Добавим бота в группу введя ранее придуманный username
Поставить галочку при добавлении бота
Выберем название группы, жмем далее
Получаем chat_id, напишем любое сообщение в группу
Отправим запрос к API телеграм:
curl -XGET https://api.telegram.com/bot<ТОКЕН_БОТА>/GetUpdates
{
"ok": true,
...
"chat": {
"id": -123123123, # Записываем данное значение
...
Запишите значение из result[].message.chat.id, в примере -123123123
Живой пример
send_resolved установлен в true, Alertmanager отправит уведомления после того, когда алерт разрешится
{{ if eq (index .Alerts 0).Status "resolved" }}{{ else }} - меняет запись в письме при статусе алерта
ПРодолжение статьи, живой пример настройки:
Продолжение
Комментарии пользователей
Эту новость ещё не комментировалиНаписать комментарий
Анонимам нельзя оставоять комментарии, зарегистрируйтесь!