Мониторинг: метрики, Prometheus, Grafana

Рейтинг: 64% · 16 голосов
Исчерпывающий курс по Tarantool 3.x: модель данных, движки memtx и vinyl, Lua и файберы, транзакции и MVCC, SQL, конфигурация (box.cfg и декларативная 3.x), репликация и Raft, шардирование vshard, эксплуатация, безопасность. 47 уроков со схемами.
Ответить
Аватара пользователя
denis_tnt
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Мониторинг: метрики, Prometheus, Grafana

Сообщение denis_tnt »

Оглавление курса (47)
  1. Что такое Tarantool: in-memory СУБД и сервер приложений
  2. Архитектура изнутри: процесс, потоки, event-loop
  3. Установка и первый запуск: tt CLI, пакеты, Docker
  4. Интерактив: консоль, admin-консоль, первые команды
  5. Спейсы и кортежи: форматы, типы данных
  6. Типы индексов и их применимость
  7. Движки хранения: memtx vs vinyl
  8. DDL: схема, создание спейсов и индексов, миграции
  9. DML и выборки: insert/update/upsert, итераторы
  10. Персистентность: WAL, снапшоты, recovery
  11. Внутренности memtx: аллокаторы slab/arena, память
  12. Внутренности vinyl: LSM, компакция, тюнинг
  13. Lua и LuaJIT в Tarantool: box, модули, rocks
  14. Файберы: кооперативная многозадачность, каналы
  15. Транзакции: ACID, изоляция, MVCC
  16. Хранимые процедуры, модули, организация приложения
  17. net.box: удалённые вызовы, async
  18. Пулы соединений, балансировка, реконнект
  19. Ошибки и диагностика: box.error, pcall
  20. Типы и сериализация: MsgPack, decimal, datetime, uuid
  21. SQL в Tarantool: возможности и связь с box
  22. SQL: таблицы, JOIN, подзапросы, представления
  23. SQL: подготовленные выражения, транзакции, Lua-интероп
  24. Классическая конфигурация box.cfg (legacy 1.x/2.x)
  25. Декларативная конфигурация 3.x: config.yaml, иерархия
  26. Роли и приложения в 3.x
  27. Централизованная конфигурация: etcd / config storage
  28. tt CLI глубоко: разработка, сборка, запуск
  29. Cartridge (официальный legacy) и миграция на 3.x
  30. Репликация: replicaset, топологии
  31. Механика репликации: WAL-стриминг, vclock
  32. Синхронная репликация и выборы лидера (Raft)
  33. Жизненный цикл узла: bootstrap, join, rejoin
  34. vshard: router/storage, виртуальные бакеты
  35. Решардинг и rebalancing бакетов
  36. Запросы поверх шардов: map-reduce, crud
  37. Мониторинг: метрики, Prometheus, Grafana (вы здесь)
  38. Логирование и аудит
  39. Бэкапы и восстановление
  40. Безопасность: аутентификация, RBAC, TLS
  41. Производительность: профилирование, тюнинг
  42. Обновления: схема, rolling upgrade
  43. Деплой в продакшен: Docker, топология (официальные паттерны)
  44. Администрирование через официальный TCM (Tarantool Cluster Manager)
  45. Коннекторы: Python, Go, Java
  46. Ключевые модули (rocks): crud, metrics, queue, expirationd
  47. Capstone: шардированный отказоустойчивый кластер
Зачем это нужно

Tarantool - это in-memory СУБД и сервер приложений в одном процессе. Если он начнёт упираться в память arena, копить отстающую репликацию или захлёбываться запросами, вы должны узнать об этом не из жалоб пользователей, а из графика. Цепочка наблюдаемости в чистом Tarantool выглядит так: instance отдаёт метрики -> Prometheus их собирает (scrape) и хранит как time series -> Grafana рисует дашборды и считает алерты. В этом уроке разбираем, как именно метрики рождаются внутри процесса, как они превращаются в текстовый эндпоинт и как доезжают до графика.

Откуда берутся числа: модуль metrics

