Высокая кардинальность: проблемы, подходы и практические решения
В эпоху микро-сервисной архитектуры и детализированных телеметрических метрик высокая кардинальность становится почти неизбежной. В Prometheus каждый уникальный набор значений метрики и связанных с ней лейблов образует отдельный временной ряд. Непродуманный дизайн метрик, избыточные лейблы и гранулярность данных приводят к взрывному росту числа серий, что усиливает нагрузку на память, диск и процессор, ухудшает время отклика запросов и усложняет поддержку инфраструктуры мониторинга. Данная глава фокусируется на архитектурных принципах, схемах хранения, подходах к агрегации и практических приемах снижения кардинальности без потери ценной аналитики.
Краткое введение
В Prometheus кардинальность определяется количеством уникальных комбинаций метрик и значений лейблов. Высокая кардинальность не всегда означает плохую метрику; она может быть необходима, но следует управлять ею, чтобы система мониторинга оставалась устойчивой. Главные проблемы - рост памяти и индексов в TSDB, увеличение использования CPU на инкрементальные вычисления и сложность обработки запросов. Эффективная стратегия сочетает в себе грамотный дизайн метрик, конфигурацию сбора, использование записывающих правил (recording rules) и применение внешних хранилищ для длительного хранения и исторического анализа.
- Что именно считать высокой кардинальностью и как она проявляется в вашем стеке Prometheus.
- Как архитектура Prometheus и сопутствующих решений влияет на хранение и вычисления при большом объеме серий.
- Какие процессы и практики позволят снизить кардинальность на этапе сбора данных, упрощая аналитические запросы.
- Как выбрать стратегию хранения и интеграции: локальный Prometheus против удалённых хранилищ и горизонтального масштаба.
Краткое содержание главы
- Определение и последствия высокой кардинальности в Prometheus, примеры типовых сценариев.
- Архитектура хранения временных рядов в Prometheus и как кардинальность влияет на память, диск и вычисления.
- Практические методы снижения кардинальности на уровне дизайна метрик, relabeling и агрегаций.
- Стратегии хранения и анализа: удалённые хранители, федерация, downsampling и управление ретенцией.
- Рекомендации по внедрению: шаги, чек-листы, примеры конфигураций и сценариев миграции.
Что такое высокая кардинальность и почему она критична
Высокая кардинальность возникает, когда числовые метрики относятся к большому числу уникальных сочетаний значений лейблов. В реальных системах это может быть комбинация сервисов, инстансов, клиентов, пользователей или сессий, где каждый уникальный элемент порождает отдельную серию. В Prometheus такой уровень детализации немедленно отражается в размере индекса и объёме записываемых точек: каждый новый уникальный набор лейблов требует отдельной серии в памяти и на диске. В результате страдает не только скорость записи и чтения, но и продолжительность загрузки, а также устойчивость системы при ретенции данных.
Это особенно ощутимо, когда в метрики включаются параметры, отражающие идентификаторы пользователей, запросы по устройствам, SKU или геолокацию клиента. В таких случаях простая запись метрик без фильтрации лейблов приводит к сотням тысяч и даже миллионам серий, что неприемлемо для типичной инфраструктуры мониторинга.
С точки зрения анализа, высокая кардинальность усложняет поиск закономерностей: PromQL-выражения, которые требуют группировки по множеству лейблов, становятся ресурсоемкими. Даже простая агрегация по нескольким лейблам может приводить к экспоненциальному росту вычислительной сложности. В результате наблюдается задержка в ответах, увеличение задержки в дэшбордах и риск временных сбоев при пиковых нагрузках.
Ниже приводятся характерные признаки высокой кардинальности и способы их диагностики:
- большое число временных рядов, которые начинаются и заканчиваются в короткие промежутки времени, часто связанные с уникальными идентификаторами.
- длительная загрузка на этапе индексации и рост требований к памяти во времени.
- увеличение времени выполнения сложных PromQL-запросов, особенно тех, которые используют группировку по крупным наборам лейблов.
- частые обновления конфигураций relabel_config и запись правил, применяемых к длительно-хранящимся данным.
В качестве примера типичного сценария можно рассмотреть метрику http_requests_total{service="api", region="eu-west-1", user_id="12345"}. Со временем число уникальных user_id может стать огромным, даже если значение самой метрики остается информативным на уровне сервиса и региона. В этом случае целесообразно пересмотреть смысл и гранулярность самой лейбловой конструкции.
Архитектура и ограничения: как TSDB хранит и обрабатывает множество серий
Prometheus реализует собственный Time Series Database (TSDB) с WAL-логированием и периодическими блоками данных. Каждый уникальный набор лейблов образует серию, индекс которой хранится в памяти и на диске. При высокой кардинальности индекс становится существенно плотнее, а количество активных серий растет быстрее, чем способность системы обрабатывать их.
Ключевые моменты архитектуры и их связь с кардинальностью:
- Индекс серий: карта labelset → серия. Увеличение количества комбинаций лейблов ведет к росту размера индекса и памяти, занятой для кэширования.
- Хранение точек: данные хранятся во временных блоках (blocks) с уплотнённой компрессией. Большое число серий увеличивает копию данных и требования к дисковому пространству.
- Время жизни серий: Prometheus хранит данные в течение заданной ретенции; серии с редкими обновлениями занимают память дольше и требуют большего объема точки для индекса.
- Работа запросов: PromQL вычисления часто требуют склейки по коду лейблов, построения подмножества серий и агрегаций, что становится дорого при большом количестве серий.
Эти ограничения означают, что для систем с высоким уровнем кардинальности необходима целостная стратегия: сочетание архитектурных решений, коррекция дизайна метрик и выбор подходящих инструментов для хранения с сильной горизонтальной масштабируемостью.
Методы снижения нагрузки без потери аналитической ценности в контексте архитектуры:
- Relabeling и Drop правил: на этапе сбора отбрасывать или перерабрать высоко-детализированные лейблы, которые не критичны для бизнес-аналитики.
- Recording rules: предварительная агрегация по более низкой кардинальности (например, агрегирование по сервису и региона, исключение per-user детализаций).
- Горизонтальное масштабирование и удалённые хранилища: federation, хранение в объектном хранилище с последующим downsampling и агрегацией в слоях хранения.
Пример конфигурации relabel_configs для Dropping высоко-детализированных лейблов:
scrape_configs:
- **job_name**: 'api-telemetry'
static_configs:
- **targets**: ['api-telemetry:9100']
relabel_configs:
- **source_labels**: [__name__]
regex: 'http_requests_total'
action: keep
- **source_labels**: [user_id]
regex: '.+'
action: drop
- **source_labels**: [trace_id]
regex: '.+'
action: drop
Пример записи (recording rule) для снижения кардинальности:
groups:
- **name**: high_cardinality_downsample
rules:
- **record**: http_requests_total_by_service
expr: sum by (service) (rate(http_requests_total[5m]))
Эти примеры показывают, как можно уменьшить число серий, сохранив возможность проводить обзор по сервисам и географиям, что существенно облегчает последующий анализ.
Практические техники снижения кардинальности на уровне моделирования и сбора
Эффективная работа начинается с проектирования метрик и выбора лейблов, формирующих идентификатор серии. Основные принципы:
- Ограничение числа динамических лейблов: не следует включать идентификаторы пользователей, сессии или уникальные контексты без крайней необходимости. Если идентификатор необходим для диагностики, переносим его в отдельные метрики или используем косвенные индикаторы.
- Выделение бизнес-значимых лейблов: оставляйте в конфигурации только те лейблы, которые действительно нужны для анализа по бизнес-логике (например, сервис, регион, версия). Остальные лейблы можно аггрегировать или не собирать.
- Гранулярность агрегаций: реализуйте агрегацию на стороне источника данных, там, где это возможно и экономически оправдано. Это уменьшает поток уникальных комбинаций в Prometheus.
- Использование recording rules: создавайте низко-кардинальные, предагрегированные метрики, которые служат основой для анализа без обращения к огромному числу исходных серий.
- Применение relabel_configs: систематически удаляйте или перестраивайте лейблы на этапе сбора, чтобы предотвратить рост кардинальности "на входе".
- Управление ретенцией и хранением: сочетайте локальное хранение с удалёнными хранилищами и downsampling, чтобы сохранять долгосрочные тренды без избыточной детализации.
Практическая часть - примеры подходов и применимости:
- Перераспределение лейблов: замените лейбл user_id на более общий бизнес-метрик, например customer_segment, без потери смысла для основных аналитических задач.
- Использование «плавающих» аггрегаций: вместо детального подсчета по каждому пользователю, накапливайте показатели по временным окнам (5-15 минут) и по сервисам.
- Разделение метрик на две группы: «нормальные» метрики с низкой кардинальностью и «детализированные» только там, где это действительно нужно (инциденты, отладочная диагностика).
Примеры типовых схем записи метрик:
- Метрика без персональных идентификаторов, которая сохраняет общую статистику по сервисам и регионам: http_requests_total{service, region, status}
- Метрика для детализированной диагностики, вынесенная в отдельную систему мониторинга с ограничением доступа: http_requests_detail{user_id} - для инцидентных расследований с применением удалённого хранения.
Примеры PromQL и паттерны анализа высоко-детализированных данных
-
Аггрегирование по сервису и региону для быстрого обзора:
sum by (service, region) (rate(http_requests_total[5m]))
-
Уменьшение влияния высокодименсиональных лейблов в запросах:
sum by (service) (rate(http_requests_total{job="api-frontend"}[5m])) -
Поиск «горячих» точек с использованием подмножества лейблов:
topk(5, sum by (service) (rate(http_requests_total[5m])))
-
Проверка наличия отсутствующих серий для ключевых лейблов (Absent):
absent(sum by (service) (rate(http_requests_total[5m])))
Эти элементы позволяют переключиться от детализированного (и часто чрезмерного) уровня к агрегированному, который способен отражать общие тенденции без перегрузки системы мониторинга.
Решения для хранения и анализа: от ретенции до удалённых хранилищ
При кардинальности выше определенного порога необходима стратегия хранения и анализа данных, которая выходит за рамки одного инстанса Prometheus. Основные направления:
- Remote write/read для длительного хранения: перенос данных в внешние хранилища с поддержкой downsampling и агрегаций. Популярные решения: Cortex, Thanos, Mimir. Эти проекты обеспечивают горизонтальное масштабирование, федерацию и единый глобальный запрос на данные округа.
- Федерация и агрегация: локальные инстансы Prometheus агрегируются центральным слоем (federation) или через слой агрегирования в Thanos/Mimir, позволяя выполнять поиск и аналитику по большому набору источников без нагрузки на отдельный узел.
- Downsampling и ретенция: по мере старения данных, применение downsampling снижает размерности и ускоряет запросы. В продвинутых сценариях можно иметь несколько уровней хранения: быстрый темпоральный слой (Prometheus), средний (downsampled Prometheus) и долгохранящиеся (объектное хранилище в Thanos Cortex).
- Архитектурные схемы: Prometheus + Thanos Sidecar/Store-API + Object Storage обеспечивает масштабируемый доступ к глобальным метрикам. Cortex позволяет линейно масштабировать запись и чтение, обеспечивая уровневая инфраструктура. Mimir - альтернатива с фокусом на российском рынке и поддержке гипермасштабных графов мониторинга.
Пример конфигурации remote_write для удалённого хранилища (обобщённый пример):
remote_write:
- url: "http://thanos-receiver.example.net/api/v1/receive"
remote_timeout: 30s
queue_config:
capacity: 2500
max_shager: 5
Пример конфигурации Thanos Sidecar в инфраструктуре Kubernetes:
containers:
- **name**: prometheus
image: prom/prometheus:v2.36.0
args: ["-config.file=/etc/prometheus/prometheus.yml", "-storage.tsdb.path=/prometheus"]
- **name**: thanos-sidecar
image: thanosio/thanos:v0.28.0
args:
- sidecar
- --tsdb.path=/prometheus
- --prometheus.url=http://localhost:9090
- --objstore.config=$(S3_CONFIG)
Интеграция с удалённым хранением требует аккуратной настройки прав доступа, политики ретенции и согласованной сетевой архитектуры. В больших средах подобные решения позволяют достигнуть линейного масштабирования ввода-вывода и эффективного анализа по всей инфраструктуре.
Примеры реализации и сценарии внедрения: шаги, код и конфигурации
Этап 1. Диагностика кардинальности
- Соберите показатели по количеству уникальных значений ключевых лейблов: помните, что не все лейблы одинаково важны для аналитики. Начните с доработки конфигурации сбора и анализа потребления памяти Prometheus.
- Определите лейблы, которые чаще всего создают новые серии, и оцените их бизнес-ценность.
Этап
2. Модель метрик и relabeling
- Определите набор лейблов, необходимых для аналитики, и параметры, которые можно безопасно удалить.
- Примените relabel_configs для удаления или переработки «денег» лейблов. Пример приведён выше.
Этап
3. Агрегации и правила записи
- Разработайте и внедрите набор записывающих правил для снижения кардинальности, создавая агрегированные метрики.
- Поддерживайте два слоя метрик: детализированные (для расследований) и агрегированные (для оперативной аналитики).
Этап 4. Архитектура хранения
- Оцените требования к хранению и скорости доступа. При необходимости - внедрите удалённое хранение через Thanos/Cortex и federated запросы.
- Установите политику ретенции и длительности хранения для каждого слоя, чтобы сохранить полезные данные для анализа без перегрузки.
Этап 5. Внедрение и миграция
- Пошагово внедряйте изменения, начиная с тестовой среды и ограниченного набора метрик.
- Проводите регрессионное тестирование запросов, чтобы убедиться, что аналитика не потеряна.
Примеры конфигураций и сценариев внедрения
-
Пример записи, выделяющей сервис-уровневую метрику по region без per-user детализации:
groups: - **name**: global_service_aggregation rules: - **record**: http_requests_total_by_service_region expr: sum by (service, region) (rate(http_requests_total[5m])) -
Пример relabel_configs для drop лишних лейблов по Scrape:
relabel_configs: - **source_labels**: [__address__] target_label: instance regex: '.*' replacement: '$1' - **action**: drop regex: 'trace_id|user_id' source_labels: [trace_id]Key takeaways
-
Высокая кардинальность - естественный след сложной бизнес-обстановки, но она опасна для производительности Prometheus и инфраструктуры мониторинга в целом.
-
Архитектура Prometheus и современные подходы к хранению требуют стратегий снижения кардинальности на уровне инжекции данных, чтобы обеспечить устойчивость и масштабируемость.
-
Эффективная реализация сочетает: грамотный дизайн метрик, relabeling, агрегации через recording rules и использование удалённых хранилищ для длительного анализа.
-
Интеграция с Thanos/Cortex/Mimir позволяет горизонтально масштабировать сбор и хранение, сохраняя единый слой аналитики и быстрый доступ к данным.
-
Важная часть - план миграции: постепенно внедрять изменения, тестировать на бизнес-кейсовом наборе данных и поддерживать чёткие политики ретенции и агрегаций.
-
Примеры конфигураций relabel_configs и recording rules демонстрируют практическую применимость подходов и позволяют начать работу через минимальные изменения существующей инфраструктуры.
-
Непрерывная оптимизация требует постоянного мониторинга собственных метрик кардинальности, анализа запросов и регулярной ревизии набора лейблов, поскольку бизнес-объекты и сервисы эволюционируют.
FAQ
- Что такое высокая кардинальность в Prometheus и чем она опасна?
Высокая кардинальность - это большое число уникальных комбинаций метрик и лейблов, образующих множество временных рядов. Она опасна тем, что увеличивает требования к памяти и диску, усложняет индексацию и ухудшает скорость выполнения PromQL-запросов. Это приводит к большим задержкам в дэшбордах и риску перегрузки инстанса Prometheus при ретенции.
- Какие признаки сигнализируют о проблеме кардинальности?
Ключевые признаки включают рост числа одновременно активных серий, ускоренное использование памяти, увеличение времени выполнения запросов, частые ошибки при попытке промо-подсчета (rate, sum, count) и противоречивые результаты в запросах, когда группировка по большим наборам лейблов приводит к перегрузке вычислительной подсистемы.
- Какие подходы можно применить без изменений кода?
Начните с анализа и ограничения лейблов, которые попадают в метрики. Применяйте relabel_configs для удаления или переработки лишних лейблов на этапе сбора. Введите recording rules для агрегаций с меньшей кардинальностью и рассмодрите использование удалённых хранилищ для долговременного анализа и масштабирования.
- Как определить, какие метрики являются «высокой кардинальностью» в моей системе?
Проводите регулярный аудит метрик: смотрите на количество уникальных значений ключевых лейблов и сервисов. Метрики с лейблами вроде user_id, session_id, trace_id, UUID инстансов часто приводят к экспоненциальному росту серий. Используйте Prometheus API для подсчета уникальных значений: count by (label) (count_over_time({metric}[1h])) может помочь в предварительной идентификации.
- Как применить relabel_configs для снижения кардинальности?
Relabel_configs позволяет отбросить или переработать лейблы до того, как данные попадут в индекс. Вы можете удалить специфические лейблы (например, user_id), переименовать лейблы в более общие (region, service), а также перенаправить данные в другие наборы метрик. Это один из самых эффективных инструментов для контроля кардинальности на этапе сбора.
- Что выбрать между локальным хранением и удалёнными хранилищами?
Локальное хранение обеспечивает низкую задержку и простоту настройки, но усложняется при масштабировании и долговременном анализе. Удалённые хранилища (Thanos, Cortex, Mimir) позволяют горизонтальное масштабирование, федерацию и продвинутую ретенцию (downsampling), что помогает справиться с кардинальностью. Оптимальная стратегия - комбинация локальных инстансов для оперативной аналитики и удалённого хранилища для долговременной тенденционной аналитики.
- Каковы ограничения Prometheus в контексте высокой кардинальности?
Память и размер индекса - главные ограничения. При большом числе серий Prometheus может исчерпать доступную память и ресурсы CPU. Запросы с группировками по большим набором лейблов будут потреблять много времени и ресурсов. В таких условиях важно применять агрегацию и удаленное хранение.
- Как мигрировать на Thanos/Cortex без потери функциональности?
Начните с внедрения удаленного хранения для существующих экземпляров Prometheus и постепенной миграции запросов к новому слою агрегации. В процессе внедрения воспользуйтесь federation и downsampling, чтобы сохранить целостность аналитики. Важно обеспечить совместимость моделей данных и сверку результатов между локальным Prometheus и удаленным хранилищем.
- Какие примеры записей правил (recording rules) наиболее эффективны для снижения кардинальности?
Эффективные правила - это агрегации по узким и бизнес-значимым лейблам. Примеры: суммирование по сервису и региону, усреднение и rate на окнах 5-15 минут, создание агрегированных метрик для инцидентов. Важно, чтобы эти правила не теряли ценность для анализа и позволяли быстро получать обобщенные индикаторы.
- Как измерять эффект внедрения снижения кардинальности?
Мониторьте количество серий до и после изменений, показатели памяти и дискосодержания Prometheus, время выполнения PromQL-запросов и задержку в дэшбордах. Визуально сравнивайте графики до/после изменений, а также анализируйте качество бизнес-метрик, чтобы убедиться, что агрегации сохраняют полезную информацию. Регулярно проводите стресс-тестирование и мониторинг нагрузки на инстансы.
Глава завершается блоком «Key takeaways» и разделом FAQ, где подробно освещаются типовые сценарии, методики и практические решения. В рамках методических рекомендаций важна последовательная стратегия: начать с минимизации кардинальности на входе, внедрить агрегации и затем применить удалённые хранилища для долговременного анализа. Такой подход позволяет сохранять аналитическую ценность системы мониторинга, поддерживает устойчивую операционную работу и облегчает масштабирование в условиях роста количества серий.



