Декларативная конфигурация 3.x: config.yaml, иерархия

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

Декларативная конфигурация 3.x: config.yaml, иерархия

Сообщение 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 "в коде" - через вызов box.cfg{} в Lua-скрипте. Это императивный подход: вы описываете, какие параметры применить к одному конкретному процессу. Начиная с версии 3.0, рекомендуемый способ другой - декларативный YAML-файл (обычно config.yaml), который описывает топологию ВСЕГО кластера сразу: какие есть группы, реплика-сеты, инстансы, и какие настройки к ним применяются. box.cfg-подход с 3.0 официально считается legacy, но никуда не делся: под капотом декларативная конфигурация в итоге всё равно превращается в вызовы box.cfg для каждого инстанса.

Ключевая идея урока: один config.yaml описывает много инстансов, а параметры в нём раскладываются по иерархии из четырёх уровней - global, group, replicaset, instance. Это позволяет писать общее один раз сверху и точечно переопределять снизу.

Механика и архитектура

Топология: три вложенных контейнера

YAML описывает кластер сверху вниз тремя вложенными секциями:
  • groups - группа объединяет реплика-сеты. Типичный смысл - разделить роли: в шардированном кластере одна группа хранит данные (storages), другая держит роутеры.
  • replicasets - реплика-сет это пачка инстансов, работающих над одними и теми же данными. Это единица репликации и отказоустойчивости.
  • instances - один запущенный процесс Tarantool. Хранит данные или работает роутером.

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

groups:
  group001:
    replicasets:
      replicaset001:
        instances:
          instance001:
            # ...
          instance002:
            # ...
Четыре скоупа конфигурации

Самое важное: почти любой параметр можно задать на любом из четырёх уровней (скоупов). Уровень определяется тем, на какой глубине YAML вы написали ключ:
  • global - параметр в корне файла, применяется ко всем инстансам кластера.
  • group - параметр внутри конкретной группы, применяется ко всем её инстансам.
  • replicaset - параметр внутри реплика-сета, применяется ко всем его инстансам.
  • instance - параметр у конкретного инстанса.
Инстанс наследует значения сверху вниз, а при конфликте действует порядок приоритета от высшего к низшему: instance > replicaset > group > global. То есть чем "ближе" уровень к инстансу, тем он сильнее. Если iproto.listen задан и глобально, и на инстансе - победит значение инстанса.
Правило простое: общее пишем наверху (global/group), частное - внизу (instance). Tarantool сливает (merge) уровни, начиная с global, и каждый следующий, более узкий уровень переопределяет совпадающие ключи.
Изображение
Иерархия скоупов config.yaml и приоритет

Где находятся настройки vs топология

Не путайте две вещи в файле. Имена групп/реплика-сетов/инстансов - это топология (кто есть кто). А ключи вроде iproto, replication, memtx, log, credentials - это настройки, которые можно положить на любом из четырёх уровней. Один и тот же ключ iproto.listen технически валиден и в корне (global), и внутри instance001.

Откуда вообще берётся конечное значение: precedence источников

Помимо иерархии уровней внутри файла, есть ещё приоритет источников. Итоговое значение опции собирается из нескольких мест, от высшего приоритета к низшему:
  • переменные окружения TT_* (например TT_IPROTO_LISTEN) - перебивают файл;
  • локальный YAML-файл;
  • централизованное хранилище (etcd или Tarantool-based);
  • переменные TT_*_DEFAULT - задают дефолты, если в файле опции нет.
Модуль config: как это применяется внутри

После старта работающий инстанс знает свою конфигурацию через встроенный модуль config. Декларативная конфигурация - это модель "целевого состояния" (target state): вы описываете, КАК должно быть, а Tarantool сам вычисляет, что поменять. Это отличается от box.cfg{}, где вы императивно применяете изменения. Перечитать файл без рестарта - config:reload(). Динамические опции применятся на лету; не-динамические (например размер арены памяти, директории) будут пропущены с алертом и реально применятся только после рестарта.

Ключевые команды и код (оба трека)

Трек 1.x/2.x - box.cfg (legacy)

Один инстанс, всё императивно в init.lua:

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