В Tarantool 3.x модуль встроен в ядро (раньше это была отдельная rock-зависимость). Он состоит из двух частей:
  • Коллекторы - объекты, которые хранят значения в памяти. Семантика типов один в один как у Prometheus.
  • Callback-и сбора - функции, которые перед отдачей метрик опрашивают

    Код: Выделить всё

    box.info
    ,

    Код: Выделить всё

    box.stat
    ,

    Код: Выделить всё

    box.slab.info()
    и заполняют встроенные коллекторы с префиксом .
Четыре базовых типа коллекторов:

Код: Выделить всё

counter   - монотонно растёт, сбрасывается только при рестарте (tnt_net_requests_total)
gauge     - произвольное число вверх/вниз            (tnt_info_memory_lua)
histogram - набор bucket-ов по границам le + _sum + _count (латентность)
summary   - то же, но считает квантили на стороне инстанса
Ключевой момент про внутреннюю механику: встроенные метрики - это НЕ фоновый сборщик, который крутится по таймеру. Значения вычисляются лениво, в момент чтения - когда кто-то дёргает эндпоинт или вызывает

Код: Выделить всё

metrics.collect()
. Поэтому сам факт включения метрик почти ничего не стоит: нагрузка появляется только на момент scrape. Под капотом callback просто читает уже готовые счётчики ядра (

Код: Выделить всё

box.stat()
,

Код: Выделить всё

box.info()
), так что один scrape - это дёшево.

Метрика идентифицируется не только именем, но и набором label (меток). Например

Код: Выделить всё

tnt_space_len{name="users", engine="memtx"}
- отдельная серия на каждый спейс. В кластере критично добавить метку с именем инстанса, иначе серии от разных нод сольются. В декларативном конфиге это делается через

Код: Выделить всё

metrics.labels
с предопределённой переменной

Код: Выделить всё

{{ instance_name }}
.

От памяти к HTTP: плагины и форматы

Коллекторы живут в памяти как Lua-объекты. Чтобы Prometheus их забрал, нужно отдать их по HTTP в plain-text формате экспозиции Prometheus. За это отвечают плагины модуля metrics:

Код: Выделить всё

prometheus
(текст с

Код: Выделить всё

# HELP/# TYPE
и строками

Код: Выделить всё

имя{метки} значение
) и (для Telegraf/InfluxDB). Плагин - это просто сериализатор: он обходит реестр коллекторов и печатает их.

В чистом Tarantool 3.x правильный способ поднять эндпоинт - официальная роль

Код: Выделить всё

roles.metrics-export
. Она запускает встроенный HTTP-сервер и вешает на него пути с нужным форматом. Никакого кастомного кода писать не надо.

Код: Выделить всё

metrics:
  include: [ all ]
  exclude: [ vinyl ]
  labels:
    alias: '{{ instance_name }}'

groups:
  storages:
    roles: [ roles.metrics-export ]
    roles_cfg:
      roles.metrics-export:
        http:
          - listen: 8081
            endpoints:
              - path: /metrics/prometheus/
                format: prometheus
              - path: /metrics/json/
                format: json
После этого

Код: Выделить всё

curl http://host:8081/metrics/prometheus/
вернёт текст вида

Код: Выделить всё

tnt_info_uptime 137.5
. Это и есть точка контакта с внешним миром.

Изображение
Путь метрики: инстанс - Prometheus - Grafana

Prometheus: pull, а не push

Принципиальная вещь: Prometheus работает по модели pull. Не Tarantool шлёт метрики - Prometheus сам ходит на эндпоинты по расписанию (

Код: Выделить всё

scrape_interval
, обычно 5-15 секунд), забирает текстовый снимок и складывает каждую серию в свою TSDB как пары (timestamp, value). Counter в TSDB лежит как сырое растущее число; превращение в "запросов в секунду" - уже задача запроса PromQL (), а не инстанса.

Конфиг scrape-задания перечисляет инстансы как targets и задаёт путь:

Код: Выделить всё

global:
  scrape_interval: 5s

scrape_configs:
  - job_name: tarantool
    metrics_path: /metrics/prometheus/
    static_configs:
      - targets:
          - 'storage-a-001:8081'
          - 'storage-a-002:8082'
          - 'router-a-001:8083'
Grafana: чтение и визуализация

