Контур делает несколько десятков продуктов, каждый из которых состоит из нескольких десятков микросервисов, каждый из которых запущен на десятках серверов.
Эта инфраструктура порождает метрики на всех технологических уровнях — нагрузка на железо, состояние ОС, метрики приложений. Исходные данные собираются в один большой кластер Graphite. Сейчас у нас есть миллион уникальных метрик, по которым суммарно генерируется 20 тысяч значений в секунду.
Ясно, что за миллионом метрик не уследить глазами на телевизорах и дашбордах — нужна система отправки уведомлений о нештатных ситуациях. Перед тем как написать свою систему Moira, мы использовали для этой задачи Seyren.
Плюсы и минусы Seyren
Seyren позволяет через веб-интерфейс указать произвольное выражение на языке функций Graphite и подписаться на уведомления. Уведомления приходят в том случае, если результат вычисления выражения превысил фиксированный порог.
Кажется, это то, что нужно. Но за год эксплуатации Seyren мы наступили на несколько граблей:
- Внутри Контура есть несколько команд, которые делают разные продукты. В Seyren нет понятия «пользователь» или «группа» — каждый видит настройки и события всех остальных в одном огромном списке.
- Seyren при вычислении значения метрики полагается на API Graphite и сама никак не валидирует введенные выражения. Ошибки при этом падают где-то внутри в логи, а в веб-интерфейсе все выглядит работающим. Если вы нарисуете график в веб-интерфейсе Graphite, нет никакой гарантии, что такое же выражение будет работать в Seyren. А если и будет, его вычисление может дать неожиданный результат.
- Не все запросы в Graphite работают эффективно. При большом количестве метрик выражение может вычисляться несколько секунд. Не беда, если это происходит однократно по запросу пользователя. Но Seyren запрашивает каждое сохраненное выражение через API Graphite раз в минуту. Если таких выражений в Seyren несколько, они гарантированно убивают кластер любого размера. Не хочется учить всех пользователей мониторинга искусству составления оптимальных запросов в Graphite.
- Seyren пропускает события. Мы своими глазами видели точки на графике, которые выходили за пороговое значение, но Seyren при этом необъяснимо молчала. Стабильно воспроизвести и, тем более, починить этот баг нам не удалось.
Альтернативы Seyren
А почему мы вообще выбрали Seyren? Должны быть другие варианты.
Seyren — это лучшее, что было в разделе Monitoring на странице Tools That Work With Graphite из официальной документации Graphite. Мы пробовали все и выбрали Seyren. Возможно, вам подойдет что-то другое с этой страницы (теперь Moira там тоже есть).
Еще есть riemann. Скорее всего, это самая гибкая и производительная система мониторинга в мире. Она поддерживает входящие данные в формате Graphite. Настройки riemann — это код, который хранится в репозитории. Одним словом, это настоящий DevOps.
К сожалению, у riemann слишком высокий порог входа. Для Seyren этот порог нулевой — если вы пользуетесь Graphite, скопировать выражение в Seyren не требует никаких дополнительных знаний. Конфигурация riemann — это код на Clojure. Страница Just enough Clojure to work with Riemann — это пара часов вдумчивого чтения, даже если вам знакома концепция функционального программирования. Мы хотим, чтобы любой разработчик мог настроить уведомления о неполадках в своей зоне ответственности, не изучая новый язык программирования.
А раз уж мы начали обсуждать, чего мы хотим или не хотим, давайте поймем, какие у нас вообще есть требования к системе уведомлений.
Требования к системе отправки уведомлений
- Не должна нагружать кластер Graphite частыми автоматизированными запросами. Хорошо, если она вообще не будет зависеть от основного кластера Graphite.
- Должна поддерживать все функции Graphite и вычислять их так же, как они вычисляются при построении графиков.
- Должна уметь различать пользователей и дать им возможность настраивать, что они будут видеть в веб-интерфейсе.
- Должна уметь отправлять уведомления через популярные каналы — электронную почту, Slack, Pushover, Telegram. При этом добавление новых плагинов должно быть не слишком сложным.
Moira: как мы построили такую систему
Moira состоит из модулей, как и сам Graphite. Сейчас это принято называть микросервисной архитектурой. Это позволяет в любой момент заменить часть системы на более производительную или более функциональную, не выбрасывая систему целиком. Все части Moira независимы друг от друга и общаются только через единое хранилище данных Redis.
moira-cache
Мы хотим оставить в покое Graphite — следовательно, мы хотим получать копию потока входящих метрик. Но входящих метрик очень много.
Чтобы решить эту проблему, нужно учесть два обстоятельства:
- Для оповещений нужна только свежая информация — историю при необходимости можно посмотреть в Graphite.
- Среди всего потока входящих метрик нужны только те, на которые настроено хотя бы одно правило оповещения.
Moira-cache — это быстрый сервис на Go, который принимает входящий поток метрик, фильтрует из них нужные и сохраняет в Redis кэш значений этих метрик за последний час.
moira-worker
Мы хотим поддерживать все функции Graphite, и чтобы они вычислялись в точности так же, как в самом Graphite. Раз уж Graphite выложен в opensource, самый надежный способ добиться результата — взять исходники Graphite и включить их прямо в наше приложение.
Moira-worker — это сервис на Python, который проверяет значения в кэше с помощью оригинального кода функций Graphite и генерирует события для оповещения.
Кроме того, мы добавили в moira-worker возможность использовать для уведомлений не только функции Graphite, но и более универсальные Python-выражения.
страница редактирования уведомлений
moira-web
Мы хотим уметь различать пользователей и показывать каждому только то, что он хочет видеть. Это две задачи.
Как различать пользователей? Система мониторинга — это инструмент для интранета, и здесь невозможно придумать одно решение для аутентификации, которое устроило бы всех. Кому-то нужен LDAP, кому-то логин через GitHub или Google. Мы не стали ничего придумывать: Moira просто доверяет заголовку X-Webauth-User, полученному от вышестоящего веб-сервера (например, nginx или oauth_proxy). Чтобы Moira научилась различать ваших пользователей, вам нужно передать в значении этого заголовка идентификатор пользователя (например, логин).
Как показывать пользователю только те настройки, которые он хочет видеть? Для этого мы используем теги, которые работают как в веб-интерфейсе, так и в настройке уведомлений.
список настроенных уведомлений на главном экране
страница редактирования подписок
moira-notifier
Мы хотим уметь отправлять уведомления через популярные каналы — Slack, Telegram, почту, Pushover. Кроме того, moira-notifier:
- Умеет соблюдать заданное расписание (например, не беспокоит ночью по пустякам).
- Защищает пользователя от заваливания письмами, если какой-то из триггеров «взбесился» и начал присылать уведомления слишком часто.
- Повторяет отправку уведомления, если произошла ошибка доставки.
Как попробовать Moira? Как задать вопрос разработчикам?
Мы используем Moira в продакшен-окружении уже полгода. На одной восьмиядерной виртуальной машине мы обрабатываем входящий поток в 20 тысяч точек в секунду при тысячах отслеживаемых метрик и сотнях пользователей.
В конце 2015 года мы решили, что Moira уже достаточно стабильна для того, чтобы предложить opensource-сообществу попробовать ей воспользоваться.
Инструкция по установке и использованию есть в нашей документации. Кроме того, вы можете посмотреть код на GitHub, прислать багрепорт или пуллреквест.
Если ваша нагрузка выше, или у вас сильнее ограничены ресурсы — приходите пообщаться в наш чат Gitter. Мы расскажем, как масштабировать Moira для вашего случая, или вместе попробуем оптимизировать ее код.
И, конечно, мы с удовольствием ответим на ваши вопросы в комментариях.