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

Quick Start

Этот гайд проводит путь «с нуля до применённого Destiny» примерно за 5 минут: поднять Keeper, создать первого оператора, подключить один агент и применить простой Destiny, который установит пакет и создаст файл на хосте.

Это demo-сценарий для знакомства, не прод-инсталляция. Прод-раскатка (HA, несколько Keeper, managed-инфраструктура, persistent Vault, TLS-материал) — раздел Операции и Установка из пакетов.

КомпонентЗачем
PostgreSQLЕдинственное холодное хранилище Keeper-кластера: реестры агентов и операторов, каталог сервисов, журналы.
RedisHeartbeat-кэш, lease на идентификаторы агентов, координация между инстансами Keeper.
VaultPKI для выпуска mTLS-идентичности агентов и хранение секретов (DSN, пароль Redis, ключ подписи токенов).
Исполняемые файлы keeper, soul, soul-lintСм. Установка.

Все три компонента должны быть доступны по сети с хоста, где работает Keeper.

Keeper слушает несколько listener-ов. Значения ниже — пример из demo-конфига; в проде они настраиваются:

ПортНазначениеПротоколОбязательность
8080Operator API (HTTP), health-check /readyz, web-UI /uiHTTPобязательный
9090Метрики (/metrics, Prometheus scrape/pull)HTTPобязательный listener
8081MCPHTTPопциональный listener
9442gRPC bootstrap (онбординг агента: soul init)server-only TLSобязательный
9443gRPC EventStream (долгоживущий стрим агента: soul run)mTLSобязательный

Агент soul сам инициирует соединение к Keeper-у — на управляемых хостах не нужно открывать входящие порты (наружу слушает только локальный listener метрик).

Поднимите PostgreSQL, Redis и Vault. Keeper читает DSN PostgreSQL, пароль Redis и ключ подписи операторских токенов из Vault, а также выпускает mTLS-сертификаты агентов через Vault PKI. Провижининг сводится к:

  • записать KV-секреты: DSN PostgreSQL, пароль Redis, ключ подписи токенов;
  • включить PKI-engine и завести роль для выпуска сертификатов агентов;
  • выпустить серверный TLS-сертификат Keeper-а из того же PKI-корня.

Подробные команды провижининга Vault (KV, PKI, AppRole, выпуск серверного сертификата) — Установка из пакетов. Требования к версиям, обязательные параметры и режимы PostgreSQL / Redis / Vault (что нужно настроить до запуска Keeper) — Подготовка инфраструктуры.

Локальное знакомство: поднять все три через Docker Compose

Заголовок раздела «Локальное знакомство: поднять все три через Docker Compose»

Для быстрого локального знакомства ставить руками ничего не нужно: один compose.yml поднимает PostgreSQL, Redis и Vault с настройками, согласованными с demo-конфигом keeper.yml ниже (Redis без пароля, Vault в dev-режиме). Сохраните и запустите docker compose up -d:

# compose.yml — инфраструктура для локального знакомства (не для прода)
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: keeper
POSTGRES_PASSWORD: keeper
POSTGRES_DB: keeper
ports: ["127.0.0.1:5432:5432"]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keeper -d keeper"]
interval: 2s
timeout: 3s
retries: 30
redis:
image: redis:7-alpine
ports: ["127.0.0.1:6379:6379"] # без пароля — совпадает с redis.password_ref: "" ниже
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 2s
timeout: 3s
retries: 30
vault:
image: hashicorp/vault:1.18
cap_add: ["IPC_LOCK"]
environment:
VAULT_DEV_ROOT_TOKEN_ID: root # dev-mode root-токен — совпадает с vault.token: root ниже
VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200
ports: ["127.0.0.1:8200:8200"]
healthcheck:
test: ["CMD", "vault", "status", "-address=http://127.0.0.1:8200"]
interval: 2s
timeout: 3s
retries: 30

Это поднимает три сервиса. Теперь провижининг dev-Vault — один KV-секрет плюс PKI, который выпускает TLS-материал (серверный сертификат Keeper-а и CA, который кладут на каждый хост). CLI vault обращается к контейнеру выше:

Окно терминала
export VAULT_ADDR=http://127.0.0.1:8200 VAULT_TOKEN=root
# KV-секрет, который читает demo keeper.yml (postgres.dsn_ref)
vault kv put secret/keeper/postgres dsn="postgres://keeper:keeper@127.0.0.1:5432/keeper"
# PKI: engine → root → роль выпуска
vault secrets enable -path=pki pki
vault secrets tune -max-lease-ttl=87600h pki
vault write pki/root/generate/internal common_name="Soul Stack Demo Root" ttl=87600h
vault write pki/roles/soul-seed allow_any_name=true max_ttl=720h
# Выпустить серверный серт Keeper-а из того же корня (к нему цепляются агенты)
vault write -format=json pki/issue/soul-seed \
common_name=127.0.0.1 alt_names=localhost ip_sans=127.0.0.1 ttl=720h > keeper-issue.json
jq -r .data.certificate keeper-issue.json > keeper.crt
jq -r .data.private_key keeper-issue.json > keeper.key
jq -r .data.issuing_ca keeper-issue.json > pki-ca.crt

keeper.crt / keeper.key / pki-ca.crt — ровно те три файла, на которые ссылается demo keeper.yml ниже. pki-ca.crt — это CA: скопируйте его на каждый хост (soul.yml → keeper.tls.ca), чтобы агент мог проверить Keeper на bootstrap-фазе (шаг 4.2).

Заполните конфиг Keeper-а (адреса PostgreSQL/Redis/Vault через vault:-ref-ы, listener-ы, пути к TLS-материалу) и запустите исполняемый файл. Минимальный demo-конфиг — как и весь этот гайд, только для знакомства:

# keeper.yml — минимальный demo-конфиг
kid: keeper-demo-01
listen:
grpc:
bootstrap: # онбординг агента (server-only TLS)
addr: "127.0.0.1:9442"
tls:
cert: /etc/keeper/tls/keeper.crt
key: /etc/keeper/tls/keeper.key
event_stream: # долгоживущий стрим агента (mTLS)
addr: "127.0.0.1:9443"
tls:
cert: /etc/keeper/tls/keeper.crt
key: /etc/keeper/tls/keeper.key
ca: /etc/keeper/tls/pki-ca.crt # тот же PKI-корень, что у сертификатов агентов
openapi: { addr: "127.0.0.1:8080" } # Operator API + /readyz + /ui
metrics: { addr: "127.0.0.1:9090" } # Prometheus scrape
mcp: { addr: "127.0.0.1:8081" } # опционально; уберите блок — MCP выключен
postgres:
dsn_ref: vault:secret/keeper/postgres # читает поле dsn из Vault KV
redis:
addr: "127.0.0.1:6379"
password_ref: "" # пусто = Redis без пароля (demo)
vault:
addr: "http://127.0.0.1:8200"
token: "root" # dev-mode root-токен; в проде — AppRole
pki_mount: "pki" # PKI engine для выпуска mTLS-идентичности агентов
pki_role: "soul-seed"

Секреты (DSN PostgreSQL, пароль Redis) в конфиге не лежат — они подтягиваются из Vault vault:-ref-ами (postgres.dsn_ref, redis.password_ref). vault.token: root — dev-shortcut для Vault в dev-режиме; в проде Keeper аутентифицируется в Vault через AppRole (см. Установку из пакетов). Прочие блоки (auth / otel / logging / reaper / …) опущены — у них рабочие дефолты.

Проверьте готовность:

Окно терминала
curl -fsS http://127.0.0.1:8080/readyz && echo OK

/readyz отвечает 200, когда инстанс готов принимать трафик (доступны PostgreSQL и Redis).

Оператор Soul Stack называется Archon (Архонт), его идентификатор — AID. AID — это любая строка по паттерну ^[a-z0-9][a-z0-9._@-]{1,127}$: начинается с буквы или цифры, дальше допускаются a-z0-9 и символы ._@-, общая длина 2–128 символов. Подходят, например, archon-alice, alice@corp.com, uid-4815, ops-team. Первый Архонт создаётся административной подкомандой самого исполняемого файла keeper — она под блокировкой проверяет, что реестр операторов пуст, создаёт первого Архонта с ролью cluster-admin и выпускает для него JWT:

Окно терминала
keeper init \
--archon=archon-alice \
--config=/etc/keeper/keeper.yml \
--credential-out=/etc/keeper/archon-alice.jwt

--archon=alice@corp.com или --archon=ops-team — тоже валидны: подходит любой AID по паттерну выше.

JWT пишется в файл --credential-out с правами 0400. Сохраните токен в переменную для следующих шагов:

Окно терминала
TOKEN=$(cat /etc/keeper/archon-alice.jwt)

Смотреть API в браузере удобно через GET /docs — встроенный вьювер OpenAPI-спеки. Откройте http://127.0.0.1:8080/docs, вставьте JWT в поле ввода — страница подгрузит полную спеку с поиском по эндпоинтам и кнопкой «Try It».

Soul — агент на управляемом хосте. Идентификатор агента (SID) равен FQDN хоста. Онбординг идёт через CSR: приватный ключ генерируется на хосте и никогда его не покидает. Поток в два хода — оператор регистрирует хост и получает одноразовый bootstrap-токен, затем soul init на хосте обменивает токен на mTLS-идентичность (SoulSeed).

На стороне Keeper-а (через Operator API):

Окно терминала
curl -s -X POST http://keeper.example.com:8080/v1/souls \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"sid": "host-01.example.com", "transport": "agent", "covens": ["demo"]}'

В ответе — bootstrap_token (возвращается один раз, TTL по умолчанию 24 часа). Запись агента появляется в статусе pending. Метка covens: ["demo"] — стабильный тег хоста, по которому позже таргетируются сценарии. Потерянный токен не восстановить — только перевыпустить через POST /v1/souls/{sid}/issue-token.

Перед soul init положите на хост PKI-корень (тот же CA, что и серверный сертификат Keeper-а) по пути из конфига soul.yml (keeper.tls.ca) — этим файлом агент проверяет серверный сертификат Keeper-а на bootstrap-фазе.

Минимальный soul.yml:

sid: host-01.example.com
paths:
modules: /var/lib/soul-stack/modules
seed: /var/lib/soul-stack/seed
keeper:
endpoints:
- host: keeper.example.com
bootstrap_port: 9442 # server-only TLS, фаза `soul init`
event_stream_port: 9443 # mTLS, фаза `soul run`
priority: 1
tls:
ca: /var/lib/soul-stack/seed/ca.crt

soul init генерирует приватный ключ и CSR, подключается к bootstrap-listener-у Keeper-а и раскладывает полученный SoulSeed. Bootstrap-токен из 4.1 передаётся одним из двух способов:

  • флагом --token=<bootstrap_token>;
  • переменной окружения SOUL_BOOTSTRAP_TOKEN (флаг имеет приоритет над переменной).

Эквивалент через флаг (удобно для разовой ручной отладки):

Окно терминала
soul init --token='<bootstrap_token из 4.1>' --config /etc/soul/soul.yml

При успехе запись агента переходит pending → connected после запуска демона. Запустите демон (держит EventStream к Keeper-у по mTLS):

Окно терминала
soul run --config /etc/soul/soul.yml

Проверьте, что хост виден как connected:

Окно терминала
curl -s http://keeper.example.com:8080/v1/souls/host-01.example.com \
-H "Authorization: Bearer $TOKEN"
# в ответе status: connected

Состояние, которое вы применяете, лежит в репозитории сервиса — обычном git-репо. Именно отсюда берётся сервис demo, который регистрируется ниже: вы пишете его и пушите в git. Для этого гайда — однострочный манифест плюс единственный сценарий create, который ставит пакет и кладёт файл. Минимальная раскладка:

demo-service/
├── service.yml # манифест: имя + версия схемы состояния
└── scenario/
└── create/
└── main.yml # операция create (запускается при создании инкарнации)

service.yml — манифест. Версия сервиса — это git-ref (ADR-007), поэтому поля version: здесь нет:

service.yml
name: demo
state_schema_version: 1 # на v1 каталог migrations/ не нужен

scenario/create/main.yml — сценарий create. Без orchestration-дельты (on: / serial: / where:) его шаги выполняются на всех хостах инкарнации. Каждый шаг — желаемое состояние вида core.<module>.<state>: core.pkg.installed = «пакет установлен», core.file.present = «файл с таким содержимым существует» — не императивная команда, и каждый шаг идемпотентен:

scenario/create/main.yml
input:
banner_text:
type: string
default: "Managed by Soul Stack"
state_changes:
sets:
banner: "${ input.banner_text }"
tasks:
- name: Install the htop package
module: core.pkg.installed
params:
name: htop
- name: Write the managed banner to motd
module: core.file.present
params:
path: /etc/motd
content: "${ input.banner_text }\n"
mode: "0644"

Грамматика задач (control-блоки, register:, requisites) — в DSL → Destiny; orchestration-дельта — в DSL → Scenario.

Закоммитьте и запушьте репо, запомнив ref (тег или ветку), на который будете ссылаться. Затем зарегистрируйте сервис в каталоге Keeper-а (git-источник + ref):

Окно терминала
curl -s -X POST http://keeper.example.com:8080/v1/services \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "demo", "git": "https://git.example.com/svc/demo.git", "ref": "main"}'

Создать incarnation — runtime-инстанс сервиса; это запускает сценарий create на хостах. Привяжем к метке demo (там наш агент из шага 4):

Окно терминала
curl -s -X POST http://keeper.example.com:8080/v1/incarnations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "demo-app",
"service": "demo",
"covens": ["demo"]
}'

Ответ — 202 Accepted с apply_id: операция асинхронная.

Опросить статус incarnation (applyingready при успехе, error_locked при провале):

Окно терминала
curl -s http://keeper.example.com:8080/v1/incarnations/demo-app \
-H "Authorization: Bearer $TOKEN"

При status: ready проверьте на хосте, что состояние применилось:

Окно терминала
which htop && cat /etc/motd

История прогонов (snapshots состояния):

Окно терминала
curl -s http://keeper.example.com:8080/v1/incarnations/demo-app/history \
-H "Authorization: Bearer $TOKEN"
  • Концепции — словарь и ментальная модель: что именно применяется к хосту.
  • DSL — как писать собственные Destiny и сценарии.
  • Модули — каталог встроенных core-модулей.
  • Операции — день второй: обновления, мониторинг, восстановление.