Привет! Я Сергей, DevOps-инженер в KTS.

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

Новую систему я выбирал среди self-hosted, чтобы больше не зависеть от зарубежных провайдеров. Нашел два подходящих решения, IncidentRelay 1.1 и OneUptime 11.4.1, поднял оба в Kubernetes и сравнивал уже на своих сценариях дежурства. Ниже расскажу, почему был выбран OneUptime.

Оглавление

Почему не Telegram-бот

Расписание дежурств в боте не заведешь. Сегодня алерты по проекту получаю я, завтра другой инженер, и слать все подряд всем девопсам не нужно. С PagerDuty нам жилось хорошо: забили расписание в систему и получаем алерты строго в свои смены.

Еще нужны цепочки эскалации. Сначала алерт получает поддержка; если она не отреагировала за отведенное время, инцидент уходит дежурному девопсу, а если молчит и он, поднимается до тимлида. В Telegram такую цепочку не собрать, разве что городить свой сервис и изобретать велосипед.

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

Сам Telegram к тому же стал ненадёжным каналом. У кого-то отвалился VPN, уведомление пришло через час или не пришло вовсе, а для оперативного алертинга такой канал уже не годится. Так я и стал искать полноценную замену PagerDuty и начал с IncidentRelay.

IncidentRelay

IncidentRelay 1.1 был ближе к тому тонкому пейджеру, который я искал. Официальный helm-чарт поднялся быстро, нативные интеграции с Alertmanager и Mattermost были на месте, а наш Keycloak подключился так, что роли и права можно было забирать прямо из IdP. Для Telegram там же можно указать прокси.

Ограничения всплыли, когда я пошел по сценариям дежурного. Интерфейс местами подсказывал нужное действие только со второй или третьей попытки, часть элементов отрисовывалась криво, а дашбордов со статистикой по инцидентам не было совсем. Сильнее всего не хватило мобильного приложения: днем без него можно жить, но для ночного дежурства мне нужен был нормальный push-канал.

Проект еще молодой, и каких-то функций в нем может не быть просто по возрасту, но ждать я не стал и отложил его.

IncidentRelay 1.1: интерфейс пилота
IncidentRelay 1.1: интерфейс пилота

OneUptime

OneUptime с ходу показался куда взрослее. В нем есть свои мониторы, агенты, статусные страницы, ранбуки, интеграции с LLM и GitLab, хотя мне для пилота хватало инцидентов, расписания дежурств, эскалаций, метрик и доставки алертов.

Расписания и правила эскалации работали, в UI был русский язык, мобильное приложение принимало push-уведомления. Метрики по инцидентам и времени решения тоже есть, но централизованного дашборда по всем проектам я не нашел, и чтобы посмотреть цифры, приходится заходить в отдельный монитор проекта. Жить можно, просто лишний заход на каждый проект.

Метрики доступны внутри отдельного монитора
Метрики доступны внутри отдельного монитора

Правда, инфраструктуры он просит заметно больше. Ему нужны Postgres и ClickHouse, по ресурсам и количеству компонентов он тяжелее IncidentRelay, и копией PagerDuty я бы его не назвал: это большая платформа, от которой мне нужен только слой инцидентов и on-call.

Если будете ставить ее себе, документация по установке у проекта не самая подробная. В ней не было явно сказано, что внешнему Postgres нужно расширение uuid-ossp, а ClickHouse должен быть реплицируемым, иначе OneUptime не запускается. Для ClickHouse я в итоге взял Altinity operator в Kubernetes (как вариант, можно взять внешний managed ClickHouse с репликацией). Оба нюанса пришлось выяснять, отлавливая ошибки в логах.

С Telegram из России вышло хуже, чем в IncidentRelay: прокси для него в OneUptime не задать, и канал работает криво, пока не отфильтруешь трафик и не повесишь внешний прокси только на обращения к Telegram. Рядом с ним есть пуши из приложения и почта, так что если один канал даст сбой, алерт все равно дойдет до инженера.

UI-конструктор workflow

У OneUptime нет нативной интеграции с Alertmanager, поэтому я решил попробовать его нативный Workflow для обработки входящих алертов. Внешняя система отправляет информацию о событии в вебхук, после чего запускается собранная вручную цепочка, в которой можно разобрать пэйлоад, добавить теги и создать или обновить инцидент.

Мне это подходило, потому что алерты из разных проектов приходят в разных форматах. Казалось, на каждый проект можно собрать свой workflow, положить внутрь Custom Code и получить свой маппинг.

Но на деле не все так радужно. Я не нашел версионирования и API для управления workflow, а перенести цепочку в другой проект (тут под проектом подразумевается изолированное окружение OneUptime) нельзя (хотя внутри одного проекта ее можно дублировать). А когда логика отображается только в UI-конструкторе, ее сложнее ревьюить, повторять между окружениями и восстанавливать.

Я еще попробовал накинуть на инциденты теги вроде проект1 и проект2, чтобы видеть источник и разводить по ним эскалации. Схема работала, но в общей таблице источник так и оставался тегом, не привязанным к затронутому ресурсу OneUptime.

Workflow, который я тестировал для приема внешних алертов
Workflow, который я тестировал для приема внешних алертов

Incoming Request

После неудачи с Workflow я перешел на мониторы типа Incoming Request. У каждого такого монитора есть свой URL и secret key: внешняя система отправляет туда HTTP GET или POST, а OneUptime сам источник не опрашивает.

