Привет, Хабр! Меня зовут Глеб Типсин, я являюсь ведущим разработчиком продукта «Системы персонализации и геймификации» в SM Lab.

Глеб Типсин — ведущий разработчик «Системы персонализации и геймификации» в SM Lab

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

В этой статье мы разберём, как устроены метрики в Prometheus, как происходит их сбор, а также что с ними можно делать. Кроме того, обсудим подходы к мониторингу, архитектуру Prometheus и её ограничения.

Материал подойдёт тем, кто только знакомится с мониторингом и хочет освоить «базу», а также тем, кто уже работает с Prometheus, но хочет "освежить" свои знания и узнать что-то новое.


Мониторинг и подходы

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

Мониторинг дает:

  • Повышение уровня прозрачности: понимание того, как система ведет себя в условиях эксплуатации (production среда);

  • Оповещение о проблемах: если что-то вышло из строя, то требуется немедленное вмешательство. Также могут поступать оповещения о будущих сбоях, которые стоят предупредить заранее;

  • Долгосрочный и ретроспективный анализ: насколько быстро растет нагрузка на систему? Насколько быстро растет хранимый объем данных? Ответы на эти вопросы позволяют заблаговременно принять необходимые меры;

  • Сравнение с предыдущими версиями системы: оценка изменений в состоянии системы после проноса очередной доработки — улучшилось ли её «самочувствие» или ухудшилось.

Можно выделить два подхода в мониторинге:

Подходы в мониторинге
Подходы в мониторинге
  • Метод белого ящика — мониторинг на основе внутренних метрик и показателей системы;

  • Метод черного ящика — наблюдение за внешним поведением системы с точки зрения пользователя.

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

Метод черного ящика заключается в наблюдении за симптомами, позволяя выявлять уже возникшие, а не прогнозируемые проблемы: «Система работает некорректно прямо сейчас». Его ключевое преимущество — система обращается к человеку только при наличии реальной, ощутимой проблемы. Однако этот подход малоэффективен для прогнозирования и предотвращения неизбежных проблем, которые еще не проявились.

Подходы в сборе показателей

  • RED;

  • USE;

  • 4 Golden Signals.

RED — это метод, который в своей основе представляет собой подход черного ящика, ориентированный на показатели, доступные для внешнего наблюдения:

  • Rate — количество запросов в секунду;

  • Errors — количество запросов, которые вернули ошибку;

  • Duration — время, затраченное на обработку запроса.

USE — метод ориентирован на мониторинг ресурсов. Помогает понять, как эффективно используются системные ресурсы и выявить узкие места. Концептуально представляет собой метод белого ящика, который фокусируется на внутренних показателях системы:

  • Utilization — процент времени, в течение которого ресурс был использован;

  • Saturation — количество работы, которую ресурс должен выполнить, но которая в данный момент находится в очереди на обработку;

  • Errors — количество ошибок.

Четыре золотых сигнала (4 Golden Signals) включают время отклика, величину трафика, уровень ошибок и степень загруженности системы:

4 золотых сигнала
4 золотых сигнала
  • Время отклика (Latency) — время, которое требуется для выполнения запроса;

  • Величина трафика (Traffic) — уровень нагрузки на систему, измеряемый в единицах, специфичных для данной системы, таких как RPS (запросы в секунду), RPM (запросы в минуту), TPS (транзакции в секунду) и т.п;

  • Уровень ошибок (Errors) — частота или количество ошибок, такие как некорректные коды ответа, исключения в приложении и другие подобные проблемы;

  • Степень загруженности (Saturation) — показатель того, насколько полно загружена система.

Подход с четырьмя золотыми сигналами представляет собой сочетание метода белого и черного ящика.

Архитектура Prometheus

Одной из самых популярных связок для мониторинга является интеграция Prometheus и Grafana.

Prometheus отвечает за сбор и хранение метрик в виде временных рядов, а Grafana используется для визуализации этих данных. Вместе они образуют мощный инструмент для мониторинга и анализа производительности распределённых систем.

Самая популярная связка в мониторинге
Самая популярная связка в мониторинге

Сервер Prometheus включает несколько ключевых компонентов, которые работают совместно для сбора, хранения и отображения метрик:

