6.9 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-062 | architecture | architect | proposed | 2026-06-09 | claude-opus-4-8 |
adr-0025: Build-cache-pruner — фоновый heartbeat-демон авто-уборки docker build cache на хосте
Сквозной (cross-cutting) ADR: вводит новый фоновый компонент оркестратора в ряду
reconciler(adr-0007),job_reaper(adr-0011) иdisk_watchdog(adr-0024). Детальное решение задачи —docs/work-items/ORCH-062/06-adr/ADR-001-build-cache-pruner.md.
Статус
Proposed (ORCH-062)
Контекст
07.06.2026 диск хоста mva154 тихо дорос до 100% и положил весь self-hosting-конвейер всех
проектов (один прод-инстанс orchestrator на общей БД/очереди). Доминирующий «пожиратель» —
docker build cache (≈11 ГБ от частых пересборок прод/staging-образов). disk_watchdog
(adr-0024, ORCH-063) ввёл сигнал о заполнении (Telegram ≥85%) и явно отложил авто-очистку в
отдельную задачу. ORCH-062 — эта задача: автоматическое освобождение build cache, чтобы
инцидент не повторялся без оператора.
Сверено по коду: контейнер orchestrator не содержит docker CLI (Dockerfile:11 — только
openssh-client git curl); host-docker-операции приложение уже делает через ssh на хост
(image_freshness.image_revision, self_deploy Phase B), канал deploy_ssh_user@deploy_ssh_host
настроен. У оркестратора три проверенных фоновых daemon-потока с единым каркасом.
Решение
Вводится четвёртый фоновый компонент build-cache-pruner (src/build_cache_pruner.py):
- Калька каркаса
disk_watchdog/reconciler/reaper: daemon-поток, чистый стоп через_stop.wait(interval), контрактstart()/stop(timeout)/status(), старт/стоп вmain.lifespan(старт последним — послеdisk_watchdog.start(); стоп первым в reverse), наблюдаемость — аддитивный блокbuild_cache_pruneвGET /queue. Leaf-модуль (без обратных зависимостей наstage_engine/stages/qg). - Уборка — строго
docker builder prune -f --filter until=<until>(BuildKit GC, дефолтuntil=24h): удаляется только старый build cache, тёплый ≤24ч сохраняется.-a— опционально и только в паре с возрастным фильтром. Запрещеныdocker image prune/system prune/удаление образов запущенных сервисов/остановка-рестарт контейнеров. - Исполнение на хосте через ssh (CLI в контейнере нет):
ssh deploy_ssh_user@deploy_ssh_host "docker builder prune …", bounded таймаутом. Нет ssh-таргета → тик no-op → фича естественно скоупится на self-hosting-прод. - Конфиг/kill-switch (
ORCH_BUILD_CACHE_PRUNE_*, дефолты безопасные):enabled(дефолтtrue),interval_s(6ч),until(24h),all(false),timeout_s,notify_min_gb. Валидаторы по образцуdisk_monitor_*(невалид → лог + дефолт). - Сигнал + лечение как пара: disk_watchdog сигналит о росте диска, build-cache-pruner убирает доминирующего «пожирателя» — две половины одной операционной защиты.
Инварианты: STAGE_TRANSITIONS, реестр QG_CHECKS, check_*, src/stage_engine.py, схема БД
— не меняются (pruner — эксплуатационный демон, не Quality Gate, как watchdog/reaper). Без
миграции БД (учёт результата in-memory, best-effort). never-raise per-команда/per-tick. Уборка
никогда не рестартит docker daemon/прод-контейнер (self-hosting безопасность; рестарт-путь —
отвергнутый Вариант B). При выключенном kill-switch — поведение 1:1 как сейчас (нулевая регрессия
для enduro-trails).
Альтернативы
- host
daemon.json builder.gc.defaultKeepStorage— отвергнуто: требует рестарта docker daemon (останавливает ВСЕ контейнеры хоста = групповой self-hosting риск); политика по объёму, не по возрасту; не наблюдаемо вGET /queue. - host-cron — отвергнуто как основное (оставлено ручным fallback): off-git невидимая инфра,
без
/queue-наблюдаемости, без config-kill-switch, не тестируется. - raw-HTTP по docker.sock / docker CLI в образе — отвергнуто: лишний код / раздувание образа против уже существующего ssh-канала.
Последствия
- + Корень инцидента 07.06 устраняется автоматически; тёплый кэш сохранён; без новых зависимостей и без рестарта docker/прода (принцип «всё в Docker, минимум зависимостей»).
- + Знакомый паттерн фонового демона → низкий риск, наблюдаемость, обратимость, тестируемость.
- − Зависимость от ssh на хост (как
image_freshness/self_deploy); нет таргета → no-op (наблюдаемо), фича не работает, но ничего не ломает. - Откат:
ORCH_BUILD_CACHE_PRUNE_ENABLED=false; миграций БД нет.
Ссылки
- Задачный ADR:
docs/work-items/ORCH-062/06-adr/ADR-001-build-cache-pruner.md - Инфра/риски:
docs/work-items/ORCH-062/07-infra-requirements.md,docs/work-items/ORCH-062/10-tech-risks.md - Комплемент: adr-0024-disk-watchdog.md (ORCH-063 — сигнал)
- Родственные компоненты: adr-0007-reconciler.md, adr-0011-job-reaper-lease-reclaim.md
- Топология host / env-карта:
docs/operations/INFRA.md