Files
orchestrator/docs/architecture/adr/adr-0010-post-deploy-monitor.md

7.1 KiB
Raw Blame History

adr-0010: Post-deploy мониторинг прода + реакция на деградацию

  • Статус: proposed (design) — реализация в ветке feature/ORCH-021-post-deploy-rollback
  • Дата: 2026-06-07
  • Задача: ORCH-021
  • Метка: arch:major-change (новая под-компонента + новый reserved-agent job-kind)
  • Детальный ADR: docs/work-items/ORCH-021/06-adr/ADR-001-post-deploy-monitor.md

Контекст

Конвейер заканчивается на deploy → done: check_deploy_status видит deploy_status: SUCCESS → terminal-sync (Plane → Done, release merge-lease), и оркестратор забывает про прод. «Успех» сегодня = health-check в момент рестарта (~60с окно в orchestrator-deploy-hook.sh). Класс инцидентов «зелёный деплой, красный прод» (прецедент ET-8): деградация проявляется через минуты под боевым трафиком, health отвечает 200 ok, фича сломана. Для self-hosting опасно вдвойне — сломанный прод-орк (8500) обслуживает ВСЕ проекты из общего инстанса.

Решение

Продлить ответственность конвейера ЗА done: после терминального перехода для применимого репо армится пост-деплой наблюдение окна post_deploy_window_s (дефолт ~15 мин) с интервалом post_deploy_interval_s; деградация фиксируется по детерминированным порогам, при подтверждении выполняется реакция.

Механизм — reserved-agent job post-deploy-monitor (калька deploy-finalizer, ORCH-36), НЕ отдельная стадия и НЕ daemon-поток:

  • Арм: в stage_engine.advance_stage, в блоке next_stage == "done", при post_deploy.post_deploy_applies(repo)post_deploy.arm_monitor(...) (sentinel armed = идемпотентность, первый job через enqueue_job(available_at_delay_s=...)).
  • Тик: launcher.launch_job перехватывает agent == "post-deploy-monitor" ДО _spawnstage_engine.run_post_deploy_monitor(job): один опрос сигналов, append в персистентный series, классификация; HEALTHY и окно не истекло → перепостановка с задержкой; иначе → реакция + артефакт + mark_done.
  • Чистая логика — новый leaf-модуль src/post_deploy.py (never-raise, по образцу self_deploy.py/staging_verdict.py): post_deploy_applies, probe_signals (опрос /health + доля 5xx на /status,/queue), classify (HEALTHY|DEGRADED — главный предмет юнит-тестов), decide_action (NONE|ROLLBACK|ALERT_ONLY с учётом self-hosting), sentinel-state хелперы, write_post_deploy_log.

Сигналы и пороги (детерминированно, AC-3…AC-6): DEGRADED≥ post_deploy_fail_threshold ПОСЛЕДОВАТЕЛЬНЫХ провалов health ИЛИ доля 5xx на окне > post_deploy_5xx_threshold. Одиночный глюк < порога → HEALTHY (нет ложных откатов).

Реакция (BR-4/BR-5):

  • Self-hosting (orchestrator) — ВСЕГДА ALERT_ONLY: громкий Telegram + Plane, запрос ручного approve отката. Тик НИКОГДА не откатывает/рестартит прод-контейнер (структурный инвариант). Откат прод-орка, если оператор решит, — только detached host-процесс (self_deploy.initiate_deploy), вне тика (MVP).
  • Не-self + post_deploy_auto_rollback=True: хук --rollback с прод-env; exit 0 → ROLLBACK_OK, 1/2 → ROLLBACK_FAILED + громкий алерт.
  • Дефолт (auto_rollback=False) → ALERT_ONLY.

Артефакт 16-post-deploy-log.md (новый) с YAML-frontmatter (post_deploy_status, action_taken, window_s, checks_total/failed) — машиночитаемо для петли уроков ORCH-8; best-effort. Наблюдаемость — блок post_deploy в GET /queue (образец reconcile.status()).

Альтернативы

  • Daemon-watchdog (как reconciler) — отклонён: per-task серия опросов в памяти не restart-safe (а деплой орка = рестарт); restart-safe-вариант требует тех же sentinel, reserved-agent проще и уже имеет проверенную jobs+sentinel машинерию.
  • Отдельная пост-deploy стадия + QG — отклонён: меняет STAGE_TRANSITIONS/ QG_CHECKS, ломает семантику терминального done; наблюдение принципиально ПОСЛЕ done.
  • Авто-rollback прод-орка из тика — отклонён (self-hosting safety): групповой риск; контейнер не откатит себя надёжно. Self → alert + ручной approve (как ORCH-54).
  • Колонка в tasks — отклонён: миграция на проде; sentinel-файлы restart-safe (как ORCH-36/53/58).

Последствия

  • Класс «зелёный деплой, красный прод» закрыт измеримыми порогами; деградация = сигнал для ORCH-8.
  • Реестры (STAGE_TRANSITIONS/QG_CHECKS), контракт check_deploy_status, terminal-sync, merge-gate, exit-code-контракт хука, схема БД — не меняются.
  • Дефолты безопасны: kill-switch on, auto-rollback off, self только alert.
  • Ограничение: монитор self бежит внутри наблюдаемого прода — полностью wedged контейнер = пропущенный тик/алерт (known MVP gap; внешний watchdog — follow-up).
  • Self-hosting: тик не рестартит/не роняет прод-контейнер; kill-switch post_deploy_monitor_enabled обязателен; поэтапный раскат через post_deploy_repos.

Связи

adr-0007-executable-self-deploy (ORCH-36 — sentinel/detached-host/finalizer образец, map_exit_code_to_status), adr-0007-reconciler (ORCH-53 — daemon/status() образец, отклонён как основной механизм), adr-0006 (merge-gate — условность/флаги раската), adr-0003 (staging-gate — образец условности), adr-0008 (provenance — .deploy-prev-image/ хук-откат). Прецедент ET-8. Будущее: ORCH-8 (петля уроков), ORCH-54 (полный авто).