Архитектура мониторинга Prometheus + Grafana
Архитектура мониторинга Prometheus + Grafana
  • Первый компонент это TSDB (база данных временных рядов), которая используется для хранения метрик в виде временных рядов. Каждый временной ряд представлен как набор пар (timestamp, value), где timestamp — это временная метка, а value — значение метрики на данный момент времени. TSDB обеспечивает эффективное хранение метрик и быстрый доступ к ним для дальнейшей обработки и анализа;

  • Второй компонент — это retrieval worker, который отвечает за сбор метрик. Prometheus использует механизм pull для получения данных, при котором через определённые интервалы времени Prometheus отправляет запросы к конечным точкам (target) метрик для получения актуальных значений. Retrieval worker выполняет эти запросы и получает метрики от целевых target.

  • Третий компонент — это HTTP server, который предоставляет API для выполнения запросов к метрикам, сохранённым в TSDB. Через HTTP сервер можно запрашивать метрики за определённый период, а также применять функции агрегации, фильтрации и преобразования данных.

  • Четвёртый компонент конфигурационные файлы, которые содержат настройки, такие как интервалы сбора метрик, статические и динамические источники данных, параметры алертов и другие аспекты работы системы.

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

Для визуализации данных используется Grafana, которая интегрируется с Prometheus и предоставляет возможность настраивать удобные дашборды для анализа состояния системы и её производительности.

Pushgateway применяется для сбора метрик от кратковременных или фоново работающих приложений, которые не поддерживают pull модель. В таких случаях приложения отправляют свои метрики в Pushgateway, а Prometheus забирает их оттуда.

Для работы с динамической инфраструктурой используется механизм service discovery. Этот процесс автоматически определяет список доступных источников данных, позволяя Prometheus адаптироваться к изменениям в инфраструктуре.

Источники данных для Prometheus:

  • Экспортеры — это специальные приложения, которые собирают метрики из различных систем и предоставляют их в формате Prometheus. Экспортеры используются, например, для мониторинга баз данных, операционных систем и сетевого оборудования;

  • Приложения — приложения, которые могут отдавать метрики в формате Prometheus. С помощью клиентских библиотек разработчики могут внедрить в свои приложения сбор и предоставление метрик.

Таким образом, Prometheus представляет собой мощный инструмент для сбора, анализа и визуализации метрик, обеспечивая мониторинг как статичных, так и динамических систем.

Ограничения Prometheus

Prometheus имеет ряд ограничений, которые важно учитывать при его внедрении:

  • Ограниченное долговременное хранение метрик: Prometheus изначально разработан для мониторинга в реальном времени, поэтому встроенные возможности хранения метрик рассчитаны на ограниченный временной период;

  • Отсутствие поддержки Global Query View: если у вас несколько независимых инстансов Prometheus, каждый из которых собирает свои метрики, выполнение объединённых запросов по данным со всех инстансов невозможно;

  • Ограниченная производительность: производительность Prometheus ограничивается возможностями одного сервера, так как он не поддерживает автоматическое горизонтальное масштабирование на несколько серверов. Для работы с высокими нагрузками требуется ручное шардирование данных или использование дополнительных решений для распределённого мониторинга.

Эти ограничения делают Prometheus менее подходящим для очень крупных систем или сценариев с высокими требованиями к долговременному хранению данных и глобальному доступу к метрикам. Однако они обходятся с помощью дополнительных инструментов и настроек.

Для решения ограничений, присущих Prometheus, существует несколько подходов, которые помогают масштабировать систему и улучшить её возможности. Наиболее популярными решениями являются:

  • VictoriaMetrics;

  • Cortex;

  • Thanos;

  • Mimir;

  • M3.

Архитектура мониторинга у нас

Усовершенствованная архитектура мониторинга
Усовершенствованная архитектура мониторинга

В каждом кластере Kubernetes развёрнут собственный экземпляр Prometheus. Приложения, размещённые внутри pod'ов, предоставляют данные о метриках на заданном порту и эндпоинте в формате Prometheus.

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

Каждый экземпляр Prometheus передаёт собранные метрики в централизованную систему VictoriaMetrics с использованием протокола remoteWrite. Это позволяет агрегировать данные мониторинга из различных кластеров в единую высокопроизводительную и масштабируемую инфраструктуру.

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

Модель данных

Данные организованы в виде временных рядов, каждый из которых состоит из уникального идентификатора и набора sample'ов. Временной ряд однозначно идентифицируется комбинацией имени метрики и набора лейблов (если они присутствуют). Каждый sample представляет собой пару: временную метку (timestamp), выраженную в миллисекундах, и значение метрики в формате float64, которое отражает состояние метрики в соответствующий момент времени.

Пример с двумя временными рядами в один и тот же момент времени:

Пример временного ряда
Пример временного ряда
  • Название метрики: skip_records_total — отражает количество пропущенных сообщений из топика брокера;

  • Набор лейблов: app — обозначает имя приложения, а topic — указывает название топика;

  • Значение: представлено числом в формате float64, отображающим текущее состояние метрики.

Данная метрика является кастомной и увеличивается непосредственно внутри приложения. На представленном изображении показан процесс извлечения значений метрик через пользовательский интерфейс Prometheus с использованием простейшего выражения на языке запросов PromQL. В результате были извлечены два временных ряда, отличающиеся значениями лейблов (название топика). Этот подход наглядно иллюстрирует, как использование лейблов позволяет значительно повысить гибкость и информативность, предоставляя возможность хранить дополнительные контекстные данные при использовании единого имени метрики.

Далее рассмотрим подробно, какие типы данных могут возвращать запросы PromQL, сосредоточив внимание на самых распространённых из них — instant vector и range vector.

Instant vector

Данный тип данных представляет собой «снимок» временных рядов в определённый момент времени. Для каждого временного ряда возвращается одно единственное значение, соответствующее последней доступной выборке на момент выполнения запроса. Такой подход позволяет получить актуальное состояние метрик именно на заданный временной срез. Данный тип был представлен в примере раннее (см. модель данных метрики).

Если в заданный момент времени данных в TSDB не обнаружено, Prometheus попытается найти ближайшее предыдущее значение. Это поведение регулируется параметром query.lookback-delta, который по умолчанию установлен на 5 минут. Для наглядности данный механизм продемонстрирован на следующей анимации:

Получение instant вектора
Получение instant вектора

Range вектор

Этот тип данных представляет собой набор временных рядов, где каждому ряду соответствует массив значений, собранных за указанный временной интервал. Проще говоря, range vector — это совокупность текущего значения метрики и всех предыдущих выборок, попадающих в заданный диапазон времени. Такой формат данных позволяет анализировать изменения метрик во времени.

Рассмотрим синтетический пример для лучшего понимания. Для метрики my_custom_metric получим range вектора за 30 секунд для 3 срезов времени. Для момента T2:

Range вектор для момента времени T2
Range вектор для момента времени T2

Для момента времени T1:

Range вектор для момента времени T1
Range вектор для момента времени T1

Для момента времени T0:

Range вектор для момента времени T0
Range вектор для момента времени T0

Для получения range vector в PromQL необходимо добавить квадратные скобки с указанием интервала времени в конце запроса. Этот интервал определяет, за какой период будут собраны данные для каждого временного ряда.

Например, для метрики my_custom_metric с интервалом 30 секунд запрос будет выглядеть так: my_custom_metric{}[30s].

Типы метрик

В Prometheus всего 4 типа метрик:

Типы метрик в Prometheus
Типы метрик в Prometheus

Пример counter:

Количество логов с определенным уровнем логирования
Количество логов с определенным уровнем логирования

Пример gauge:

Использование памяти jvm
Использование памяти jvm

Пример histogram:

Распределение количества запросов по временным bucket
Распределение количества запросов по временным bucket

⚠️ Важно отметить, что размеры bucket необходимо настраивать вручную, если такая возможность имеется. Если это не будет сделано, существует риск, что фреймворк или библиотека, которую вы используете, автоматически создаст большое количество bucket, что может привести к неоправданному увеличению объёма данных. В результате вы получите больше bucket, чем реально нужно для ваших задач.

Пример summary:

Время выполнения запросов
Время выполнения запросов

Фильтрация временных рядов

Метрики в PromQL можно фильтровать по значениям лейблов, что позволяет получать данные, соответствующие определённым критериям:

Выражения для фильтрациив в PromQL
Выражения для фильтрациив в PromQL

Для этого в фигурных скобках после имени метрики указываются условия фильтрации через запятую. Пример PromQL запроса с фильтрацией:

Пример фильтрации
Пример фильтрации

В данном примере получаем только временные ряды, у которых topic соответствует значению pg_notification_click.

⚠️ Фильтрацию можно применять как к instant vector, так и к range vector.

«La сlassique» операции

В PromQL к векторам можно применять арифметические, логические операторы, а также операторы сравнения. Операндами в таких выражениях могут быть как сами векторы, так и скалярные значения.

Самые базовые операции с векторами в PromQL
Самые базовые операции с векторами в PromQL

⚠️ Все эти операции применимы только к instant вектору.

Агрегация

В PromQL можно выполнять агрегирование векторов, чтобы объединять временные ряды и извлекать агрегированную информацию.

