[Перевод] Как мы переехали с StatsD на Prometheus всего за месяц
Недавно мы мигрировали все наши инфраструктурные метрики с StatsD на Prometheus и остались очень довольны результатами. Это была нелёгкая работа, но мы многому научились в процессе. Эта статья призвана рассказать, почему мы выбрали Prometheus, а также описать некоторые технические сложности, с которыми мы столкнулись.
Предыстория
Метрики стали настолько важной и обыденной частью современных распределённых систем, что легко забыть, что популярные протоколы открытых метрик появились всего-то в прошлом десятилетии. StatsD был разработан в Etsy в 2011 году, а вскоре за ним последовал Prometheus от SoundCloud в 2012 году. Оба собирают одни и те же типы данных (counters, gauges, и sample distributions), но их архитектура значительно отличается, отражая приоритеты систем, из которых они возникли. Например, модель StatsD с отправкой через push делает сбор метрик простым как раз-два, если ваш процесс может отправить UDP-пакет, тогда как децентрализованная модель Prometheus с опросами облегчает масштабирование сбора метрик.
Mixpanel вовремя запрыгнула на этот «поезд метрик» — мы ведь, в конце концов, аналитическая компания. Мы начали собирать метрики через StatsD в 2013 году (всего через два года после нашего знакового поста о том, почему мы ушли из облака). Для быстро развивающегося, многозадачного стека, работающего на фиксированном количестве серверов, StatsD был разумным выбором. Вопрос масштабирования метрик даже не стоял на повестке дня, а клиентские библиотеки были невероятно простыми в реализации и понимании.
Но время идёт, и инфраструктура Mixpanel претерпела кардинальные изменения. Мы вернулись в облако (на этот раз без знакового блог-поста), что дало нам гораздо больше свободы для разделения и масштабирования наших критически важных сервисов. Теперь наши сервисы работают на Kubernetes, а индивидуальные поды порождают десятки тысяч метрик в секунду. У инженеров также появились гораздо более серьезные ожидания по количеству потерянных метрик (ноль!). Чтобы справиться с этими новыми требованиями, мы перевели наши StatsD sidecar на использование TCP и перенесли агрегацию метрик на клиентов (что уменьшило задержки, вызванные большими выбросами в соединения StatsD).
В какой-то момент мы переросли традиционный StatsD и случайно создали собственную проприетарную архитектуру метрик. Поэтому, когда пришло время менять поставщика метрик, мы поняли, что у нас было несколько веских причин перейти в экосистему Prometheus:
Производительность
Многое из того, что мы сделали для повышения производительности наших внутренних библиотек метрик, тесно связано с архитектурными решениями Prometheus. Модель запросов Prometheus устраняет вероятность потери метрик, а запись метрики сводится к одной атомарной операции в клиентском процессе.
Снижение привязки к поставщику
PromQL и Grafana являются открытыми стандартами, что значит, что работа, которую мы вложили в миграцию наших коллекторов данных, дашбоарды и alert queries, может быть помочь нам на множестве разных платформ. Это уменьшит завязку на поставщике и даст нам массу гибкости для тестирования новых платформ метрик.
Экосистема
Мы любим метрики, но мы не компания по работе с инфраструктурными метриками. Инвестируя в экосистему Prometheus, мы можем использовать все обновления и улучшения, которые придумывает сообщество (например, exemplars, native гистограммы) и освободить наши силы для других, более важных для нашего бизнеса, вещей.
Задачи
Проблемы, с которыми мы столкнулись в процессе миграции, можно разделить на три основные категории: сбор метрик, изменение формы метрик и переписывание запросов.
Сбор метрик
Первой проблемой, с которой мы столкнулись, было то, как перенести наши существующие метрики в стек Prometheus. Мы выдвинули несколько требований к решению:
На период миграции метрики должны отправляться одновременно в протоколах StatsD и Prometheus .
Мы не должны требовать от сервисов переписывания кода приложений.
Не должно быть деградации производительности на стороне клиента.
Доступ к стандартным типам метрик распределения Prometheus (сводки, гистограммы, native гистограммы).
Существуют инструменты, такие как statsd_exporter, поддерживаемый организацией Prometheus, который отлично подходит для сервисов, использующих стандартный протокол StatsD. Он работает, ретранслируя трафик StatsD из вашего приложения на ваш обычный сервер StatsD, а также конвертируя метрики в протокол Prometheus и публикуя их на HTTP-эндпоинте /metrics.
Архитектура exporter sidecar
К сожалению, statsd_exporter не совсем подходил нам, так как многие наши сервисы агрегируют метрики в процессе, что означало, что мы не смогли бы получить доступ к распределению по типам метрик в Prometheus. Какое бы решение мы ни придумали, оно должно было быть встроено в клиентский процесс.
Именно это мы и сделали. Все наши критически важные сервисы написаны на Go, и, к счастью, statsd_exporter имеет открытый исходный код, и тоже написан на Go. Нашим решением стало добавить statsd_exporter в наш внутренний SDK метрик на Go и обрабатывать метрики непосредственно в памяти. Этот подход также дал некоторые дополнительные преимущества:
Сервисы могли плавно начать переход на официальный Prometheus Go SDK в своём темпе.
После миграции у нас будет система сбора без sidecar.
После некоторой работы по оптимизации производительности мы получили решение, которое удовлетворяло всем нашим требованиям!
Архитектура встроенного экспортёра
Выводы
Сбор метрик можно продумать заранее. Для владельцев сервисов обычно предельно просто переделать свои сервисы для работы с Prometheus.
statsd_exporter уже решил эту проблему, поэтому используйте его, где только сможете.
Убедитесь, что для сервисов есть возможность начать использовать нативные клиентские SDK Prometheus в будущем
Преобразование метрик
Следующей задачей, с которой мы столкнулись, был вопрос, как изменить форму наших метрик. В этом контексте форма метрики относится к её имени, меткам и единицам измерения. Хотя базовые модели данных современных StatsD и Prometheus практически идентичны, у них есть много разных соглашений, которые могут иметь неприятные последствия для эргономики запросов.
StatsD изначально не поддерживал теги и кодировал каждое измерение метрики в ее имени. Хотя большинство реализаций теперь поддерживают теги, соглашение о точечных пространствах имен по-прежнему широко используется, и многие метрики используют комбинацию префиксов имен и тегов для кодирования измерений.
Prometheus, с другой стороны, настоятельно не рекомендует кодировать измерения в имени метрики. Фактически, некоторые запросы PromQL будут полностью сломаны, когда вы попытаетесь выполнить агрегацию по измерениям, закодированным в имени метрики, например, следующий запрос коэффициента успеха:
sum(rate(
arb_lqs_grpc_server_LQS_Execute_OK[5m]
))
/
sum(rate(
{__name__=~"arb_lqs_grpc_server_LQS_Execute_.+"}[5m]
))
// Ошибка расширения ряда: вектор не может содержать метрики с одним и тем же набором меток
В наших первоначальных экспериментах мы быстро поняли, что нам нужно принять некоторые очень важные решения первого типа относительно формирования метрик. Хотя можно написать запрос, который обходит это ограничение, мы совсем не хотели, чтобы наши инженеры годами считали его нормальным. Нам нужно было найти способ полностью перенести размерность в метки, опять же, не требуя от инженеров повторной переделки кода приложения.
Первым низко висящим фруктом была замена наших перехватчиков метрик RPC (RPC metrics interceptors) стандартными перехватчиками Prometheus с открытым исходным кодом, такими как тот, который предоставляется grpc-ecosystem/go-grpc-middleware:
sum(rate(
grpc_server_handled_total{
grpc_service="LQS",
grpc_method="Execute",
grpc_code="OK"
}[5m]
))
/
sum(rate(
grpc_server_handled_total{
grpc_service="LQS",
grpc_method="Execute"
}[5m]
))
// Нет ошибки!
Это одно изменение в конечном итоге оказало огромное влияние, поскольку метрики RPC на сегодняшний день являются наиболее запрашиваемыми метриками.
Для других метрик statsd_exporter предоставляет интерфейс конфигурации для определения сопоставлений метрик, который использует правила сопоставления с шаблонами для преобразования метрик на лету. Однако на практике мы обнаружили, что инженеры (у которых ограниченное время) предпочтут написать «хакерский» запрос, чем разбираться, как написать правило сопоставления, требующее полного повторного развертывания их сервиса. Мы надеемся, что эти оставшиеся проблемные метрики в конечном итоге будут преобразованы и переинструментированы с помощью нативного SDK Prometheus.
Выводы
PromQL плохо справляется с измерениями, закодированными в имени.
Замена перехватчиков RPC — это огромный выигрыш для преобразования метрик и требует очень мало усилий.
Потратьте дополнительное время, чтобы выяснить, как вы хотите преобразовать метрики перед миграцией запросов.
Переписывание запросов
Последней задачей было переписать все наши запросы дашбордов и оповещений в PromQL. Дашборды необходимо было перенести из проприетарного формата нашего старого поставщика в Grafana, а оповещения — в проприетарный формат нашего нового поставщика.
Можем ли мы автоматизировать это?
Первоначально мы изучили инструменты для автоматического переписывания наших существующих запросов в PromQL, но оказалось, что это практически неразрешимая проблема. Существует слишком много нюансов в различиях между языками запросов временных рядов и их базовыми данными даже в реализациях PromQL, не говоря уже о совершенно разных спецификациях языков запросов.
Хотя мы не могли автоматически портировать запросы, технически было бы возможно программно преобразовать шаблоны дашбордов и оповещений таким образом, чтобы инженерам нужно было только заполнить запросы. К сожалению, к тому времени, когда мы придумали этот подход, миграция зашла слишком далеко, чтобы оказать существенное влияние.
Уменьшение боли
Поскольку не было никакого способа обойти рутинный труд ручного переписывания запросов, нашей задачей стало сделать этот процесс как можно менее болезненным.
Работа, которую мы проделали в первых двух категориях, была отличным началом; инструментирование Prometheus для сервиса можно было включить с помощью одного флага функции, и наши метрики уже были преобразованы и готовы к запросу. Кроме того, мы установили несколько рабочих часов в неделю, где мы могли помочь инженерам с вопросами или проблемами PromQL. Мы постарались все документировать, чтобы помочь всем нашим инженерам как можно быстрее освоить PromQL.
В общей сложности было перенесено ~300 дашбордов и ~600 оповещений, что в общей сложности составило примерно 4000 переписываний запросов. И силами 20 инженеров мы смогли завершить эту фазу миграции чуть более чем за 1 месяц!
Выводы
Убедитесь, что вы полностью понимаете объем работы, прежде чем приступать к миграции.
Автоматизируйте преобразование шаблонов дашбордов и оповещений, если это возможно.
Хорошо разберитесь в PromQL заранее, и выделите время, чтобы поделиться своими знаниями со всеми остальными.
Заключительные мысли
Я невероятно горжусь тем, насколько эффективно наша команда инженеров смогла выполнить эту миграцию. Я также рад видеть, как экосистема Prometheus развивается с течением времени, и рад сообщить, что Mixpanel будет участвовать в этом процессе!