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

Концепции

Этот раздел объясняет ментальную модель Soul Stack и его словарь имён. Понимание этих пяти-шести сущностей достаточно, чтобы читать остальную документацию.

Soul Stack — это центральный сервер, который хранит описание желаемого состояния хостов, и агенты, которые приводят свои хосты к этому состоянию.

Поток в одном предложении: оператор описывает, что должно быть на хосте (Destiny), сервер рендерит это описание с учётом фактов о хосте (Soulprint) и параметров (Essence), отправляет агенту, а агент применяет — устанавливает пакеты, правит файлы, управляет сервисами — и возвращает результат прогона.

flowchart TB
    Op["Оператор (Archon)"] -->|описывает желаемое состояние| D["Destiny"]
    D --> K["Keeper (центральный сервер)"]
    K -->|"рендер с учётом Soulprint + Essence<br/>доставка по gRPC поверх mTLS"| S["Soul (агент на хосте)"]
    S -->|применяет к хосту| H["хост"]
    S -.->|отчёт о прогоне обратно в Keeper| K

Ключевое отличие от «запустить скрипт по SSH»: Soul Stack декларативен и идемпотентен. Вы описываете не «выполни команду установки пакета», а «пакет htop должен быть установлен». При повторном прогоне, если состояние уже достигнуто, ничего не меняется — модуль сообщает changed=false.

Soul Stack использует «душевную» метафору. Роли за именами — привычные для master/agent-систем; дальше в документации используются только наши термины.

ИмяЧто это
KeeperЦентральный сервер. Хранит реестры, каталог сервисов, рендерит и доставляет Destiny, ведёт аудит. Масштабируется горизонтально (несколько инстансов поверх общих PostgreSQL и Redis).
Souls (Soul, «душа»)Агенты на управляемых хостах. Один исполняемый файл на Go, применяет Destiny.
DestinyЖелаемое состояние хоста после прогона — набор шагов вида «пакет установлен», «файл присутствует», «сервис запущен».
Soulprint (Принты)Факты о системе хоста: ОС, дистрибутив, ядро, CPU, память, сеть. Собираются агентом.
EssenceПараметры и секреты, привязанные к хосту/группе.
CovenСтабильный логический тег группы агентов (кластер, проект, окружение, ЦОД). Используется в таргетинге, RBAC и маршрутизации.
TraitOperator-set key-value метки на инкарнации (owner=alice, product=billing). Параллельная Coven-у ось: атрибуты владельца/продукта/namespace, по которым можно точно фильтровать таргет и сужать RBAC-видимость.
Archon (Архонт)Оператор Soul Stack — человек или machine-identity. Идентификатор (AID) — любая строка по паттерну ^[a-z0-9][a-z0-9._@-]{1,127}$ (2–128 символов); например archon-alice, alice@corp.com, uid-4815, ops-team.

Центральный сервер. Не монолит: горизонтально масштабируемый stateless-кластер поверх общих PostgreSQL (холодное хранилище: реестры, каталог сервисов, журналы) и Redis (heartbeat-кэш, lease, координация между инстансами). Любой инстанс кластера может обслужить любой запрос.

Keeper отвечает за:

  • реестр агентов и их идентичности;
  • каталог сервисов (что можно применять) и runtime-инстансы (incarnation);
  • рендер Destiny (резолв секретов, вычисление CEL-выражений, рендер шаблонов) — рендер делается на стороне Keeper-а, агент не тянет шаблонизатор;
  • доставку рендеренного Destiny агентам по gRPC поверх mTLS;
  • RBAC, аудит-журнал, интеграцию с Vault.

Агент на управляемом хосте — один статический исполняемый файл на Go soul. Работает в двух режимах одним и тем же набором модулей:

  • pull — демон, сам инициирует долгоживущее соединение к Keeper-у и ждёт заданий;
  • push — oneshot-применение, когда Keeper доставляет Destiny по SSH на хост без установленного агента (через модуль keeper.push).

