Перейти к содержимому

Essence

Essence — параметры и значения сервиса: настройки приложения, размеры, флаги, пароли, ключи. Дефолты живут в git рядом с сервисом, а оператор переопределяет их в spec инкарнации. Секреты резолвятся через Vault на стороне сервера при рендере и маскируются на выходе — в логи и отчёты в открытом виде не попадают.

Essence доступен сценарию напрямую (как essence.<путь>), а Destiny получает нужные значения только через явный проброс на входе.

Essence — не плоский список, а иерархическая сборка: значения накладываются слоями, более специфичный слой переопределяет более общий. Порядок сборки по умолчанию:

1. default — baseline для всего сервиса
2. ОС-семейство — поправки под конкретное семейство ОС хоста
3. Coven-метки — поправки под группы, к которым принадлежит хост
4. spec инкарнации — переопределения оператора (самый сильный слой)

Каждый следующий слой видит уже накопленные значения и переопределяет их. Слой оператора (spec) — самый сильный: он перебивает всё, что собрала иерархия. При этом в базе хранится исходный spec оператора (не результат слияния) — чтобы в аудите было видно, что именно он переопределил.

Раскладка дефолтов в репозитории сервиса:

essence/
├── _default.yaml # baseline
├── os/<os-family>.yaml # поправки под семейство ОС (если файл есть)
└── coven/<метка>.yaml # поправки под Coven-метку (если файл есть)

Essence не слоится по роли хоста (master/replica): роль волатильна, и роль-зависимые параметры передаются в Destiny через его вход по живой роли, а не через слой Essence.

Для большинства сервисов convention-based порядка выше достаточно — отдельного описания не требуется.

Когда нужны условия, итерация или вычисляемые значения, порядок сборки описывается явно в essence/_stack.yaml. На каждом шаге доступны факты хоста, атрибуты инкарнации и уже накопленные значения:

essence/_stack.yaml
stack:
# 1. Baseline — всегда
- file: _default.yaml
# 2. Семейство ОС, пропустить молча, если файла нет
- file: "os/${ soulprint.self.os.family }.yaml"
optional: true
# 3. Итерация по всем Coven-меткам хоста
- foreach: "${ host.covens }"
as: coven_name
file: "coven/${ coven_name }.yaml"
optional: true
# 4. Вычисляемое значение из уже собранных фактов
- inline:
redis_maxmemory: "${ int(soulprint.self.memory.total_mb * 0.6) }mb"
when: vars.redis_maxmemory == null

Операторы pipeline:

ОператорНазначение
file:Включить файл; путь может быть выражением.
inline:Включить набор значений без отдельного файла.
when:Условие включения шага.
optional: trueНе падать, если файла по file: нет.
foreach: + as:Итерация: шаг повторяется для каждого элемента.

Между шагами значения пересчитываются, поэтому поздний шаг может опираться на то, что собрал ранний.

Собранный Essence доступен в выражениях сценария как essence.<путь>:

- name: Install redis on all cluster hosts
apply:
destiny: redis
input:
version: "${ essence.redis_version }"
maxmemory: "${ essence.redis.maxmemory }"

Destiny напрямую essence.* не видит (он изолирован) — сценарий подкладывает нужные значения в input: Destiny при вызове apply:, как в примере выше.

Значения-секреты резолвятся через Vault при рендере, на стороне сервера. Движок выражений обрабатывает секрет как обычное значение — иначе нельзя было бы легитимно передать его в параметр модуля. Маскирование применяется на выходе: в логах применения, трейсах, ответах API и отчётах о прогоне секрет в открытом виде не появляется.

Поле, помеченное как секрет в схеме источника, маскируется автоматически. Для задач, прокидывающих секреты, дополнительно есть no_log: на шаге — он скрывает параметры и результат шага из логов целиком.

  • Destiny — куда Essence передаётся через входной контракт.
  • Scenario — где Essence доступен напрямую как essence.*.
  • Архитектура — фазы рендера и резолв секретов на стороне сервера.