В документации этот тип монитора описан и как heartbeat-мониторинг, но я использую его для приема внешних алертов. По сетевой модели это все еще вебхук, зато в модели данных он становится монитором, то есть ресурсом OneUptime, и именно из-за этого я на нем и остался.

Это оказалось полезнее UI-конструктора. Алерты нормально переходят в resolved без ручного Update Incident, а в общей таблице появляется колонка Affected Resource, по которой сразу видно затронутый монитор. Аналитику по проектам теперь удобнее строить по монитору, чем по служебному тегу на инциденте.

Разные форматы входящих алертов никуда не исчезли, и настраивать контракты все равно нужно. Но когда единицей настройки становится монитор с собственным URL, такую схему проще сопровождать.

Монитор виден как затронутый ресурс
Монитор виден как затронутый ресурс

Что с ролевой моделью

В IncidentRelay интеграция с Keycloak поддерживала RBAC из IdP. В OneUptime я сумел завести веб-SSO, но передачи ролей из Keycloak там нет, и модель доступа получилась шире, чем мне требовалось. Можно пригласить человека на email, к которому привязана его Keycloak-учетка, а в другом режиме войти сможет любой пользователь с учетной записью в этом Keycloak, так что политику приглашений и прав приходится проектировать уже на стороне OneUptime.

Функция OIDC в OneUptime отнесена к Enterprise, но в self-hosted установке это ограничение можно снять самостоятельно: лицензия это допускает.

С мобильным приложением вышло обиднее. Пуши после входа работают корректно, но войти через корпоративный Keycloak мне не удалось, потому что приложение обращается к неправильному эндпоинту, хотя в вебе тот же SSO-сценарий проходит. Тестировал я его пару месяцев назад, когда на iOS приложение давно не обновлялось. Недавно его снова начали обновлять, и ошибку, возможно, уже поправили, но перепроверять я не стал: проще остаться на встроенной авторизации, чем при каждом обновлении OneUptime, а обновляется он часто, заново снимать ограничение Enterprise.

Как проходил переезд

Перенести настройки из PagerDuty автоматически я не смог, потому что мой доступ в аккаунт был заблокирован полностью. У кого-то из коллег вход еще работал, но выгружать расписания и политики мы в итоге не стали: проекты мы и так знали, а времени на аккуратный экспорт не было.

OneUptime я ставил с нуля и настраивал руками, параллельно разбираясь, что в нем вообще есть и как оно устроено. Расписания и цепочки эскалации собрал заново по памяти и по нашим внутренним договоренностям.

Теоретически перенос можно автоматизировать. У PagerDuty есть MCP-сервер, у OneUptime MCP встроен в сам продукт, и через них LLM могла бы выгрузить расписания и политики из одной системы и завести их в другую. Я этот путь не проверял, поэтому за результат не ручаюсь. Кстати, MCP в OneUptime не работает с workflow, и для конструктора, который и так живет только в UI, это еще один жирный минус.

Что получилось в итоге

Я держу интеграции разных команд в одном проекте OneUptime. Пока источники жили на workflow, отличить их можно было только по тегам, а после перехода на Incoming Request в общей таблице появился сам затронутый ресурс, монитор, и очередь стало проще разбирать глазами. Healthchecks.io я оставил на месте: он по-прежнему следит за cron и скриптами и отдает события в OneUptime по вебхуку, встроенными мониторами я его не заменял.

Результаты пилота:

Критерий

IncidentRelay 1.1

OneUptime 11.4.1

Инциденты, дежурства, эскалации

Поддерживает

Поддерживает

Метрики по инцидентам

Нет

Есть внутри отдельного монитора

Alertmanager

Нативная интеграция

Можно через Incoming Request

Telegram

Есть, прокси задается в продукте

Есть, прокси задать нельзя. Из РФ работает криво, нужен внешний прокси на трафик Telegram

Mattermost

Нативная интеграция

Можно через WhatsApp, Telegram, Slack и Teams

Мобильное приложение

Нет

Есть, пуши работают

Keycloak

OIDC и RBAC из IdP

Веб-SSO есть, RBAC из IdP нет

Деплой в Kubernetes

Легкий Helm-деплой

Тяжелый Helm-деплой, реплицируемый ClickHouse

IncidentRelay 1.1 я не взял, хотя нативные Alertmanager, Mattermost и RBAC из Keycloak мне зашли, и у более взрослого проекта это был бы сильный набор. Перевесили сырой интерфейс, в котором нужное действие находишь со второй попытки, и отсутствие мобильного приложения: без пушей ночную смену я представлял плохо, а ждать, пока продукт дорастет, было некогда.

OneUptime 11.4.1 остался инцидент-хабом и on-call. За это мы платим ресурсами, самодельным приемом Alertmanager, внешним прокси на трафик Telegram, отсутствием ролей из Keycloak и мобильным SSO, который так и не завелся, но дежурства, эскалации и единая очередь закрыты, а уведомление идет пушами, Telegram и почтой, так что сбой одного канала дежурного без алерта не оставляет. Метрики, пусть и без общего дашборда на все проекты, смотрятся внутри мониторов.

А что по денежкам? Подписки команды на PagerDuty обходились нам примерно в десять раз дороже, чем ресурсы, которые ест self-hosted OneUptime, но в эту разницу не входит мое время: пилот двух продуктов и переезд с Workflow на Incoming Request заняли не один день, ошибки с ClickHouse и патч для OIDC добавили возни, и дальше время будет уходить на обновления и бэкапы.

Кстати, мои коллеги тоже пишут о своих экспериментах. Из свежего рекомендую:

Комментарии (0)