Всем привет!
Меня зовут Александр Ковалев, и я занимаюсь разработкой инженерных продуктов Platform V Works. В этой статье поговорим про observability, а именно про конкретную область — мониторинг в продуктах. Обсудим, как вообще появляется сама идея мониторинга, какие есть варианты реализации. Расскажу, по какому пути пошли мы, какие ресурсы и материалы использовали.
Статья может быть полезна тем, кто впервые сталкивается с такими инструментами, как Prometheus и Grafana, а также всем, кто хочет изучить чужие примеры и прокачать компетенции в данной области.
Представьте сервис: веб-сервер с конечной точкой (endpoint), куда пользователь шлёт запросы. Пока пользователь один, хватает стандартного логгера: видим, что записи в логах появляются, можем посмотреть ошибки и их текст.
Но по мере развития сервиса пользователей становится много, они объединяются в группы под разные сегменты, продукты или команды, а бизнес-функциональность усложняется. Можно по-прежнему анализировать происходящее через логи: развивать систему журналирования, переходить от терминала к Kibana/OpenSearch, настраивать там View и собирать фильтры. Но это неудобно, если помимо бизнес-событий нужны ещё и инфраструктурные показатели — нагрузка, задержки, ошибки на сетевом уровне. А эти показатели, в зависимости от зрелости организации, кто-то до сих пор смотрит через терминал или Zabbix.
В промышленном контуре возникает вопрос: «Достаточно ли нам логов для понимания того, что конкретно пошло не так при серьёзном сбое?» Изучая только логи, мы смотрим на единичные срабатывания, и контекст проблемы смещается для каждой выбранной строчки, а в голове при этом крутится мысль: «Эту проблему мы знаем, она не влияет ни на что».
Мы для себя сформулировали ответ: одних логов недостаточно. Да, они остаются, но в дополнение к ним нам нужно видеть срезы состояния систем на множестве панелей в реальном времени. Внедряя мониторинг, мы добавляем налог на развитие, актуализацию и сопровождение. Данным подходом мы не делаем огромный шаг, в корне срезающий стоимость анализа проблем во всех случаях, но итеративно приближаемся к «helicopter view» (взгляд на ситуацию сверху, позволяющий охватить общую картину и увидеть взаимосвязи). И это — основная задача, которую мы решаем.
В результате у нас появилась потребность в двух компонентах:
хранилище метрик, где будут аккумулироваться и агрегироваться нужные значения;
интерфейс визуализации, где мы будем видеть графики, таблицы и оповещения.
Проанализировав, что уже используется в нашей компании, а также что является де-факто стандартом на рынке, мы пришли к очевидному выбору: Prometheus как хранилище и Grafana как средство отображения и анализа.
Избежать хаоса во внедрении метрик
Мы начали с проработки архитектуры нашего решения. Было несколько вариантов — расскажу про плюсы и минусы, которые мы нашли для себя. Это реальный случай в компании с коммунальными инсталляциями и рядом ограничений от коллег из информационной безопасности.
Первый вариант, который является, скорее, базовым:

Есть существенные недостатки:
мы выставляем «наружу» каждый сервис, с которого хотим собирать метрики;
накладные расходы на коммуникации по уведомлению об изменениях;
отслеживание и применение изменений на Prometheus (на новый сервис появится новый Target);
накладные расходы на обеспечение безопасности.
Эта схема нам не подошла, но она подойдёт для pet-проекта, где основная задача — апробация.
Второй вариант, который больше подходит для организаций с гибкими стандартами или небольшим количеством проектов, где можно оперативно внедрить современные практики:

В архитектуре с OpenTelemetry Collector gateway приложения не ожидают, что внешний Prometheus скрапит их напрямую. Вместо этого они отправляют метрики на единый endpoint Collector. Там данные проходят через pipeline обработки: фильтрацию, агрегацию, возможно, sampling/recording. Затем Collector экспортирует подготовленные данные в Prometheus.
Преимущества этого решения:
Больше контроля над потоками телеметрии: Collector может обогащать метки, агрегировать, фильтровать.
Приложения отправляют данные в Collector, а не ждут скрапа снаружи.
Collector может отправлять напрямую телеметрию в выбранный вами backend или remote-write.
Подробнее можно почитать в этих статьях, чтобы реализовать такую схему в вашей организации:
Третий вариант, на котором мы остановились и который, по моему опыту, встречается чаще в крупных организациях:

Развёрнут собственный namespace‑collector Prometheus, скрапящий с сервисов метрики /actuator/prometheus. В свою очередь общий (коммунальный) Prometheus получает метрики с локального collector’а, не дёргая каждый сервис напрямую.
Вариант, который тоже является рабочим, но со своими недостатками:
При скрапинге множества сервисов напрямую легко получить избыточное количество временных рядов.
Pull-модель Prometheus не даёт промежуточной обработки: нельзя фильтровать, агрегировать или обогащать метрики до импорта — всё происходит как есть.
Прямой скрап большого количества pod’ов или namespace’ов усложняет поддержку: при росте системы конфигурация усложняется.
В этой статье я не буду рассматривать конфигурацию Prometheus, но при желании вы можете обратиться к первоисточнику.
Искушённый читатель, взглянув на схему, скажет: «Послушай, ты нарисовал всего один контейнер сервиса, а как же реальность? Есть системы missioncritical, где выставляются требования по горизонтальному масштабированию service-контейнеров. И вообще, мы можем жить сразу в нескольких ЦОДах одновременно, да ещё и с георезервированием».

Когда сервисы масштабируются, например, HPA=3, то namespace‑collector Prometheus одновременно скрапит три реплики каждого сервиса с endpoint /actuator/prometheus. Он агрегирует данные через recording rules, а центральный (коммунальный) Prometheus обращается только к этому collector через /federate, получая лишь заранее подготовленные метрики. Так снижаются нагрузка, cardinality и упрощается безопасность инфраструктуры.
Это ускоряет дальнейшие запросы и снижает нагрузку, так как Grafana и центральный Prometheus (через /federate) работают уже с агрегированными рядам. Официальная документация Prometheus описывает настройку recording rules, синтаксис record: и expr:.
Что с безопасностью
Тема широкая, поэтому поговорим только о выбранном нами варианте реализации.
Prometheus-collector внутри namespace находится в mesh и просто делает обычный HTTP-запрос к /metrics — он не знает про TLS. Однако Istio sidecar перехватывает этот запрос, упаковывает в TLS и отправляет в mTLS-канале к sidecar приложения. Этот sidecar расшифровывает запрос HTTP и передаёт его service-контейнеру. Ответ идёт назад по тому же пути, тоже через TLS. В итоге Prometheus работает на plaintext, но Istio обеспечивает шифрование всего трафика внутри mesh.
Когда же центральный Prometheus (вне namespace) скрейпит namespace-collector, он уже подключается через HTTPS и mTLS — тут мы используем настройки tls_config.
Получается такая цепочка безопасности:
Внутри namespace: Prometheus делает HTTP → Istio упаковывает в TLS → target получает метрики, ответ возвращается в TLS → Prometheus получает plaintext.
Между Prometheus: коммунальный Prometheus делает HTTPS/mTLS на namespace-collector.
Таким образом, скрейп защищён там, где нужно (mesh), а Prometheus остаётся простым HTTP-клиентом. И только федерация требует явной TLS-конфигурации.
Понять, кто и за что отвечает в процессе
Внедрение мониторинга — не только техническая задача, но и организационный процесс. Мы разбили workflow на три зоны:
разработка: формирует, реализует и проверяет метрики;
владелец продукта: валидирует и приоритизирует;
сопровождение: поддерживает и расширяет.
Такое распределение позволяет быстро реагировать на потребности бизнеса, уменьшает риск непонятых заявок и создаёт устойчивый жизненный цикл метрик.

Команда разработки:
формирование первичного списка метрик;
реализация и тестирование метрик;
документирование всех метрик: названия, тип метрик, описание, принадлежность к сервису;
создание дашбордов Grafana;
сохранение стабильной версии дашбордов в дистрибутиве продукта.
Владелец продукта:
валидация метрик: оценка «ценности» и релевантности для бизнес-задач;
принятие решений и заявки на добавление дополнительных метрик.
Сопровождение:
запросы на новые метрики для аналитики и анализа проблем при эксплуатации;
настройка или обновление дашбордов Grafana, подключенных к центральному Prometheus.
Как и многие, мы начинали со статьи от Google про 4 золотых сигнала, которую можно найти в переводе и детальном разборе.
Следующим шагом определяли слои системной архитектуры сервисов для определения узких мест и потребности в отслеживании информации на графиках в Grafana. Этот процесс для команд с разным уровнем зрелости может проходить по-разному.
Мы выделили несколько уровней:

Наша команда выделила внутри каждого сервиса три ключевых уровня: основной интерфейс, основные функции (Core) и выходные интеграции. На каждом уровне мы определяем нужные метрики, например, latency и error rate на endpoint, загрузку очередей и зависимостей на внутреннем уровне, saturation внешних вызовов и очередей.
Такой подход помогает сформировать полный, но не избыточный набор метрик, и создать информативные Grafana-дашборды, отражающие здоровье каждой части системы.
Все метрики по сервисам описали в документации, взяв за референс документацию OpenShift. В дальнейшем в Grafana настроили Data sources и приступили к созданию дашбордов Grafana c использованием PromQl.
Пройдя полностью ранее описанные шаги, мы пришли к процессу итеративного обновления stable-версии наших дашбордов и их доставки до промышленного контура.
Разбираемся в агрегации метрик
Начнём с анализа четырёх типов метрик Prometheus:
Тип |
Что отражает |
Подходит для… |
Ограничения и особенности |
Counter |
Суммарные значения (события, ошибки) |
|
Только растёт, требует |
Gauge |
Текущее состояние (загрузка, размер) |
CPU/memory/queue depth, snapshot-текущее |
Нет |
Histogram |
Распределение значений (latency) |
Вычисление квантилей, latency P95/P99 |
Нуждается в bucket-настройках, увеличивает cardinality* |
Summary |
Клиентские квантильные наблюдения |
P99 latency без server-side агрегации |
Не агрегируется между экземплярами, дорог в ресурсах |
При первом подходе к этим типам метрик у тех, кто впервые сталкивается с временными рядами, могут возникнуть вопросы: «Почему я складываю одни данные, а в результате использования функций PromQL появляются искажения?». На этот вопрос помогут ответить видеообъяснения и серия статей:
Как сэкономить время на настройке дашбордов
Если вы только знакомитесь с Grafana и Prometheus, то лучше начать с официального маркетплейса дашбордов Grafana Labs:
На сайте Grafana Dashboards можно найти множество преднастроенных дашбордов для Prometheus, Kubernetes, Node Exporter, Docker и прочих популярных инструментов.
Эти шаблоны можно импортировать прямо в вашу Grafana через JSON-файл — это быстрый способ получить базовые панели без ручного создания.
С чем мы столкнулись на этом этапе:
Множество панелей не очевидны каждому, кто будет их смотреть, поэтому пришлось в Description добавлять детальное и однозначное описание. Это позволяет сэкономить на этапе адаптации и снизить количество коммуникаций.
Некоторые панели собирают большой поток информации в кучу, что затрудняет анализ. Приходится разбивать их на группы и даже выносить в отдельные дашборды с разделением по функциональному назначению.
Некоторые панели не отображаются, и тут есть несколько развилок: изменилось название метрики, состав передаваемых меток, или каких-то статичных меток не хватило (тут речь про метки, которые принято добавлять при настройке Target в Prometheus).
Про дашборды и реальность разработки
Наверняка у вас есть различные стенды, где размещается ваш продукт: DEV, ST, IFT, LT, HF, PROD. Хочется в зависимости от задачи быстро переключаться между стендами в режиме одного экрана или дашборда. Для этого у нас есть два инструмента: добавление меток на уровне Target в Prometheus, а также настройка и использование переменных дашборда Grafana:
Если вы уже прошли эти этапы и приступили к созданию панелей на основе кастомных метрик, разработанных и доставленных до Grafana, то поделюсь полезными инструментами, которые мы использовали при создании дашбордов:
GPT-инструменты — хороший вариант для составления «рыбы» PromQL-запроса, получения рекомендаций по настройкам и описания для документации.
Статья, рассказывающая по шагам, как дойти от настройки окружения до готового дашборда, с множеством примеров, картинок и объяснений.
Статья приводит множество примеров и объяснений сложных конструкций запросов.
Ну и, конечно, обращение к первоисточнику.
Вместо заключения
Напомню, что эта статья обзорная, и её цель — собрать воедино все полезные источники и использовать для адаптации. Если перед вами стоит задача построить HA/HL-инфраструктурное решение по observability, то рекомендую ознакомиться с продуктами VictoriaMetrics и Grafana Mimir.