Cortex: хранение, ingestion и запросы на больших данных
Cortex выступает как горизонтально масштабируемый слой для Prometheus, реализующий долговременное хранение и единый механизм ingestion и запросов для больших платформ. В условиях крупных инфраструктур с тысячами метрик и длительными периодами хранения Cortex обеспечивает разделение задач между инжестером, диспетчером, искателем, хранилищем объектов и компонентами управления данными. Эта глава посвящена архитектуре Cortex в контексте хранения, ingestion и запросов на больших данных: как данные попадают в систему, как они индексируются и хранятся во времени, какие подходы используются для масштабирования чтения и записи, а также какие эксплуатационные практики обеспечивают отказоустойчивость и предсказуемую производительность на платформе масштаба предприятия.
Cortex проектируется как модульная система, где каждый компонент отвечает за конкретную функцию: ingestion и балансировку по tenant’ам, долговременное хранение в объектном хранилище, выполнение запросов по горячим данным и доступ к холодным данным из длинного архива. При этом архитектура поддерживает многопоточность, изоляцию tenant’ов и возможность горизонтального масштабирования без потери целостности данных и минимизации задержек по запросам. Понимание тонкостей Cortex важно для инженеров, ответственных за эксплуатацию мониторинга больших платформ, поскольку именно выбор конфигурации и паттернов развёртывания определяет стоимость владения, устойчивость к сбоям и качество служебных уровней по мониторингу всего технологического стека.
- Архитектура Cortex: микросервисы, хранение и поток данных
- Путь ingestion и хранение: от Prometheus к блокам Cortex в объектном хранилище
- Запросы: горячие данные через ingesters и холодные через store-gateway
- Масштабирование, отказоустойчивость и эксплуатация
- Интеграции и практические сценарии внедрения в крупных платформах
Архитектура Cortex: микросервисы, хранение и поток данных
Cortex реализует горизонтальное масштабирование за счёт разделения задач между несколькими компонентами. Основные сервисы в классическом микро-сервисном развёртывании:
- Distributor - принимает входящие метрики от клиентов (Prometheus, внешние агенты) и распределяет нагрузку по токенам tenant’а в соответствии с кольцом (ring). Distributor обеспечивает балансировку запросов на ingestion и маршрутизацию к ingesters.
- Ingester - хранит данные в памяти и делает периодическую запись WAL (write-ahead log) на диске. Ingester отвечает за быстрое попадание больших потоков метрик в систему, обеспечивает локальную агрегацию и подготовку данных к долговременному хранению.
- Querier - исполняет запросы к данным пользователей. Он может комбинировать данные из горячего пути (ингестеры) и холодного пути (хранилище объектов), чтобы вернуть полный диапазон по заданному временному окну и метрикам.
- Store-Gateway - модуль чтения данных из долговременного хранилища (object storage). Он отвечает за обращение к блокам данных, которые были сохранены в объектном хранилище, и выдачу их Querier’у.
- Compactor - процесс, который выполняет компакцию блоков в object storage для оптимизации затрат на хранение и ускорения последующих запросов. Компактация уменьшает число блоков и упрощает индексирование.
- Ring - слой согласованного распределения (часто реализуемый через Consul, etcd или собственный механизм Cortex) для георга и шардинга по tenant’ам и сериям. Ring обеспечивает устойчивость к сбоям и равномерное распределение нагрузки между инстансами ingester’ов и distributor’ов.
- Alerting и Rules - компоненты для расчёта правил оповещений и их исполнения, часто интегрируемые отдельно в рамках экосистемы Cortex (ruler).
Компоненты и их роли в рабочем потоке данных
- Ingestion начинается с прихода данных в Distributor. Distributor применяет селекторTenant’а (по данным, которые пришли с клиентской стороны) и маршрутизирует потоки к ingester’ам, соблюдая токены кольца. Это обеспечивает горизонтальное масштабирование ingress’а без жесткой привязки к конкретному узлу.
- Ingester хранит сериальные ряды в памяти для быстрого доступа при чтении и записи. Важнейшая часть - WAL: при любом сбое ingester может восстановить данные из WAL и повторно записать их в память и далее в долговременное хранилище.
- Когда диапазон временных метрик достигает порога, ingester синхронно или асинхронно сохраняет данные в блоках в объектном хранилище. Эти блоки отражают временные интервалы и соответствуют схемам TSDB-подобного формата Cortex.
- Querier осуществляет поиск по данным: для горячих данных он может напрямую запрашивать ingesters, для холодных - обращается к store-gateway, который читает блоки из object storage. В сложных случаях запрос может распараллеливаться между несколькими узлами и агрегироваться.
- Store-Gateway оптимизирует доступ к долговременному хранению и поддерживает индексы для ускорения чтения больших наборов блоков. Компонент часто оснащается кэшами, чтобы повторные запросы возвращались быстрее.
- Compactor периодически просматривает существующие блоки и выполняет их агрегацию/перекопку. Это снижает число блоков на хранении и уменьшает задержку при чтении больших временных диапазонов.
Принципы хранения и формат данных
Cortex хранит данные в виде «блоков» в объектном хранилище. Каждый блок содержит индекс и сериальные чанки (chunks), которые описывают метрики и их значения за заданный временной интервал. Вверх по стеку слой ingester пишет в память, WAL обеспечивает устойчивую запись и гарантирует повторную обработку в случае сбоев. Блоки в объектном хранилище делят данные по tenant’ам и по временным окнам, что позволяет осуществлять эффективный доступ к данным без необходимости загружать полностью все данные в память.
Важной концепцией является разделение между быстрыми данными (горячие данные в памяти ingester’ов) и холодными данными (архивные блоки в объектном хранилище). Это делает Cortex подходящим для сценариев с большими временными диапазонами - от часов до лет - без непропорционального увеличения затрат на RAM.
Путь ingestion и хранение: от Prometheus к блокам Cortex в объектном хранилище
Ingress-поток в Cortex начинается с источника данных: Prometheus, который может направлять метрики через удалённую запись (remote_write) в Cortex, либо оборудование агентов-экстракторов, настроенных на отправку метрик в Distributor. Distributor получает потоки и разбивает их по tenant’ам с использованием кольца шардинга. Это обеспечивает горизонтальное масштабирование ingestion и устранение «утилизации» отдельных узлов под тяжёлые пики.
Ingester’ы формируют базовую структуру «серий» в памяти и регулярно записывают данные в WAL для долговременной надежности. В периоды времени, когда данные становятся «историческими» по отношению к текущей работе Querier’а, Cortex переходит к сохранению данных в блоки в object storage. Такой подход позволяет быстро обслуживать широкий диапазон запросов и обеспечивает низкую стоимость хранения за счёт использования долговременного хранилища, а также упрощает регенерацию данных в случае потери узлов.
Формат блока поддерживает эффективное чтение даже при очень больших объемах данных. Индекс блока содержит метаданные по метрикам, ярлыкам и временным диапазонам, что ускоряет поиск нужных серий в конкретном времени. При этом чтение из горячего пути может происходить напрямую из ingester’ов (для недавних данных), а более старые диапазоны - через store-gateway, использующий индекс и блоки из хранилища.
Важные операционные параметры
- Временные окна блоков - ключевой параметр, влияющий на латентность чтения и размер индекса. Чем меньше окно, тем быстрее поиск по конкретному диапазону, но больше блоков.
- Размер блока и политика компактации - влияют на стоимость хранения и частоту операций чтения. Регулярная компактация снижает число блоков и упрощает сканирование данных.
- Репликация и устойчивость к сбоям - Ring обеспечивает ветвление и репликацию данных по нескольким узлам. В случае сбоев доступны механизмы перераспределения и повторной обработки WAL.
- Объектное хранилище - выбирать совместимый тип (S3, GCS, Azure Blob и пр.) и настраивать параметры доступа, тайм-ауты и ключи безопасности.
Запросы: горячие данные через ingesters и холодные данные через store-gateway
Запросный путь Cortex оптимизирован под сценарии, характерные для больших платформ: часть данных находится в памяти ingester’ов и может обслуживаться низкой задержкой; остальная часть, особенно старые диапазоны, - через store-gateway к блокам в объектном хранилище. Это разделение обеспечивает пропорциональное соотношение между производительностью запросов и стоимостью хранения.
- Горячие запросы. Когда запрос касается текущих периодов времени, Querier может обратиться непосредственно к ingester’ам, чтобы вернуть данные практически мгновенно. Это особенно важно для оперативного мониторинга и реагирования на инциденты.
- Холодные данные. Для длинной истории Cortex обращается к store-gateway, который читает соответствующие блоки из object storage. Индексы блоков позволяют выполнить поиск по метрикам без полного сканирования несущественных данных, а последующая агрегация возвращает единый ответ пользователю.
- Оптимизация запросов. Для больших диапазонов Cortex может применяться слой Query Frontend, который разделяет запрос на подзадачи и координирует выполнение параллельно между несколькими Querier’ами. Это снижает задержку и быстро возвращает результат даже при экстремально больших объёмах данных.
- Кэширование результатов. В критически важных сценариях применяются кэш-листы на уровне клиента и на уровне слоя Querier для повторных запросов к тем же диапазонам и метрикам.
Ограничение и контроль над ресурсами
- Лимитирование по памяти и памяти-очереди. Чтобы предотвратить перегрузку памяти на ingester’ах и предотвратить заторы, Cortex обеспечивает лимиты на число серий, объём буфера и скорость записи.
- Тайм-ауты и квоты запросов. Для стабильности кластера применяются лимиты по времени выполнения и объёму возвращаемых данных.
- Мониторинг производительности запросов. Важные метрики включают задержку чтения, количество активных запросов, пропускную способность к store-gateway и загрузку индексирования блоков.
Масштабирование, отказоустойчивость и эксплуатация
Эксплуатация Cortex на больших платформах требует грамотной архитектуры развёртывания, устойчивости к сбоям и планирования обновлений. Основные принципы:
- Горизонтальное масштабирование. Добавление инстансов Distributor и Ingester обеспечивает более высокую входную пропускную способность, в то же время Querier и Store-Gateway масштабируются для обработки большего объёма запросов к данным. Ring обеспечивает корректное распределение нагрузки иTenant isolation.
- Высокая доступность. Указанные компоненты спроектированы как stateless или quasi-stateless, что позволяет выполнять обновления и рестарты без потери данных. WAL обеспечивает долговременную целостность данных на случай сбоев узлов ingester’а.
- Валидация и миграции данных. При добавлении новых версий блоков или изменении схемы Cortex следует предусмотреть тестируемые миграции синхронного доступа к блокам и индексов, чтобы не прерывать мониторинг в продакшене.
- Операционные практики. Регулярная проверка состояния кольца, мониторинг использования памяти и диска, анализ задержек ingestion и чтения, а также тестирование восстановления после сбоев - основа надёжности.
- Резервное копирование и DR. Данные Cortex держатся в долговременном хранилище; резервирование на уровне объектного хранилища и регулярное тестирование восстановления из резервных копий - критически важны для бизнес-критичных систем мониторинга.
- Обновления и миграции. Рекомендуется планировать обновления поэтапно: обновление отдельных компонентов, тестирование совместимости и затем масштабируемое развёртывание. Поддержание совместимости версий между distributor, ingester, querier и store-gateway уменьшает риск несовместимости.
- Мониторинг самих Cortex. Важно не только мониторить целевую платформу, но и сам Cortex: показатели задержек ingestion, backlog WAL, заполненность памяти ingester, загрузку блоков в store-gateway, количество блоков и скорость компактации.
Практические паттерны развёртывания
- Kubernetes-подход с StatefulSet для ingester’ов и distributor’ов, плюс Deployment для querier и store-gateway. Такой подход обеспечивает управляемую эластичность и устойчивость к сбоям.
- Размещение по зонам доступности. Распределение инстансов по нескольким зонам снижает риск одновременной потери данных и помогает выдерживать региональные сбои.
- Необходимо предусмотреть стратегию обновления: сначала обновляются сервисы, не влияющие на долговременное хранение, затем - хранилище данных и, наконец, клиенты.
Интеграции и практические сценарии внедрения
Cortex часто стоит в связке с Prometheus как долговременный механизм хранения и аналитики. В крупных платформах common сценарий - Prometheus-системы пишут в Cortex через remote_write; Cortex служит единой точкой хранения и позволит централизовать данные для анализа и ретроспективной нарезки. В некоторых случаях Cortex выступает как часть более широкой экосистемы для глобального мониторинга в сочетании с другими решениями, такими как Thanos или Mimir, для федерации или кросс-областного доступа, однако порядок взаимодействия и соответствующие паттерны интеграции должны быть подробно спроектированы в зависимости от требований к latency и консистентности.
- Встроенные стратеги оптимизации чтения - использование Frontend’а запросов и кэширования; архитектура позволяет отделить ingestion-узлы от query-пути, чтобы не мешать ingestion и не перегружать одну точку входа.
- Интеграция с облачными и локальными объектными хранилищами обеспечивает гибкость в выборе инфраструктуры и контроля за затратами на хранение.
- В части операционной эксплуатации Cortex рекомендуется применять единые политики управления версиями, автоматическое тестирование миграций и интеграционные тесты для сценариев отказов и восстановления.
Проект Cortex предусматривает богатые механизмы для работы в крупных коллективах: multi-tenant isolation, контроль доступа на уровне tenants, глобальная видимость метрик и единый путь доступа к историческим данным. В условиях больших платформ эта архитектура позволяет обеспечить предсказуемые SLA по задержкам на запросы, сохранить значения в долгосрочной перспективе и поддерживать высокую доступность мониторинга.
Примечание: в этой главе не приводятся детальные примеры конфигураций, так как они зависят от версии Cortex, инфраструктурных ограничений и политики безопасности конкретной организации. Для практической реализации рекомендуется опираться на официальную документацию вашего развёртывания Cortex и внедрять настройку постепенно, с тестированием на пилотной среде.
Key takeaways
- Cortex обеспечивает горизонтальное масштабирование за счёт разделения функций ingestion, хранения и запросов между-distributor, ingester, querier и store-gateway.
- Горячие данные поступают через ingester’ы с поддержкой WAL, холодные данные хранятся в объектном хранилище и доступны через store-gateway.
- Архитектура позволяет эффективно хранить огромные объемы данных, используя блоковую структуру и компактацию блоков в объектном хранилище.
- Запросы выполняются через распределённый путь: ingestion-путь и read-путь, с использованием frontend-кэширования и параллельного исполнения.
- Эксплуатация требует стратегий HA, DR, мониторинга долговременного хранения и планирования миграций версий компонентов.
- Интеграции с Prometheus и экосистемой мониторинга требуют аккуратного проектирования маршрутов данных и учёта требований к latency и консистентности.
- Практические рекомендации включают архитектурные паттерны развёртывания, зоны доступности, управление версиями и тестирование в пилотных окружениях.
FAQ
- Что такое Cortex и чем он отличается от других решений для долгосрочного хранения Prometheus?
Cortex - это горизонтально масштабируемый слой для Prometheus, который обеспечивает ingestion, долговременное хранение и масштабируемые запросы в рамках мульти-tenant архитектуры. В отличие от одновременных решений, Cortex отделяет ingestion и запросы, использует блоковую модель хранения в объектном хранилище и обеспечивает устойчивость к сбоям за счёт WAL и кольца шардинга. В контексте больших платформ Cortex позволяет хранить годы данных по тысячам метрик и обеспечить управляемый ресурсами доступ к ним.
- Как Cortex достигает масштабирования ingestion?
Масштабирование ingestion достигается за счёт Distributor и Ingester. Distributor распределяет входящие потоки данных по токенам tenant’а через кольцо; ingester принимает данные, держит их в памяти и записывает WAL. По мере роста нагрузки добавляются новые ingester’ы, которые перераспределяют данные и обеспечивают параллельное обслуживание. Репликация через Ring обеспечивает устойчивость к сбоям и баланс нагрузки.
- Как Cortex хранит данные в долгосрочной перспективе и как обеспечивается доступ к ним?
Данные сохраняются в блоках в объектном хранилище. Каждый блок содержит индекс и chunk’и, относящиеся к конкретному диапазону времени и tenant’у. Горячие данные доступны через ingester’ы; холодные данные - через store-gateway, который читает блоки из хранилища и предоставляет их Querier. Компактация блоков увеличивает эффективность чтения и уменьшает стоимость хранения.
- Какие паттерны запросов используются для больших наборов данных?
Cortex применяет горизонтальное масштабирование запроса через несколько Querier’ов и optional Frontend для батчинга и кэширования. Запросы к горячим данным обслуживаются напрямую ingester’ами, к холодным - через store-gateway. Параллельное выполнение задач и агрегация результатов обеспечивают приемлемую задержку даже при больших диапазонах времени и множестве метрик.
- Как организовать отказоустойчивость и доступность Cortex в крупной среде?
Важно обеспечить горизонтальное масштабирование всех компонентов, распределение по зонам доступности и отказоустойчивый ring. WAL помогает восстанавливаться после сбоев ingester’а, объектное хранилище обеспечивает долговременную сохранность. Регулярное тестирование восстановления, мониторинг ключевых метрик (RAM, backlog WAL, задержки ingestion/queries, число блоков) и планирование обновлений снижают риск простоя.
- Какие практики конфигурации способствуют эффективной эксплуатации Cortex?
Рекомендуются паттерны развёртывания с разделением рабочих нагрузок на ingestion и query-путь, использование Frontend для критических сценариев, настройка зон Availability, мониторинг метрик Cortex и окружающей инфраструктуры (объектного хранилища, сети). Важна корректная настройка времени жизни блоков, размеров блоков и скорости компактации, чтобы балансировать задержку и стоимость хранения.
- Какие интеграции следует рассмотреть в рамках крупных платформ?
Варианты включают прямую интеграцию Prometheus через remote_write к Cortex, совместную работу с системами федерации мониторинга, а также продуманную стратегию хранения исторических данных - выбор между Cortex-подходом и альтернативами (например, Thanos или Mimir) в зависимости от требований к консистентности, latency и затратам. В крупных средах целесообразно провести пилоты для сравнения TCO и поведения под типичными нагрузками.
- Какие угрозы производительности следует мониторить в Cortex?
Основные риски - перегрузка ingestion path (в частности backlog WAL), недостаточная память на ingester’ах, узкие места в сети между distributor и ingester’ами, задержки на чтение из object storage и чрезмерное количество блоков, препятствующее эффективному сканированию. Регулярный мониторинг латентности запросов, очередей, пропускной способности и состояния_RING поможет выявлять проблемы заранее.
- Какие сценарии миграций и обновлений стоит планировать?
Рекомендуется проводить обновления поэтапно, начиная с компонентов, не влияющих на долговременное хранение, затем обновлять хранилище и, наконец, клиенты. Важно тестировать совместимость версий, миграции индексов и структуры блоков на стенде перед переносом в продакшн. В крупных платформах миграции требуют координации между командами SRE, платформа-инженерии и разработчиками метрик.
- Какие вопросы безопасности и соответствия следует учитывать?
В контексте Cortex критически важно обеспечить безопасные каналы связи между компонентами, управление доступами к объектному хранилищу, контроль за секретами и ключами доступа, а также аудит изменений конфигураций и сбоев. При работе в мульти-арендной среде требуется строгая сегрегация прав и шифрование данных как в покое, так и в транзит.



