Архитектура хранилища метрик
Окметр имеет микросервисную архитектуру, в которой вся система разделена на множество компонентов, выполняющих определенную задачу. Эти компоненты работают отдельно и параллельно. Тенант — логическая сущность, позволяющая хранить мониторинговые данные изолированно от других тенантов.
Компоненты:
- Collector
- User-interface-backend
- Agent-updater
- Auth-proxy
- Postgres
- Distributor
- Ingester
- Compactor
- Query frontend
- Querier
- Store gateway
- Block Storage
- Etcd
- Ruler (опциональный компонент)
- Alertmanager (опциональный компонент)
Основные компоненты Okmeter: Хранилище метрик
Схема взаимодействие основных компонентов:
Collector
Collector – это stateless компонент, который производит аутентификацию запросов на запись данных и дальнейшую их маршрутизацию. Каждый запрос содержит в себе метрики.
Следующие шаги описывают, как запрос перемещается через collector:
- Производится аутентификация запроса на основании API token. Если запрос успешно аутентифицирован, выполнение запроса продолжается в соответствии с приведенными ниже шагами.
- Запрос содержащий real-time данные: метрики из запроса отправляются в Distributor.
- Запрос содержащий исторические данные (например, если сеть на сервере была недоступна некоторое время). Из метрик содержащихся в запросе формируется Prometheus block (аналогично Ingester) и, после окончания формирования, блок отправляется в Block-storage.
User-interface-backend
User-interface-backend - это stateless компонент, который реализует функционал личного кабинета пользователя и API:
- Возможности личного кабинета пользователя:
- Создание тенантов(проектов) для изоляции потоков мониторинговых данных;
- Разделение метрик по тенантам – каждый проект/сервис может отправлять мониторинговые данные в свой тенант;
- Выдача пользователям доступа к метрикам в рамках тенанта;
- Режим “супертенанта” – возможность сделать запрос для отображения метрик одновременно в группу тенантов или во все тенанты.
- Управление пользователями, их доступами в к тенантам (проектам);
- Управлять и просматривать дашборды, графики, алерты и триггеры;
- Аутентификация во внешних источниках данных:
- Ldap
- Active Directory
- Создание тенантов(проектов) для изоляции потоков мониторинговых данных;
- Возможности API:
- Управление каналами доставки алертов (настройка Alertmanager):
- Webhook(HTTP push) – при срабатывании триггера вы получите информацию в HTTP-запросе на настроенный URL;
- Email (SMTP);
- Telegram;
- Opsgenie;
- PagerDuty;
- Управление Recording Rule;
- Управление Alert Rule;
- Управление каналами доставки алертов (настройка Alertmanager):
Agent-updater
Agent-updater – это stateless компонент, который используется для обновления okagent. Следующие шаги описывают, как производится обновление:
- Agent-updater принимает запросы от okagent
- На основание токена определяет tenant к которому относится проект.
- Возвращает последнюю доступную версию агента для данного хоста и ссылку на где может быть скачена данная версия. Определение версии производится на основание конфигурационного файла Agent-updater и возможны следующие стратегии:
- Для tenant не задана никакая версия - отдается текущая версия по умолчанию.
- Для данного хоста задана определенная версия (каждый агент имеет уникальный UUID) - возвращается заданная версия.
- Для tenant задан процент канареечной версии. В этом случае, если хост попадает в процент хостов, которые должны получить canary версию возвращается canary version, всем остальным возвращается - текущая версия по умолчанию.
Notification-manager
Notification-manager - это stateless компонент, который получает алерты из Kafka и производит их отправку в соответствии с настроенными каналами доставки, например email, telegramm, webhook и тд.
Auth-proxy
Auth-proxy - это stateless компонент, который производит аутентификацию всех API запросов. Аутентификация производится на основание API tokens. В случае успешной аутентификации, запрос отправляется в соответствующий компонент Okmeter Storage.
Postgres
Postgres - это stateful компонент. Данная база данных используется для хранения данных пользователей и тенантов.
Компоненты Okmeter Storage
Схема взаимодействия компонент Okmeter-storage:
Distributor
Distributor — это stateless компонент, который получает метрики от collector. Distributor проверяет их правильность и соответствие установленным ограничениям для данного tenant.
Затем Distributor делит метрики на пакеты, с учетом правил шардирования и отправляет их в ingester, обслуживающий шард. Копии пакета отправляется на несколько ingester параллельно, в зависимости от коэффициента репликации.
Ingester
Ingester – это stateful компонент, который записывает в журнал (WAL) на локальном диске все входящие метрики и формирует в памяти двухчасовые блоки метрик. После окончания формирования 2-х часовой блок записывается на локальный диск, и затем отправляется в долговременное хранилище. С локального диска блоки удаляются в соответствии с политикой удаления блоков в Ingester (по умолчанию спустя 6 часов). По этой причине Querier запрашивает данные, как из Ingester, так и из долговременного хранилища при выполнении запроса на чтение.
Compactor
Compactor – это stateless компонент, который используется для оптимизации хранения блоков в Block Storage.
Compactor отвечает за: Сжатие нескольких блоков в один оптимизированный блок большего размера. Это достигается за счет дедуплицирования данных (полученного за счет репликации на уровне Ingester) и уменьшает размер индекса, за счет объединения блоков, что приводит к снижению затрат на хранение. Запрос меньшего количества блоков происходит быстрее, поэтому это также увеличивает скорость запроса. Удаление устаревших блоков, в соответствии с retention policy.
Query-frontend
Query-frontend — это stateless компонент, который используется для ускорения запросов на чтение, за счет разделения их на подзапросы и кэширования результатов ответа.
Следующие шаги описывают, как запрос перемещается через query-frontend:
- Query-frontend получает запрос.
- Если запрос является range-запросом, то Query-frontend разбивает его по времени на несколько запросов меньшего размера, которые можно выполнить параллельно.
- Query-frontend проверяет кэш результатов. Если результат запроса находится в кеше, то Query-frontend возвращает кешированный результат. Если нет, выполнение запроса продолжается в соответствии с приведенными ниже шагами.
- Query-frontend помещает запрос (или запросы, если произошло разделение исходного запроса) в очередь в памяти, где он ожидает, пока его не заберет Querier.
- Qurier берет запрос из очереди и выполняет его. Если запрос был разделен или разбит на несколько подзапросов, каждый запрос может быть обработан разными Querier’ами.
- Затем результат(-ы) запроса возвращаются в Query-frontend, который агрегирует и пересылает результаты клиенту.
Querier
Querier — это stateless компонент, который извлекает из Block Storage и Ingester необходимые временные ряды и лейблы, и затем выполняет выражения PromQL на полученном наборе данных.
Querier использует Storage-gateway для получения данных из долговременного хранилища (Block Storage) и Ingester для получения недавно полученных данных.
Store gateway
Storage-gateway – это stateful компонент, который используется для реализации интерфейса доступа к данным в долгосрочном хранилище для других компонентов (Querier и Ruler).
Storage-gateway постоянно хранит в памятии index файл всех блоков для тенантов которые обслуживает данный Storage gateway (в соответствии с политикой шардирования), которые находятся в Block Storage. Index файла достаточно для определения, какие данные необходимо предоставить для каждого конкретного запроса и позволяет извлекать с помощью range запросов только необходимые серии, что снижает потребление ресурсов Block Storage для обслуживания запросов.
Block Storage (S3)
Block Storage (S3) - это stateful компонент, который является S3 совместимое хранилище данных и используется для долгосрочного хранения метрик. Данный компонент может быть реализован на базе Minio или Ceph S3.
Etcd
Etcd - это stateful компонент, который используется для хранения данных необходимой для работы репликации и шардирования данных.
Ruler (опциональный компонент)
Ruler – это stateless компонент, который производит выполнение PromQL (заданный с помощью Prometheus record rules) и сохраняет результат выполнения в виде новой метрики. Так же, данный компонент выполняет PromQL (заданный с помощью Prometheus alerts) и, если выполняется условие срабатывания, передает алерт в Alertmanager.
Alertmanager (опциональный компонент)
Alertmanager – это stateful компонент, который принимает оповещения от Ruler, производит их группировку, дедупликацию и отправляет уведомления в соответствии с настроенными каналами доставки, например через email, telegram, webhook и тд.