box.cfg{
    listen = '127.0.0.1:3301',
    replication = {'127.0.0.1:3301', '127.0.0.1:3302'},
    read_only = false,
    memtx_memory = 256 * 1024 * 1024,
}
Запуск: tarantool init.lua. Топологии как объекта тут нет - вы вручную перечисляете адреса соседей в каждом скрипте.

Трек 3.x - config.yaml (декларативно)

Тот же смысл, но как часть описанного кластера. Обратите внимание, как box.cfg-опции мигрируют в YAML-ключи:

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

credentials:
  users:
    replicator:
      password: 'topsecret'
      roles: [replication]

iproto:
  advertise:
    peer:
      login: replicator

replication:
  failover: manual

groups:
  group001:
    replicasets:
      replicaset001:
        leader: instance001
        instances:
          instance001:
            iproto:
              listen:
                - uri: '127.0.0.1:3301'
          instance002:
            iproto:
              listen:
                - uri: '127.0.0.1:3302'
Здесь credentials и replication.failover заданы глобально, leader - на уровне replicaset, а iproto.listen - на уровне instance. Запуск инстанса:

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

tarantool --name instance001 --config config.yaml
Соответствие box.cfg -> config.yaml

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

box.cfg (legacy)          -> config.yaml (3.x)
------------------------------------------------
listen = 3301             -> iproto.listen: [{uri: '...'}]
replication = {...}       -> (вычисляется из топологии replicaset)
read_only = true          -> database.mode: ro  (или через failover)
memtx_memory = N          -> memtx.memory: N
wal_dir / memtx_dir = ... -> wal.dir / snapshot.dir
log_level = 5             -> log.level: 5
Полезные вызовы модуля config

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

require('config'):get('iproto.listen')   -- значение опции для ЭТОГО инстанса
require('config'):get('labels')          -- метки инстанса
require('config'):info()                 -- статус, алерты, активный конфиг
require('config'):reload()               -- перечитать файл без рестарта
Частые заблуждения и грабли
  • "Приоритет идёт сверху вниз по файлу". Нет. Приоритет определяется СКОУПОМ, а не порядком строк: instance всегда сильнее global, где бы они ни стояли.
  • Путают global и group. global - это корень файла. group - это внутри groups.group001. Параметр, написанный в корне, видят все группы; в group001 - только её инстансы.
  • Ждут, что любой reload применит всё. Не-динамические опции (память, директории) на горячую не применяются - только рестарт. Смотрите алерты в config:info().
  • Массивы переопределяются, не сливаются. Для roles (тип array) роль инстанса полностью заменяет роли с верхнего уровня, а не добавляется к ним. А вот roles_cfg (map) сливается по ключам.
  • labels наследуются и переопределяются по ключу из всех скоупов, к которым принадлежит инстанс - удобно, но легко получить не ту метку, забыв про верхний уровень.
  • Имя инстанса обязано совпадать с ключом в YAML и с тем, что передано в --name. Иначе инстанс не найдёт свою ветку конфигурации.
  • Шаблоны. В значениях можно использовать {{ instance_name }}, {{ replicaset_name }}, {{ group_name }} - например, чтобы развести пути снапшотов по инстансам.
Мини-лаба

Возьмите config.yaml из примера выше. Добавьте опцию log.level: 'info' в глобальный скоуп (корень файла), а для instance002 переопределите её на 'verbose' в его instance-скоупе. Запустите instance002, выполните в консоли require('config'):get('log.level') и убедитесь, что вернулось 'verbose'. Затем запустите instance001 и проверьте, что у него унаследовалось 'info'. Поясните себе, почему: instance > global.

Контрольные вопросы
  • Перечислите четыре скоупа конфигурации и укажите порядок их приоритета при конфликте одного и того же ключа.
  • Чем отличается global-скоуп от group-скоупа и где физически в YAML находится каждый из них?
  • Во что в config.yaml мигрируют box.cfg-опции listen, memtx_memory и read_only?
  • Что произойдёт при config:reload(), если в файле изменили не-динамическую опцию (например размер памяти)?
👍1 ❤️2 🔥 😄 🤔1
Ответить
← Предыдущая глава
Классическая конфигурация box.cfg (legacy 1.x/2.x)
Следующая глава →
Роли и приложения в 3.x

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

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

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

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

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