Grafana сама ничего не собирает - это слой визуализации поверх datasource (Prometheus). Панели шлют в Prometheus PromQL-запросы и рисуют ответ. Для Tarantool есть готовые официальные дашборды на grafana.com: ID 21474 для Tarantool 3 (Prometheus) и ID 21484 (InfluxDB). Импорт - по ID или по JSON. Дашборд параметризован переменной datasource и меткой alias, поэтому одна и та же панель работает для всех нод кластера через выпадающий список.

Полезные внутренние метрики, на которые стоит смотреть в первую очередь:

Код: Выделить всё

tnt_info_memory_lua          - память Lua-рантайма (утечки бизнес-логики)
tnt_slab_arena_used_ratio    - заполнение arena (риск ER_MEMORY_ISSUE)
tnt_net_requests_current     - бэклог незавершённых запросов
tnt_replication_lag          - отставание реплики, секунды
tnt_space_len{name=...}      - число кортежей в спейсе
Создать свою метрику тоже можно без сторонних библиотек:

Код: Выделить всё

local metrics = require('metrics')
local ops = metrics.counter('myapp_orders_total', 'Число заказов')
-- внутри обработчика:
ops:inc(1, { status = 'ok' })
При следующем scrape она автоматически попадёт в эндпоинт - отдельный реестр заводить не нужно.

Частые заблуждения и грабли
Метрики - это pull. Если на графике пусто, в 90% случаев проблема не в Tarantool, а в том, что Prometheus не достучался до эндпоинта (порт, firewall, неверный metrics_path) или выбран не тот datasource в Grafana.
  • Counter путают с rate.

    Код: Выделить всё

    tnt_net_requests_total
    всегда растёт - смотреть на него напрямую бессмысленно. Нужен

    Код: Выделить всё

    rate(tnt_net_requests_total[1m])
    . На сыром counter график выглядит как прямая линия.
  • Нет метки инстанса. Без /

    Код: Выделить всё

    {{ instance_name }}
    серии разных нод схлопываются, и на счётчике даёт скачки при рестарте чужой ноды. Метка инстанса обязательна в кластере.
  • Пустой дашборд при живых метриках. Официальные панели опираются на группу , в частности на

    Код: Выделить всё

    tnt_info_uptime
    . Если эта группа исключена в

    Код: Выделить всё

    metrics.exclude
    , дашборд "слепнет".
  • Взрыв кардинальности. Метка с высокой кардинальностью (user_id, trace_id) на пользовательской метрике порождает миллионы серий и кладёт Prometheus по памяти. Метки - только для значений с малым числом вариантов.
  • vinyl-метрики по умолчанию урезаны.

    Код: Выделить всё

    tnt_vinyl_*
    по числу кортежей выключены ради производительности; их включают отдельно. Не ждите их в дашборде "из коробки".
  • Слэш в конце пути. Путь в роли и

    Код: Выделить всё

    metrics_path
    в Prometheus должны совпадать байт в байт, включая завершающий слэш.
Мини-лаба

Поднимите одиночный инстанс Tarantool 3.x с включённой ролью

Код: Выделить всё

roles.metrics-export
на порту 8081 (конфиг из урока, метка alias). Запустите его, затем выполните

Код: Выделить всё

curl -s http://127.0.0.1:8081/metrics/prometheus/ | grep tnt_info_uptime
. Сделайте пару запросов к инстансу (любой

Код: Выделить всё

box.space
insert/select через консоль), снова сделайте curl и найдите строку

Код: Выделить всё

tnt_net_requests_total
- убедитесь, что число выросло. Задание-минимум: найти в выводе свою метку внутри фигурных скобок у любой серии.

Контрольные вопросы
  • Кто инициирует передачу метрик - Tarantool или Prometheus, и как называется эта модель?
  • В какой момент реально вычисляются встроенные метрики и почему включение метрик дёшево для инстанса?
  • Почему на counter-метрику нужно навешивать , а не смотреть на её абсолютное значение?
  • Что произойдёт с дашбордом, если в кластере не задать метку с именем инстанса, и как её добавить в декларативном конфиге?
👍3 ❤️ 🔥1 😄 🤔1
Ответить
← Предыдущая глава
Запросы поверх шардов: map-reduce, crud
Следующая глава →
Логирование и аудит

Все главы курса «Tarantool: in-memory СУБД и сервер приложений с нуля до продакшена»

Поделиться темой: ✈ Telegram VK

Вернуться в «Tarantool: СУБД и сервер приложений»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя