Эксплуатация
Эксплуатация Soul Stack после первого запуска: мониторинг, масштабирование, обновления, миграции состояния, бэкап и восстановление, типовой troubleshooting.
Базовая модель проста: Keeper-инстансы — stateless и stand за L4-балансировщиком, всё авторитетное состояние лежит в PostgreSQL, горячий слой и координация — в Redis. Большинство эксплуатационных операций сводится к манипуляциям с инстансами Keeper-а и обслуживанию этих двух внешних хранилищ.
Мониторинг
Заголовок раздела «Мониторинг»Телеметрия идёт по трём каналам:
| Канал | Что несёт | Как забирать |
|---|---|---|
Prometheus /metrics | счётчики, gauge, гистограммы Keeper и агентов | scrape (pull): Keeper — порт :9090, агент — metrics.listen (по умолчанию loopback 127.0.0.1:9091) |
| OpenTelemetry | сквозные трейсы (оператор → Keeper → агент) | push: Keeper и агент сами отправляют OTLP по gRPC на otel.endpoint |
| Логи | структурированный JSON | stdout/файл (systemd journal), встроенная ротация |
Важная асимметрия: метрики работают по модели pull (Prometheus сам ходит на /metrics), а OpenTelemetry — по модели push (Keeper сам отправляет трейсы в коллектор; входящего OTel-порта у него нет).
Защита /metrics
Заголовок раздела «Защита /metrics»- Keeper —
/metricsобслуживается на отдельном порту без auth-цепочки Operator API. Опционально — HTTP Basic-auth (metrics.auth.basic, пароль из Vault), см. keeper.yml → metrics. - Агент — по умолчанию bind на loopback, наружу не торчит. При внешнем scrape — bind на интерфейс + Basic-auth с паролем из файла, см. soul.yml → metrics.
Ключевые сигналы
Заголовок раздела «Ключевые сигналы»Метрики Keeper-а имеют префикс keeper_, агента — soul_. На что смотреть в первую очередь:
| Сигнал | Метрика (ориентир) | О чём говорит |
|---|---|---|
| Доступность инстанса | up{job="keeper"} | инстанс не отвечает — investigate через логи |
| Подключённые агенты | keeper_grpc_streams_active | падение ниже ожидаемого числа — часть душ отвалилась |
| Фоновая чистка | gauge лидерства Reaper-а (sum по кластеру = 1) | ноль — чистка БД остановлена, таблицы будут расти; больше единицы — аномалия координации (перезагрузить Redis) |
| Планировщик расписаний | gauge лидерства планировщика (sum = 1, если включён) | ноль при включённом планировщике — регулярные запуски не порождаются |
| Доля провальных прогонов | rate провальных / всех scenario-прогонов | рост выше нормы — investigate сценарий или хосты |
| Латентность Vault | гистограмма чтения Vault | рост — Vault отвечает медленно, новые операции замедляются |
Доменные идентификаторы (id прогона, sid, имя сценария) живут в трейсах, а не в метках метрик — это сознательно, чтобы не раздувать кардинальность Prometheus. Конкретного виновника ищите по трейсам и логам (по correlation-id и id прогона).
Масштабирование
Заголовок раздела «Масштабирование»Keeper-инстансы stateless: всё авторитетное состояние — в общей PostgreSQL, presence и координация — в общем Redis. Поэтому масштабирование горизонтальное:
flowchart TB
A["агенты"] --> LB["L4-балансировщик"]
LB --> K1["keeper-1"]
LB --> K2["keeper-2"]
LB --> K3["keeper-N"]
K1 --> D[("PostgreSQL + Redis — общие")]
K2 --> D
K3 --> D
- Любой инстанс обслуживает любой запрос оператора и любой стрим агента.
- Добавление мощности = запуск ещё одного инстанса на тот же PostgreSQL + Redis за тем же балансировщиком. Репликации состояния между инстансами нет.
- Для health-probe балансировщику достаточно TCP-проверки порта EventStream; у Keeper-а также есть HTTP
/readyz. - Каждый инстанс имеет уникальный в пределах кластера
kid.
Требования к хранилищам. Суммарный поток подключений к PostgreSQL примерно равен postgres.pool.max × число инстансов — закладывайте это в max_connections PostgreSQL. Redis должен выдерживать presence/heartbeat всех душ; для крупных инсталляций используйте кластерную топологию Redis.
Обновление без downtime
Заголовок раздела «Обновление без downtime»Кластер из нескольких инстансов обновляется rolling-способом, по одному инстансу:
- Снимите бэкап PostgreSQL (см. ниже) и сверьтесь с changelog обновляемой версии.
- Выведите первый инстанс из активного backend балансировщика.
- Установите новую версию и перезапустите инстанс. При остановке инстанс gracefully закрывает стримы — агенты по своему fallback-list-у уходят на оставшиеся инстансы. При старте новой версии применяются миграции схемы БД (если есть).
- Дождитесь готовности (
/readyz→ 200, число активных стримов растёт по мере возврата агентов), верните инстанс в балансировщик. - Выдержите паузу, чтобы агенты перераспределились, и переходите к следующему инстансу.
Совместимость. Контракт Keeper↔агент — forward-compatible (только добавление полей, без удаления и переиспользования). Новый Keeper понимает старого агента и наоборот, поэтому в окне обновления версии Keeper и агентов могут сосуществовать. Breaking-изменения выносятся в новую версию контракта.
Откат. Если новая версия не стартует — оставшиеся инстансы продолжают обслуживать. Откатите пакет на предыдущую версию и перезапустите инстанс, затем разбирайтесь с проблемной версией отдельно. Поскольку миграции состояния — forward-only, после применившейся миграции схемы откат версии может потребовать восстановления из бэкапа — отсюда правило «бэкап до обновления».
Обновление агентов идёт независимо от Keeper-а и не требует одновременности (forward-compat контракта). Раскатывайте новую версию soul своей системой доставки пакетов; в pull-режиме агент сам переподключится после перезапуска сервиса.
Обновление инкарнации (миграции состояния)
Заголовок раздела «Обновление инкарнации (миграции состояния)»Состояние инкарнации (runtime-инстанса сервиса) версионируется. Переход на новую версию схемы — явный шаг оператора, а не автоматическое «ленивое» обновление:
- Оператор инициирует upgrade инкарнации до целевой версии через Operator API.
- Цепочка миграций применяется атомарно, одной транзакцией PostgreSQL: либо состояние полностью переходит на новую версию, либо остаётся прежним при ошибке.
- Перед изменением сохраняется snapshot прежнего состояния в историю — это путь отката (миграции forward-only, обратной миграции нет).
Миграция — это чистая функция «старое состояние → новое состояние» без побочных эффектов на хостах. Грамматика DSL, раскладка файлов migrations/ и тесты миграций — в справочнике DSL → Миграции состояния.
Бэкап и восстановление
Заголовок раздела «Бэкап и восстановление»PostgreSQL — единственное холодное хранилище состояния кластера: реестры агентов и операторов, каталог сервисов, состояния инкарнаций, журналы. Поэтому:
- Бэкап = бэкап PostgreSQL. Используйте штатные средства резервного копирования вашей PostgreSQL (логический дамп или непрерывное архивирование WAL для point-in-time recovery). Снимайте бэкап перед каждым обновлением.
- Redis бэкапить не нужно для восстановления состояния — там только горячие, эфемерные данные (presence, lease, кэш). После потери Redis инстансы перезаполнят его сами; на время недоступности Redis деградируют функции, опирающиеся на координацию (выбор лидеров, presence), но авторитетное состояние не теряется.
- Vault обслуживается и резервируется по собственному регламенту вашей инсталляции Vault.
Восстановление. Поднимите PostgreSQL из бэкапа, убедитесь в доступности Redis и Vault, запустите инстансы Keeper-а — они подхватят состояние из БД. Агенты переподключатся по своим fallback-list-ам. Если прогон «завис» из-за внезапной потери инстанса-владельца, есть штатный механизм реклейма зависших прогонов — см. troubleshooting ниже.
RBAC и операторы
Заголовок раздела «RBAC и операторы»Каталог ролей и реестр операторов живут в PostgreSQL и управляются через Operator API (не через конфиг-файл):
- первый оператор создаётся административной подкомандой
keeper initпри первичной настройке кластера; - дальнейшие операторы и роли заводятся через API авторизованным оператором;
- отзыв оператора действует почти мгновенно: при ревокации все инстансы кластера пересобирают RBAC-снимок, и следующий же запрос отозванного оператора отклоняется (
401) — единицы миллисекунд при здоровом Redis, не дольше интервала обновления снимка (по умолчанию ~10 секунд) при потере сигнала. Ограниченный TTL токена (auth.jwt.ttl_default) остаётся дополнительным рубежом защиты, а не основным.
Подробнее о bootstrap первого оператора — Установка из пакетов.
Troubleshooting
Заголовок раздела «Troubleshooting»Развёрнутый разбор типовых ситуаций по схеме «симптом → причина → проверка/решение» — в отдельном разделе Решение проблем: агент не переходит в connected, инкарнация в error_locked, истёкший bootstrap-токен, ошибки рендера/шаблонов, недоступный Vault/PKI, mTLS не сходится, отказ доступа.
Краткая шпаргалка «куда смотреть»:
| Симптом | Вероятная причина | Что проверить |
|---|---|---|
Агент не в статусе connected | сбой подключения / просроченная идентичность / упавший сервис | логи агента (bootstrap, mTLS, verify); сетевую доступность bootstrap- и EventStream-портов Keeper-а; статус systemd-сервиса soul |
Прогон долго в статусе applying | инстанс-владелец прогона недоступен (актуально при нескольких инстансах и выключенном воркер-пуле) | включён ли acolytes > 0; число живых инстансов; механизм реклейма зависших прогонов |
Инкарнация в статусе error_locked | прогон завершился ошибкой, изменения не закоммичены в БД | отчёт о прогоне и логи; устранить причину и повторить прогон (unlock + повтор — операции Operator API) |
| Доступ запрещён (403) | у оператора нет нужного permission / истёк токен | роль оператора и его permissions; срок действия токена |
| Сбой резолва секрета на старте | Vault недоступен или путь/ключ неверны | доступность Vault; корректность vault:-ref-ов в keeper.yml; наличие нужных полей в Vault KV |
| Hot-reload не применился | ошибка валидации нового конфига / поле требует перезапуска | логи на предмет события неудачного reload; таблицу «reload-able / restart-required» в keeper.yml → Hot-reload |
Логи структурированы (JSON по умолчанию) и несут kid/sid, id прогона и trace-id — этого достаточно, чтобы связать запись в логах с трейсом и сетевым событием.
См. также
Заголовок раздела «См. также»- Решение проблем — развёрнутый troubleshooting по схеме «симптом → причина → решение».
- Конфигурация → keeper.yml — параметры Keeper-а, включая HA-инвариант и hot-reload.
- Конфигурация → soul.yml — параметры агента.
- Компоненты → Keeper — порты, HA, первичный интерфейс оператора.
- Установка — внешняя инфраструктура (PostgreSQL/Redis/Vault), способы установки.