Агрегирование позволяет применять функции, такие как sum, min, max, avg, count, quantile, чтобы свести значения временных рядов к одному или нескольким агрегированным результатам:

Типы агрегаций в PromQL
Типы агрегаций в PromQL

⚠️ Все эти операции применимы только к instant вектору.

Базовые функции

Наиболее часто используемые функции:

Базовые функции в PromQL
Базовые функции в PromQL

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

⚠️ Перечисленные функции применимы исключительно к range векторам, так как они работают с массивами значений, собранных за определённый временной интервал. Кроме того, эти функции предназначены для использования с метриками типа counter.

Increase

Данная функция показывает, насколько изменилось значение метрики за заданный интервал. Для наглядности рассмотрим небольшой пример.

Для метрики my_custom_metric существует следующий набор измерений:

Набор измерений для метрики my_custom_metric
Набор измерений для метрики my_custom_metric

Теперь применим функцию increase для момента времени T3, используя range vector с временным интервалом в 2 минуты. Это позволит вычислить разницу между значениями метрики на границах заданного интервала.

Графическая интерпретация increase
Графическая интерпретация increase

Функция increase возвращает величину роста метрики в пределах указанного диапазона времени. В данном случае, для момента T3, это изменение отражает разницу между последним доступным значением метрики в интервале и её начальным значением.

Rate

Функция rate вычисляет среднюю скорость изменения метрики в секунду на основе накопительных данных за указанный временной интервал. Также для наглядности рассмотрим небольшой пример.

Набор измерений для метрики my_custom_metric
Набор измерений для метрики my_custom_metric

Теперь применим функцию rate для момента времени T3, используя range vector с интервалом в 2 минуты. Эта функция рассчитает среднюю скорость изменения метрики, используя значения на начальной и конечной границах интервала.

Графическая интерпретация rate
Графическая интерпретация rate

Функция rate возвращает скорость изменения метрики в секунду, то есть она вычисляет производную метрики по времени.

Irate

Функция irate является близким аналогом rate, но с одним важным отличием: она вычисляет производную, основываясь только на двух последних значениях, попавших в указанный временной интервал. Это делает её подходящей для анализа мгновенной скорости изменения метрики. Также приведем наглядный пример:

Набор измерений для метрики my_custom_metric
Набор измерений для метрики my_custom_metric

Теперь применим функцию irate для момента времени T3, используя range vector с интервалом в 2 минуты. В данном случае функция определит разницу между двумя последними значениями метрики, попавшими в диапазон, и поделит её на временной промежуток между этими значениями.

Графическая интерпретация irate
Графическая интерпретация irate

В отличие от rate, которая усредняет изменения по всему интервалу, irate отображает мгновенные изменения, делая её более чувствительной к резким колебаниям.

Обработка сбросов counter

Приложения, предоставляющие метрики, неизбежно обновляются, например, при редеплое, что приводит к сбросу метрик типа counter до нуля. В таких случаях некоторые функции Prometheus, такие как increase, rate, irate и другие, способны корректно обрабатывать подобные случаи.

Метрики типа counter обладают важным свойством — они монотонно возрастают. Это позволяет легко обнаружить сброс: новое значение счётчика оказывается меньше предыдущего. Prometheus автоматически учитывает такие случаи и корректирует расчёты, добавляя дельту, которая компенсирует разницу, возникшую из-за сброса:

Обработка сбросов counter
Обработка сбросов counter

Экстраполяция

Некоторые функции Prometheus, такие как increase и rate, используют экстраполяцию, поскольку значения метрик не всегда совпадают с точными границами временного окна. Это может приводить к появлению дробных значений в результате вычислений, даже если метрика по своей природе должна быть целочисленной.

В общем случае экстраполяция работает следующим образом:

Общий случай экстраполяции
Общий случай экстраполяции

Prometheus оценивает положение значений метрики относительно границ временного интервала и "достраивает" недостающие части.

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

Экстраполяция
Экстраполяция

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

Экстраполяция
Экстраполяция

А вот для медленно изменяющихся счетчиков, экстраполяция может привести к не совсем корректным результатам:

Экстраполяция для медленно изменяющихся счетчиков
Экстраполяция для медленно изменяющихся счетчиков

В этой статье мы разобрали базовые концепции работы с метриками в Prometheus, начиная от подходов в мониторинге и инфраструктуры до функций и особенностей экстраполяции. Этот материал был задуман как вводный, чтобы помочь вам уверенно начать работу с Prometheus.

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