Grafana OnCall - это инструмент, который поможет организовать надежное оповещение при инцидентах для вашей команды, поддерживающее интеграцию со Slack и Telegram.
Более подробно о данном продукту можно узнать из статьи или из видео. Целью же данной статьи является выполнение небольшой лабораторки в ходе которой вы ближе познакомитесь с продуктом и пройдете основные этапы работ с ним.
Цель лабораторки, как и всё в этом мире, крайне проста - запустить контейнер nginx и если он отключен прислать оповещение в Slack.
Цепочка взаимодействий будет следующая: используя Prometheus будем считывать метрики Nginx и передавать их в Grafana. Grafana будет отслеживать состояние метрик и реагировать на них соответствующем образом (оповещение в Slack).
Grafana - это сервис по управлению метриками и создания алертов.
Grafana OnCall - плагин позволяющий настраивать оповещение об алертах более детально.
Разобьем нашу задачу на шаги:
Запустим Grafana/OnCall в docker compose;
Добавим плагин “Grafana/OnCall” в “Grafana/Grafana”;
Добавим в docker compose контейнер “nginx” и “prometheus”;
Отследим метрики контейнера “nginx” при помощи “prometheus” и передавать их в “Grafana/OnCall”;
Настроить сценарий реагирования для инцидента останов сервиса Nginx;
Создать бота для Slack и выполнить интеграцию c Grafana/Oncall;
Создадим расписания для оповещений.
Grafana/OnCall и docker compose
GitHub. Для данной задачи мы будем использовать среду: hobby.
Выполним команду:
curl -fsSL https://raw.githubusercontent.com/grafana/oncall/dev/docker-compose.yml -o docker-compose.yml
Выполним команду:
echo "DOMAIN=http://localhost:8080 COMPOSE_PROFILES=with_grafana SECRET_KEY=my_random_secret_must_be_more_than_32_characters_long RABBITMQ_PASSWORD=rabbitmq_secret_pw MYSQL_PASSWORD=mysql_secret_pw" > .env
Выполним команду:
docker-compose up -d
Откроем порт 3000 в браузере: localhost:3000
Логин и пароль - admin. После входа нам предложат изменить пароль, этот шаг можно пропустить нажав кнопку skip.
Плагин “Grafana/OnCall” в “Grafana/Grafana”
Находясь на странице “Grafana” в панели меню в левой части экрана выберите “Configuration” и перейдите в раздел “Plugins”. В поисковой строке наберите “OnCall” и выберите его.

Для инициализации плагина потребуется токен. Для этого выполните команду:
docker-compose run engine python manage.py issue_invite_for_the_frontend --override
Полученный токен необходимо скопировать и вставить в графу “Invite token”, как показано на скрине ниже.

Нажмите кнопку “Enable” для плагина OnCall, убедитесь, что ввели полученный токен в графу “Invite token” и нажмите “Connect”. После добавления плагин Grafana/OnCall появится в меню быстрого доступа в левой части экрана.
Nginx и Prometheus
Добавим в файл docker-compose.yml
код:
web:
image: nginx:1.23.1
ports:
- "8000:80"
Добавим в файл docker-compose.yml код:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
container_name: prometheus
hostname: prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
ports:
- 9090:9090
restart: unless-stopped networks:
- default
В директорию c файлом docker-compose.yml
добавим новый файл prometheus.yml
и добавим в него код:
global:
scrape_interval: 50s #как часто обновлять таргет
evaluation_interval: 60s #как часто производить оценку правил
scrape_timeout: 50s #через сколько времени до истечения срока ожидания запросить обновление
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: [ 'localhost:9090' ]
- job_name: 'nginx'
metrics_path: /metrics
static_configs:
- targets: [ 'web:8000' ]
- job_name: 'grafana'
metrics_path: /metrics
static_configs:
- targets: [ 'grafana:3000' ]
Для наглядности мы добавим для Prometheus 3 источника метрик: Prometheus; Nginx и Grafana. Вновь выполним команду :
docker-compose up -d
Отслеживание метрик контейнера Nginx при помощи Prometheus
Откроем порт “prometheus” 9090 в браузере (localhost:9090). В верхнем меню открывшегося окна выберем “Status/Targets”, подождем выполнения проверки метрик. По итогу мы должны получить следующие.

Как видим два сервиса из трех в состоянии “up”. Причина в том, что для сервиса Nginx не включена функция отображения метрик.
Добавим функцию отображения метрик для нашего контейнера Nginx. Для этого нам потребуется изменить файл конфигурации Nginx default.conf
.
Создадим в нашей директории файл default.conf
и добавим в него следующий код:
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main; 7
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /metrics { # Те самые строки кода,
stub_status on; # которых нам не хватало
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
Дополним код для файла docker-compose.yml
:
web:
image: nginx:1.23.1
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
ports:
- "8000:80"
И так мы квлючили оображение метрик для нашего Nginx, однако новая сложность состоит в том, что формат метрик Nginx не подходит для Prometheus. Для решения этой задачи мы будем использовать контейнер nginx/nginx-prometheus-exporter .
Добавим в файл docker-compose.yml новый блог кода:
exporter:
image: nginx/nginx-prometheus-exporter:0.11
ports:
- 9113:9113
command:
- -nginx.scrape-uri=http://web:80/metrics
Не забудем обновить файл prometheus.yml
:
global:
scrape_interval: 50s
evaluation_interval: 60s
scrape_timeout: 50s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: [ 'localhost:9090' ]
- job_name: 'nginx'
metrics_path: /metrics # Примечание. Если не указать metrics_path, то применится стандартный путь /metrics
static_configs:
- targets: [ 'exporter:9113' ] # Заменили источник метрик на exporter
- job_name: 'grafana'
metrics_path: /metrics
static_configs:
- targets: [ 'grafana:3000' ]
Выполните останов всех контейнеров и перезапустите docker-compose командой:
docker-compose up -d
Повторно выполним вход на порт localhost:9090
. Перейдем в раздел “Status/Targets”. На этот раз статусы всех ресурсов должны быть в состоянии “up”.

Посмотрим какие метрики Prometheus считывает с сервиса Nginx. Откроем порт 9113 в браузере localhost:9113/metrics
. Для нашей конечной задачи нам потребуется отслеживать метрику nginx_up
, которая отвечает за состояние сервиса (up/down).

Настроить сценарий реагирования для инцидента Останов сервиса Nginx
Добавим плагин Prometheus в Grafana. Откроем порт 3000 в браузере localhost:3000
и перейдем в раздел “Configurations/Plugins”. Выполним поиск: Prometheus.

Нажмем на кнопку “Create a Prometheus data source” и выполним настройку. Необходимо задать путь до сервиса Prometheus в графе URL, как показано на скрине ниже.

Остальные настройки оставляем по умолчанию и нажимаем “Save & Test”.

Создадим цепочку эскалации для OnCall (сценарий реагирования на инцидент). Перейдем в раздел “OnCall/Escalations Chains”.

Наш сценарий будет уведомлять пользователя admin об инциденте, выжидать 1 минут и повторно направлять уведомление.
На данном этапе сценарий не будет подразумеваться применения Slack

Перейдем в раздел “Integrations” и создадим новую интеграцию для оповещений, нажав кнопку “New Integration receiving alerts”. Выберем “Grafana Alerting” нажав кнопку “Quick Connect”.

Далее нажимаем “Open Escalations Settings” и выберем ранее созданный сценарий эскалации.

Далее необходимо внести изменения в настройки “Contact points”. Перейдем в раздел “Alerting/Contact points”.

Перейдем в настройки точки доступа.

В графе URL изменим путь с localhost:8080
на engine:8080
. Для проверки точки контакта выполните “Test/Sent test notification” (в правой части окна). Вы должны увидеть сообщение об успешном выполнении теста.
Нажимаем “Save Contact Point” и переходим к настройке “Notification policies”, для этого перейдем в соответсвующий раздел.

Перейдет в настройки “Root policy - default for all alerts” и поменяем “Default contact point” на созданный нами ранее. Сохраним изменения.
Перейдем в раздел “Alert Rules” для завершения настроек.
Нажмем кнопку “New Alert Rules”. Для отслеживание состояния сервисов выберем плагин Prometheus, Metric = nginx_up
.

Метрика nginx_up
передает значение 1 при работе сервиса и 0 при его отключении. Таким образом нам необходимо получать оповещение, когда значение метрики не равно 1. Для этого настроим модуль “B - expression” следующим образом.

В графе “Set alert condition” выберем “B - expression”. Выполним проверку настроенного Alert нажав кнопку “Preview alert” при этом вы не должны получить ошибку в появившемся окне.
Заполним информацию для данного правила оповещения.

Нажмем кнопку “Save and exit”.
Перед проверкой созданного оповещения перейдем в раздел “OnCall/Alert Group”. В таблице будет ранее созданное нами оповещение, которое мы получили при выполнении теста конфигурации “Contact point”.

Проверим работу настроенного оповещения
Произведем останов контейнера Nginx и проверим работу настроенного нами Grafana/OnCall. Откроем в браузере порт 9113 http://localhost:9113/metrics
и увидим изменение отслеживаемой нами метрики nginx_up
, параметр должен быть равен 0.
Проверим наличия оповещения в “OnCall/Alert Group”.

Оповещение не придет мгновенно: Prometheus обновляет метрики раз в 60s, настроенный нами Alert rules выполняет проверку раз в минут, после проверки и получение значения 0 от метрики
nginx_up
состояния Alert измениться с “Norm” на “Pending”, ожидая в течении 5 минут восстановления нормального состояния (=1) и только после этого переведет Alert в состояние “Firing”.
Проверим состояние “Alerting/Alert rules”.

Создадим бота для Slack и выполним интеграцию c Grafana/Oncall;
Для интеграции со Slack контейнер с движком Grafana/OnCall (engine) должен использовать протокол https (localtunel).
Установим localtunel выполнив команду npm install -g localtunnel
и добавим в наш проект выполнив команду в директори с doker-compose yarn add localtunnel
Запустим контейнер Grafana/OnCall (engine) используя протокол https:
lt --port 8080 -s <URL_ADDRESS> --print-requests
например lt --port 8080 -s galgameth-fcm-96 --print-requests
Откроем наш URL и завершим установку.

Создайте рабочее пространство в Slack или используйте существующее.
Перейдем по ссылке https://api.slack.com/apps и добавим нашего бота, нажав на Create an App. Выберем From an app manifest и определим рабочее пространство для бота.
Создадим yaml манифест.
_metadata:
major_version: 1
minor_version: 1
display_information:
name: <YOUR_BOT_NAME>
features: app_home:
home_tab_enabled: true
messages_tab_enabled: true
messages_tab_read_only_enabled: false
...
interactivity:
is_enabled: true
request_url: <ONCALL_ENGINE_PUBLIC_URL>/slack/interactive_api_endpoint/
org_deploy_enabled: false
socket_mode_enabled: false
<YOUR_BOT_NAME>
- имя вашего бота, например test_bot_rb
.<ONCALL_ENGINE_PUBLIC_URL>
- ранее созданный url адрес для контейнера engine, в нашем случае https://galgameth-fcm-96.loca.lt/
.
Нажимаем Next - Create. Выполним верификацию для нашего бота: test_bot_rb/Features/App manifest. Нажмем Click here to verify и завершим настройку бота.

Установим наш бот в рабочее пространство test_bot_rb/Settings/Basic informations

Проверим наши настройки

Проведем интеграцию Slack и Grafana/OnCall.
Зайдем на порт localhost:3000
и выполним вход в Grafana. Перейдем в раздел Grafana OnCall/ChatOps и впервую очередь произведем настройку ENV variables.

Нам необходимо внести следующие данные:
SLACK_CLIENT_OAUTH_ID
= Basic Information -> App Credentials -> Client ID;SLACK_CLIENT_OAUTH_SECRET
= Basic Information -> App Credentials -> Client Secret;SLACK_SIGNING_SECRET
= Basic Information -> App Credentials -> Signing Secret;SLACK_INSTALL_RETURN_REDIRECT_HOST
= << OnCall external URL >>.

Вернемся в раздел ChatOps и нажмем Install Slack integration, далее I’ll check.. и Разрешить. Вы получите сообщение “Не удается получить доступ к сайту”, интеграция выполнена.
Вновь войдите в раздел ChatOps и настройте ваш Slack integration.
Для данного бота был создан канал в Slack “grafana oncall“. Выберем данный канал для оповещений от OnCall.

Создадим расписание оповещений
Перейдем в раздел Schedules и нажмем Add schedule for on-call rotation. Для нашего расписания будем использовать “google calendar”.
Укажем название нашего расписания и добавим ical url, для этого перейдем в календарь, выберем интересующий нас календарь и зайдем в его настройки

и скопируем “Secret address ical format”.

Внесем данные и завершим создание расписания нажав Create Schedule.

Создадим расписание при котором с 9:00 до 14:00 оповещения будут приходить пользователю “Roman”, а с 14:00 и до 21:00 пользователю “admin”.
Пользователь "admin" создается по умолчанию, доп. пользователь создается в разделе доступном администратору: Server Admin/Users - New user
Перейдем в календарь и выполним настройку расписания. Для каждой временного участка мы указали соответсвующее имя пользователя Grafana. Для пользователя admin дополнительно указали [L1], что позволяет разделить наших пользователей по уровням. Перейдем в раздел Grafana OnCall/Schedules и нажмем Reload для нашего распис

На скрине выше представлена информация из календаря, а также пользователь, которому в данный момент будут приходить оповещения (OnCall now).
Обновим ранее созданное оповещение в разделе Grafana OnCall/Integrations выполнив следующие настройки:
Направим оповещения в канал Slack: Grafana OnCall;
Добавим “Notify user from on-call schedule” и выберем наше расписание.

Выполним тестирование нашего оповещения нажав “Send demo alert” (верхний правый угол скрина выше). Проверим получение оповещения в Slack.
Проверим работу оповещения остановив контейнер Nginx

Поздравляю, вы дошли до конца!
Надеюсь данная статья хоть немного помогла Вам с освоением продукта Grafana/OnCall.
Комментарии (9)
Matvey-Kuk
21.11.2022 15:57+1Отличная статья! Спасибо за такое подробное описание всей связки!
Несколько добавлений:
В версии 1.1 появился полноценный редактор расписаний, можно даже без гугл календаря.
Можно конфигурировать кодом через терраформ: https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/oncall_escalation
У Grafana OnCall есть русскоязычный чатик: https://t.me/amixr_ru
skymal4ik
Расскажите, чем не подошёл или не устроил AlertManager от Prometheus? Вроде по функционалу то же самое, но с настройкой явно проще, по сути один yaml с правилами и всё.
onegreyonewhite
Наверное это для адептов мышкакликательных свидетелей гуя. Они же не умеют в cli и конфиги, им GUI подавай и 100500 кликов мышкой.
RoCman Автор
Большую часть операций выполненных в мануале можно описать в docker-compose файле. Например используя Provision Grafana.
Сразу скажу, что я не являюсь амбассадором Grafana и не пытаюсь её кому либо навязать :)
sergeykons
OnCall умеет в Escalation plans и прочие нужные фичи. Настраивать да все приходится через GUI.
Но как Oss альтернатива PagerDuty вполне неплохо
RoCman Автор
У Prometheus AlertManager функционал примерно такой же, как у Grafana Alerting. Отследим метрики, сгруппируем алерты и направим письмо на почту.
OnCall же позволяет создавать цепочки эскалации, расписание для сотрудников и интегрируется со Slack и Telegram.
skymal4ik
Спасибо, это интересно, надо будет глянуть ради расширения кругозора.
Ps начиная с версии v0.24 AlertManager так же умеет telegram нативно.
Wernisag
Тут скорее аналогично вопросу про мониторинг. Зачем нужна вика, пром, заббикс, [подставь что-то своё], когда есть ещё какая-то система мониторинга.
Собственно, одна система что-то умеет, другая нет, третья делает это лучше, а четвертая проще. OnCall скорее нужен для дополнения AlertManager, а не вместо него.
Вот тут чуть подробнее про возможности OnCall
nspickiy
Grafana OnCall это всё таки аналог не Alert Manager, а PagerDuty, opsGenie и прочее, то есть когда у вас есть команды, дежурства, расписания, эсколации, постмортемы и так далее.