Как это устроено

Архитектура control-plane

Центральный сервер описывает желаемое состояние, агенты приводят к нему хосты. Между ними — честная reconcile-петля и один транспорт, работающий и в pull, и в push.

Операторweb-UI · soulctl · MCP · OpenAPI
KEEPERstateless-кластеррендер Destiny · RBAC · аудит · реестры · web-UI
soulагент на хостестатический исполняемый файл на Go · применяет Destiny
PostgreSQLдолговечное состояние
Redisгорячее: presence · lease · heartbeat
Vaultсекреты (масштаб — на выходе)

Keeper — мозг без состояния на диске

Keeper хранит реестры (сервисы, coven-метки, RBAC), рендерит Destiny из Essence, планирует инкарнации и ведёт аудит. Всё состояние — в общих PostgreSQL и Redis, не на диске инстанса, поэтому любой Keeper обслуживает любой запрос: кластер масштабируется горизонтально и переживает потерю узла без shared-storage.

Soul — агент, которого почти не видно

На управляемом хосте — один статический исполняемый файл на Go. Он получает срендеренный Destiny, сверяет текущее состояние хоста с желаемым и меняет только то, что разошлось. Никакого интерпретатора рядом: core-модули включены в исполняемый файл, кастомные — подключаются как процессы-плагины по gRPC-stdio.

Reconcile — не «выполнить», а «привести к состоянию»

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

Транспорт — один, две модели доставки

Канал Keeper↔Soul — gRPC поверх mTLS. В pull-модели агент-демон держит соединение и применяет Destiny сам. В push-модели тот же исполняемый файл запускается oneshot по SSH — без постоянного агента на хосте. Один набор модулей, одна реализация reconcile.

Данные — горячее и холодное раздельно

PostgreSQL держит долговечное состояние (инкарнации, прогоны, RBAC-снимки). Redis — волатильное и горячее: presence, heartbeat, lease-и, pub/sub. Секреты живут в Vault и резолвятся в момент рендера, маскируясь на выходе. Разделение горячего и холодного — то, что держит цель в 100k+ хостов.

Три слоя: Service → Incarnation → Destiny

ServiceЧто за сервис и из чего он собран — версии, модули, параметры-контракт.
IncarnationКонкретное воплощение сервиса на хостах — то, что провизионится и reconcile-ится.
DestinyЖелаемое состояние хоста: шаги-модули, отрендеренные из Essence в строгом режиме.