Первый сервис на душах
Это руководство — полный проход от git-репозитория сервиса до применённого состояния на нескольких хостах и проверки результата. Quick Start показывал минимальный сервис на одном хосте; здесь та же логика разворачивается на множество душ, привязанных к Coven, и разбирается, что именно происходит на каждом шаге.
Предполагается, что несколько хостов уже в статусе connected (см. Онбординг душ) и JWT первого Архонта лежит в TOKEN.
Что мы соберём
Заголовок раздела «Что мы соберём»Цепочка сущностей, которую пройдём:
flowchart LR
R["git-репо сервиса<br/>scenario/ + essence/"] -->|register| C["каталог сервисов"]
C -->|create incarnation| S["scenario create"]
S --> H["применяется на хостах coven, по covens"]
H --> P["incarnation.state в Postgres"]
- Service — тип сервиса: git-репозиторий со сценариями (
scenario/), дефолтными параметрами (essence/) и манифестом. Регистрируется в каталоге какgit-источник +ref. - Incarnation — runtime-инстанс сервиса: конкретное развёртывание, привязанное к набору хостов. Создание инкарнации запускает сценарий
create. - Scenario — операция над инкарнацией (
create,restart, …).createприводит хосты в начальное состояние.
Шаг 1. Подготовить репозиторий сервиса
Заголовок раздела «Шаг 1. Подготовить репозиторий сервиса»Сервис — это обычный git-репозиторий с такой раскладкой:
my-service/├── service.yml # манифест сервиса (state_schema, метаданные)├── essence/│ └── _default.yaml # дефолтные параметры (Essence)└── scenario/ └── create/ └── main.yml # сценарий первичного развёртыванияМинимальный scenario/create/main.yml ставит пакет и кладёт файл на каждый хост инкарнации. Без оркестрационной дельты (on: / serial: / where:) сценарий применяется ко всем хостам инкарнации одновременно:
input: banner_text: type: string default: "Managed by Soul Stack"
state_changes: sets: banner: "${ input.banner_text }"
tasks: - name: Install htop package module: core.pkg.installed params: name: htop
- name: Write managed banner to motd module: core.file.present params: path: /etc/motd content: "${ input.banner_text }\n" mode: "0644"Шаги — это желаемое состояние (core.pkg.installed = «пакет установлен», core.file.present = «файл с таким содержимым существует»), а не императивные команды. Каждый шаг идемпотентен: повторный прогон ничего не меняет, если состояние уже достигнуто. Грамматика задач — DSL → Destiny, оркестрационная дельта — DSL → Scenario.
Закоммитьте и запушьте репозиторий, запомните ref (тег или ветку), на который будете ссылаться, — версия сервиса в Soul Stack задаётся git-ref-ом, а не полем в манифесте.
Шаг 2. Зарегистрировать сервис
Заголовок раздела «Шаг 2. Зарегистрировать сервис»Чтобы Keeper мог резолвить сервис, он должен быть в каталоге сервисов. Каталог живёт в Postgres и наполняется через Operator API — git-источник + ref:
curl -s -X POST http://keeper.example.com:8080/v1/services \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "my-service", "git": "https://git.example.com/svc/my-service.git", "ref": "v1.0.0" }'ref — стабильный тег (v1.0.0) для прода или ветка (main) для разработки. Keeper материализует репозиторий по этому ref-у при резолве.
Шаг 3. Создать incarnation на coven
Заголовок раздела «Шаг 3. Создать incarnation на coven»Создание инкарнации запускает сценарий create на хостах. Привяжем инкарнацию к Coven prod — она раскатается на все хосты с этой меткой:
curl -s -X POST http://keeper.example.com:8080/v1/incarnations \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "my-service-prod", "service": "my-service", "covens": ["prod"], "input": { "banner_text": "Managed by Soul Stack — prod" } }'Ответ — 202 Accepted с apply_id: операция асинхронная. Keeper резолвит сервис по ref-у, разворачивает сценарий create и применяет его на всех prod-хостах.
Поле covens определяет множество хостов инкарнации. Если в сценарии create шаги не сужают таргет (нет on: / where:), они выполняются на всех этих хостах. Сужение и порядок раскатки — тема Оркестрации.
Шаг 4. Дождаться статуса ready
Заголовок раздела «Шаг 4. Дождаться статуса ready»Опросить статус инкарнации (applying → ready при успехе, error_locked при провале):
curl -s http://keeper.example.com:8080/v1/incarnations/my-service-prod \ -H "Authorization: Bearer $TOKEN"История прогонов (snapshots состояния с результатами по хостам):
curl -s http://keeper.example.com:8080/v1/incarnations/my-service-prod/history \ -H "Authorization: Bearer $TOKEN"В истории видно, на каких хостах прогон прошёл и где что изменилось (changed). Тот же прогон визуально доступен в web-UI (/ui) и через soulctl (soulctl).
Шаг 5. Проверить результат на хостах
Заголовок раздела «Шаг 5. Проверить результат на хостах»При status: ready зафиксированное состояние доступно в incarnation.state (поле banner из state_changes). Проверьте факт прямо на хостах — например, на host-01.example.com:
which htop && cat /etc/motd# → /usr/bin/htop# → Managed by Soul Stack — prodТо же самое на остальных prod-хостах: сценарий create применился ко всему множеству, заданному covens.
Что дальше: повторное применение и эволюция
Заголовок раздела «Что дальше: повторное применение и эволюция»- Повторный прогон того же сценария идемпотентен: уже достигнутое состояние не меняется, изменения происходят только там, где реальное состояние разошлось с желаемым.
- Новые операции над инкарнацией (рестарт, добавление пользователя, обновление конфига) — это другие сценарии в том же сервисе (
scenario/restart/,scenario/add_user/, …), запускаемые как прогоны над существующей инкарнацией. - Новая версия сервиса — это новый
ref. Обновление инкарнации на него и миграцииincarnation.state— отдельная оператор-инициируемая операция (см. Операции → Обновление инкарнации).
Что дальше
Заголовок раздела «Что дальше»- Оркестрация сценарием — управлять порядком раскатки: rolling, run_once, таргетинг по фактам.
- DSL → Scenario — оркестрационная дельта,
state_changes, передача данных между хостами. - DSL → Essence — откуда берутся параметры и как их переопределять.
- Мониторинг из коробки — наблюдать за хостами после раскатки.