Идентичность агента — SID (равен FQDN хоста) и SoulSeed (mTLS-пара «сертификат + приватный ключ», выпускается Keeper-ом, регулярно ротируется). Приватный ключ генерируется на хосте и никогда его не покидает.

Destiny — это декларативное описание желаемого состояния хоста. Состоит из шагов; каждый шаг адресует модуль и его состояние в форме core.<module>.<state>:

- module: core.pkg.installed # пакет должен быть установлен
params:
name: nginx
- module: core.file.present # файл должен присутствовать
params:
path: /etc/nginx/nginx.conf
content: "..."
- module: core.service.running # сервис должен быть запущен
params:
name: nginx

Каждый шаг идемпотентен: модуль сначала проверяет текущее состояние и меняет хост, только если оно отличается от желаемого. Результат шага — changed=true (состояние изменилось) или changed=false (уже было таким).

Destiny не пишут на «языке программирования» — это YAML с типизированной схемой. Выражения внутри (условия, интерполяция) — на CEL; рендер файлов — Go text/template. См. раздел DSL.

Soulprint — типизированный набор фактов, который агент собирает о своём хосте: семейство и дистрибутив ОС, версия, архитектура, пакетный менеджер и init-система, ядро, CPU, память, сетевые интерфейсы. Эти факты доступны при рендере Destiny — например, чтобы выбрать имя пакета по дистрибутиву или таргетировать шаг по признаку хоста.

В выражениях факты адресуются как soulprint.self.<путь> — например soulprint.self.os.family.

Essence — параметры и значения, привязанные к агенту или группе: настройки приложения, пароли, ключи. Секреты резолвятся через Vault на стороне Keeper-а при рендере и маскируются на выходе (в логах, трейсах, отчётах) — в открытом виде они в журналы не попадают.

Coven — стабильный логический тег группы агентов: кластер, проект, окружение, ЦОД, тип железа. На метки Coven опираются:

  • таргетинг — какие хосты участвуют в прогоне сценария;
  • RBAC — какие операторы видят и управляют какими группами;
  • маршрутизация — потенциально, к каким Keeper-инстансам тяготеет группа.

Важно: Coven — это только стабильные признаки. Волатильная роль хоста (например, primary/replica в кластере) Coven-ом не является — она определяется живой проверкой во время прогона.

Trait — operator-set key-value метки на инкарнации: owner=alice, product=billing, namespace=dba-ns. Это параллельная Coven-у ось — там, где Coven отвечает «к какой группе относится хост» плоской меткой, Trait отвечает «чей это инстанс / какой продукт / namespace» парой ключ-значение.

Отличия от Coven:

  • key-value, а не плоская метка. Значение Trait — скаляр (product: billing) или список (owners: [alice, bob]); по ключу можно точно фильтровать (owner == 'alice'), чего плоский Coven не даёт.
  • принадлежит инкарнации, не хосту. Trait задаётся оператором в incarnation.spec.traits при создании инкарнации и проецируется на все её хосты автоматически — это организационная метка владельца/продукта всего инстанса.
  • источник — оператор, не агент. Как и Coven, Trait — стабильная registry-данность (кто владеет инстансом), а не факт, который агент репортит о системе.

Trait-метки проецируются в soulprint.self.traits.<ключ> и доступны в таргетинге (where:) и в RBAC-scope (trait=ключ:значение). Управление — Trait на инкарнации (REST/MCP/UI), таргетинг — Scenario → where:.

Два связанных понятия из runtime-модели:

  • Serviceтип: git-репозиторий со сценариями, дефолтными параметрами и схемой состояния. Версионируется git-ref-ом (тег или ветка).
  • Incarnationruntime-инстанс сервиса: конкретное применение типа к набору хостов, со своим состоянием в PostgreSQL. У incarnation есть spec (что заказано), state (что фактически достигнуто) и status (где сейчас прогон).

Например, Service redis-cluster — это описание «как поднять кластер Redis»; Incarnation redis-prod-eu — конкретный кластер в проде EU, со своим набором хостов и состоянием.