Архитектура хранилища метрик


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

Компоненты:

Основные компоненты Okmeter: Хранилище метрик

Схема взаимодействие основных компонентов:

Collector

Collector – это stateless компонент, который производит аутентификацию запросов на запись данных и дальнейшую их маршрутизацию. Каждый запрос содержит в себе метрики.

Следующие шаги описывают, как запрос перемещается через collector:

  1. Производится аутентификация запроса на основании API token. Если запрос успешно аутентифицирован, выполнение запроса продолжается в соответствии с приведенными ниже шагами.
  2. Запрос содержащий real-time данные: метрики из запроса отправляются в Distributor.
  3. Запрос содержащий исторические данные (например, если сеть на сервере была недоступна некоторое время). Из метрик содержащихся в запросе формируется 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;

Agent-updater

Agent-updater – это stateless компонент, который используется для обновления okagent. Следующие шаги описывают, как производится обновление:

  1. Agent-updater принимает запросы от okagent
  2. На основание токена определяет tenant к которому относится проект.
  3. Возвращает последнюю доступную версию агента для данного хоста и ссылку на где может быть скачена данная версия. Определение версии производится на основание конфигурационного файла Agent-updater и возможны следующие стратегии:
  4. Для tenant не задана никакая версия - отдается текущая версия по умолчанию.
  5. Для данного хоста задана определенная версия (каждый агент имеет уникальный UUID) - возвращается заданная версия.
  6. Для 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:

  1. Query-frontend получает запрос.
  2. Если запрос является range-запросом, то Query-frontend разбивает его по времени на несколько запросов меньшего размера, которые можно выполнить параллельно.
  3. Query-frontend проверяет кэш результатов. Если результат запроса находится в кеше, то Query-frontend возвращает кешированный результат. Если нет, выполнение запроса продолжается в соответствии с приведенными ниже шагами.
  4. Query-frontend помещает запрос (или запросы, если произошло разделение исходного запроса) в очередь в памяти, где он ожидает, пока его не заберет Querier.
  5. Qurier берет запрос из очереди и выполняет его. Если запрос был разделен или разбит на несколько подзапросов, каждый запрос может быть обработан разными Querier’ами.
  6. Затем результат(-ы) запроса возвращаются в 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 и тд.