
Привет, Хабр! Меня зовут Николай, я – старший инженер по внедрению в Т2. На определенном этапе эксплуатации системы, когда настроены все мониторинги, и подключены все алерты, появляется необходимость оформить работоспособность всего, что есть, в одной метрике. Такую метрику, знаете, и отделу бизнес-мониторинга можно продемонстрировать, и коллегам из смежных команд – и при этом сделать все максимально прозрачным и понятным. Чтобы, как я иногда говорю, моя бабушка посмотрела и все поняла. В этой статье я расскажу, что у меня получилось из идеи создать доходчивую и простую для восприятия метрику индекса здоровья системы!
Итак, мы остановились на том, что у нас есть большая красивая система/монолит/микросервисы (архитектура не важна) и всего один инженер. Мониторинг множества метрик в большой системе требует тщательного подхода. Один инженер должен следить за разнообразными показателями, такими как использование CPU и памяти, время ответа, объем базы данных, поведение топиков в Kafka, состояние подов в Kubernetes, статистика Java-приложений и доступность эндпоинтов.
Хочется сложить все показатели, поделить сумму на их количество и получить что-то среднее, что показывало бы, как система работает. Но это невозможно, т.к. что-то измеряется в штуках, что-то – в мегабайтах, а что-то – в миллисекундах. Наверное, можно было бы сгруппировать метрики по единицам измерения, но они все показывают разные критерии, не всегда влияющие друг на друга. Время ответа сервиса, никак не коррелирует со временем жизни контейнера, а количество свободных мегабайт памяти не соотносится с объемом «дата региона» в Apache Ignite.
Проблема заключается в том, что такие метрики, как время ответа, использование памяти и время жизни контейнера, показывают разные критерии и не всегда коррелируют друг с другом.
Например:
free_memory <15% – некритична для того, чтобы ночью просыпаться и идти чистить память. Это можно спокойно сделать и в рабочее время.
А вот метрика
up_endpoint_api = 0 говорит о том, что система перестала отвечать, и тут уже некогда объяснять – нужно срочно идти разбираться, что случилось.
Для эффективного мониторинга и управления системой я решил группировать метрики не только по их значимости, но и по степени их влияния на производительность. Это позволяет более точно оценивать состояние системы и оперативно реагировать на возникающие проблемы.
Примеры группировки метрик
Критичные метрики:
up_endpoint_api = 0free_memory < 2%disk_space_usage > 98%
Описание: требуют немедленного внимания, так как указывают на серьезные проблемы, влияющие на работоспособность системы.
Средние метрики:
cpu_usage > 80%response_time > 500mskafka_topic_lag > 100 messages
Описание: указывают на потенциальные проблемы, которые могут потребовать внимания в ближайшее время, но не являются критичными для немедленного вмешательства.
Незначительные метрики:
free_memory < 15%pod_restart_count > 3
Описание: их можно решать в рабочее время – они не оказывают немедленного влияния на производительность системы.
Группировка метрик по степени их влияния позволяет эффективнее управлять системой и быстрее реагировать на возникающие проблемы. Такой подход помогает инженеру сосредоточиться на наиболее важных показателях, обеспечивая стабильность и надежность системы.
Кроме того, важно учитывать, что метрики имеют разные единицы измерения, и их прямое сравнение невозможно. Поэтому группировка по степени влияния позволяет нивелировать различия в единицах измерения и создать более гибкую и адаптивную систему мониторинга, которая учитывает как критичные, так и менее важные аспекты работы системы.
Таким образом, группировка метрик по степени их влияния и значимости позволяет более эффективно управлять системой, несмотря на разнородность самих показателей.
Вот тут появляется два подхода
Мониторинг и оценка состояния системы через метрики – ключевой аспект обеспечения ее надежности и производительности. В этой части статьи мы рассмотрим два основных подхода к подсчету метрик. Один из них – количественный метод, где каждая метрика наносит «урон» системе, вычитаясь из исходного значения ее здоровья. Я намеренно геймифицировал подход – так он становится более легким для восприятия.
Первый подход: количественный метод
Основная идея:
В этом подходе система представляется как объект с определенным количеством очков здоровья. Каждая метрика наносит урон, который вычитается из общего количества очков. Чем больше урона – тем критичнее ситуация.
Пример:
Предположим, у нашей системы есть 100 очков здоровья. Различные метрики и их пороговые значения выглядят следующим образом:
free_ram < 20% = 10 очков урона
free_ram < 10% = 50 очков урона
free_disk < 10% = 50 очков урона
response_time > 1s = 50 очков урона
response_time > 3s = 90 очков урона
up_endpoint_api == 0 = 100 очков урона
Если система использует 80% доступной памяти, она теряет 10 очков здоровья (остается 90). Если же память падает до 90%, добавляется еще 50 очков урона, и система остается с 40 очками здоровья.
Но есть и недостатки у этого подхода: если одновременно возникают проблемы с памятью и временем ответа, система может получить отрицательный баланс очков здоровья, что не всегда удобно для восприятия и интерпретации.
Пример расчета:
Если у системы остается 40 очков здоровья после проблем с памятью, и добавляется еще одна – время ответа > 3 секунд (90 очков урона), система получит -50 очков. Такое значение не имеет практического смысла.
Как итог, количественный метод позволяет наглядно оценить состояние системы через очки здоровья, но его главный недостаток – возможность получения отрицательных значений при множественных проблемах. Это делает его менее удобным для практического использования в реальных условиях, где важна четкость и простота интерпретации данных.
Ниже мы рассмотрим альтернативный подход, который может предложить более гибкую и практичную модель для мониторинга и оценки состояния системы.
Второй подход: как в школе
Теперь перейдем к альтернативному варианту, который даже на первый взгляд выглядит гораздо дружелюбнее – и при этом избавляет нас от путаницы с отрицательными значениями. Такой подход не даст индексу «уйти в минус», поэтому итоговую оценку легко интерпретировать самому и без труда интегрировать в системы, где отрицательные значения вызывают ошибки.
Ключевая идея проста: если одновременно срабатывает несколько метрик, мы учитываем только ту, которая оказывает наибольшее влияние, – то есть вычитаем из здоровья системы максимальный «штраф» по приоритету. Подробности этой логики разберем чуть дальше.
Пятибалльная система оценок:
Этот метод основан на знакомой нам со школы пятибалльной системе – понятно, просто и, как я люблю говорить, доступно даже моей бабушке.
5 – отлично
4 – хорошо
3 – удовлетворительно
2 – неудовлетворительно
1 – плохо
В нашей шкале я сознательно исключил оценку «ноль» – ведь она больше запутывает, чем помогает. Ноль – это пустота, отсутствие информации, и такая оценка может создать ложное впечатление, будто никаких проблем нет, хотя на самом деле все плохо. Даже если система работает очень нестабильно, какое-то – пусть минимальное – здоровье у нее все же есть, и это важно зафиксировать.
Преимущества такого подхода вполне очевидны:
Пятибалльная система понятна абсолютно каждому – не нужно разбираться в нюансах, чтобы увидеть, хорошо у нас или плохо.
Отсутствие отрицательных значений убирает все сложности при передаче и интерпретации индекса в других системах (там, где отрицательные оценки попросту не предусмотрены и могут вызвать ошибки).
Логика вычисления:
В отличие от количественного метода, где каждая метрика вычитает фиксированное значение, здесь применяется логика приоритетов. Если несколько метрик сработали одновременно, вычитается только та, у которой выше приоритет.
Предположим, у нас есть следующие метрики и их пороговые значения:
free_ram < 20% = 4 (хорошо)
free_ram < 10% = 2 (плохо)
free_disk < 10% = 3 (удовлетворительно)
response_time > 1s = 3 (удовлетворительно)
response_time > 3s = 2 (плохо)
up_endpoint_api == 0 = 1 (плохо)
Если система использует 15% свободной памяти, и время ответа превышает 3 секунды, сработают две метрики:
free_disk < 10% = 3 (удовлетворительно)
response_time > 3s = 2 (плохо)
Поскольку response_time > 3s имеет высокий приоритет, то именно он и попадет в итоговое вычисление индекса здоровья системы.
Ниже мы подробно рассмотрим процесс вычисления очков здоровья по этому методу и его преимущества на практике.
Как считать метрики здоровья системы
Для мониторинга состояния системы с использованием Prometheus и Grafana необходимо настроить несколько компонентов: Prometheus, Grafana, Alertmanager, а также установить экспортеры на хостах для сбора метрик с различных эндпоинтов.
Для мониторинга эндпоинтов я использую blackbox-exporter, который умеет:
По-разному опрашивать API, используя кастомный body в POST-запросе.
Выводить соответствующие метрики в удобочитаемом для Prometheus виде.
Для мониторинга бизнес-логики в базе данных я использую кастомное приложение на Python, хотя можно использовать и Oracledb_exporter.
Kafka Exporter: для мониторинга Kafka кластеров.
Redis Exporter: для сбора метрик с Redis.
JMX Exporter: для Ignite.
Node Exporter: для сбора базовых метрик с хостов.
Grafana: используется для визуализации метрик и создания дашбордов.
Alertmanager: управляет оповещениями о состоянии системы.
Присвоение очков триггерам
Каждому триггеру присваивается определенное количество очков, которое он отнимает от общего здоровья системы при срабатывании. Например, триггер, срабатывающий при HTTP-коде, отличном от 200:
vector(4) and on() ( probe_http_code != 200)
При срабатывании этого триггера система теряет 4 очка здоровья.
Также все триггеры группируются по степени их влияния на работоспособность системы. Логика заключается в том, что при срабатывании нескольких триггеров в одной группе их общий вектор будет равен максимальному значению очков в этой группе.
Например:
vector(4) and on() ( probe_http_code != 200 or redis_cluster_node < 3)
Эта конструкция с использованием or гарантирует, что вектор будет равен 4, даже если сработают оба триггера.
Чтобы избежать отрицательных значений и упростить интерпретацию, используется следующая логика:
5 - (max(
(
((vector(4) and on() (
probe_http_status_code{job="sys_api"} != 200
or
probe_http_status_code{api_service="IGNITE"} != 200
)
or on() vector(0))) == 4)
or
(
((vector(3) and on() (
ignite_total_baseline_nodes{job=~"ignite-prod."} < 1 or probe_http_status_code{job="api_user"} != 200 ) or on() vector(0))) == 3) or ( ((vector(2) and on() ( redis_cluster_known_nodes{job=~'prod.'} < 2
)
or on() vector(0))) == 2)
or
(
((vector(1) and on() (
ignite_total_baseline_nodes{job=~"ignite-prod."} < 2 or kafka_brokers{job=~"kafka-exporter-prod."} < 3
)
or on() vector(0))) == 1)
or
(
((vector(0) and on() (
probe_http_status_code{job="api_sys"} == 200
or
probe_http_status_code{job="api_user "} == 200
or
redis_cluster_known_nodes{job=~'prod.*'} < 2
)
or on() vector(0))) == 0)
))
Из полученного результата выбирается максимальное значение, которое вычитается из общего здоровья системы. Это предотвращает возможность отрицательных значений и упрощает восприятие состояния системы.
В процессе мониторинга наших сервисов мы столкнулись с интересной особенностью работы blackbox-экспортера: иногда он зависает в ожидании ответа от целевого сервиса, что напрямую связано с нагрузкой на сам экспортер. При стандартной конфигурации scrape_interval в 2 минуты даже единичный потерянный запрос (примерно 1 из 1000) может привести к серьезным последствиям. Представьте ситуацию: срабатывает алертный триггер, и в течение двух минут мы получаем false positive. В итоге портятся метрики в Prometheus Dashboard, и возникает ненужное беспокойство у SRE-инженеров и тимлидов, нарушая их драгоценный сон.
Для решения этой проблемы я внедрил более надежную стратегию: теперь промоутер-алерт срабатывает только после трех последовательных инцидентов, то есть все три запроса должны «упасть» в течение шести минут. К счастью, такая последовательность неудачных запросов пока ни разу не наблюдалась в продакшне, что говорит о корректности выбранной стратегии и снижении количества false positives в нашей системе мониторинга.
В дальнейшем уведомление о сработанном триггере отправляется в API Telegram боту, который пишет в чат инженерам. В сообщении обязательно описываю возможные причины уменьшения здоровья:

Ну и, конечно, этот трафик удобно наблюдать в Grafana:

А также рекомендую создать отдельный дашборд, посвященный индексу, и на одном из графиков отобразить все метрики в виде векторов. Это сильно упростит и ускорит поиск неисправности:

Prometheus rules – за индексом следят посторонние
В современном мире DevOps-инфраструктуры постоянный мониторинг метрик – основа стабильности и предсказуемости работы любых сервисов. За эту задачу отвечает Network Operations Center (NOK): команда, которая 24/7 следит за тысячами показателей и индексов здоровья по всем системам. Каждый новый показатель, попадающий в их зону контроля, проходит непростой путь согласований и документирования – необходимый, но довольно ресурсоемкий процесс.
Особенно сложно становится, когда нужно скорректировать уже действующую метрику: чтобы внести малейшее изменение, приходится проходить всю процедуру одобрения заново. Чтобы обойти этот бюрократический узел, я внедрил решение на основе Prometheus rules – системы, позволяющей гибко агрегировать метрики на своей стороне.
Главный плюс этого подхода в том, что вместо огромного потока «сырых» метрик в NOK теперь уходит только вычисленный интегральный индекс здоровья. Вся математика остается на моей стороне – служба мониторинга получает уже готовое значение и не делает лишних пересчетов. Мне, как разработчику, это дает свободу – я могу тонко подстраивать формулы и логику расчета в Prometheus без постоянных повторных согласований на стороне NOK.
Этот подход сразу решает несколько задач:
Снижает нагрузку на NOK – ведь теперь приходится следить не за десятками или сотнями «сырых» метрик, а только за финальным, агрегированным индикатором здоровья.
Существенно упрощает процесс изменений: если нужно что-то скорректировать в логике расчета, это можно сделать самостоятельно и быстро, без нового круга согласований.
Позволяет гибко выставлять и менять пороговые значения по своему усмотрению.
При этом полный контроль над формулой и ее деталями всегда остается у разработчика.
В итоге, мониторинговая служба получает только действительно значимую информацию о состоянии системы, а команда разработки может своевременно адаптироваться к новым задачам и требованиям бизнеса – без излишней бюрократии и лишней нагрузки на оба процесса.
Заключение
Внедрение индекса здоровья системы – это не просто новый способ мониторинга, а инвестиция в прозрачность и уверенность всех участников процесса. Его задача – сделать контроль над состоянием сервисов доступным каждому, повысить скорость реакции на инциденты и превратить обсуждение стабильности из рутинной отчетности в понятный для всех диалог.
Ключевой фактор успешного внедрения – сочетание инженерного подхода с удобной визуализацией, регулярным анализом и гибкостью настроек. Только так индекс здоровья становится не абстракцией, а реальным инструментом поддержки для бизнеса и технических специалистов.
Чтобы этот подход органично прижился в команде и культуре компании, мы реализуем его пошагово: через эксперименты, взаимодействие с коллегами и сбор обратной связи.
P.S. Поделитесь своим опытом внедрения метрик здоровья – давайте вместе повысим прозрачность и надежность наших систем!
Litemanager_remoteadmin
Интересный подход спасибо, а вообще задача кторую вы решили очень не простая , однозначно плюс вам!