feat(deploy): prod OOM swap cushion + edge maintenance page #170

Merged
developer merged 2 commits from feature/prod-hardening into development 2026-07-03 20:28:29 +00:00
Owner

Что

Две меры укрепления прод-деплоя (по твоему запросу; алерты не трогаю — они уже throttled).

1. Swap-подушка от OOM (ansible common, swap_size=1G, vm.swappiness=10). Per-container кэпы (проверено: compose v2 применяет deploy.limits → cgroup) не дают одному сервису съесть весь RAM, но сумма кэпов (~2.8 GiB) оверкоммитит хост 1.9 GiB — при одновременном спайке возможен kernel-OOM (жертва может быть postgres). Swap впитывает перегруз. Идемпотентно, builtin-only. Применяется твоим прогоном ansible-playbook (не деплоем).

2. Maintenance-гейт в caddy. prod-deploy.sh поднимает флаг на время перекатки/миграции → edge caddy отдаёт статичную 503 «технические работы» (deploy/caddy/maintenance.html) на user-facing путях; /_gm (Grafana) остаётся доступен. Флаг снимается trap-ом на любом выходе (успех / health-fail+откат / ошибка) — залипнуть не может. 503 несёт Retry-After + маркер X-Scrabble-Maintenance: 1 (для будущего оверлея в SPA). Не zero-downtime (одиночный stateful backend всё равно блипает), но окно грациозное.

Проверено (evidence)

  • caddy validate: Valid. Сырой nc-запрос при флаге ON: 503 + страница (1858 б) + Retry-After:120 + X-Scrabble-Maintenance:1; все non-/_gm пути (вкл. Connect/gRPC edge /scrabble.edge.v1.Gateway/*) → 503; /_gm → 200 (минует); тоггл флага без релоуда (per-request stat).
  • ansible-playbook --syntax-check (core 2.19.4) прошёл; docker compose config (base+prod) VALID, /srv/maint смонтирован ro.

Дальше

  • Оверлей в приложении (in-session юзер статичную страницу не видит) — отдельным UI-PR после (с брейнштормом дизайна + ревью на контуре). Заголовок-детект уже здесь.
  • Swap на прод-хостах — твой ansible-playbook прогон.
## Что Две меры укрепления прод-деплоя (по твоему запросу; алерты не трогаю — они уже throttled). **1. Swap-подушка от OOM** (ansible `common`, `swap_size=1G`, `vm.swappiness=10`). Per-container кэпы (проверено: compose v2 применяет `deploy.limits` → cgroup) не дают одному сервису съесть весь RAM, но сумма кэпов (~2.8 GiB) оверкоммитит хост 1.9 GiB — при одновременном спайке возможен kernel-OOM (жертва может быть postgres). Swap впитывает перегруз. Идемпотентно, builtin-only. **Применяется твоим прогоном `ansible-playbook`** (не деплоем). **2. Maintenance-гейт в caddy.** `prod-deploy.sh` поднимает флаг на время перекатки/миграции → edge caddy отдаёт статичную 503 «технические работы» (`deploy/caddy/maintenance.html`) на user-facing путях; `/_gm` (Grafana) остаётся доступен. Флаг снимается trap-ом на любом выходе (успех / health-fail+откат / ошибка) — залипнуть не может. 503 несёт `Retry-After` + маркер `X-Scrabble-Maintenance: 1` (для будущего оверлея в SPA). Не zero-downtime (одиночный stateful backend всё равно блипает), но окно грациозное. ## Проверено (evidence) - `caddy validate`: Valid. Сырой nc-запрос при флаге ON: **503 + страница (1858 б) + Retry-After:120 + X-Scrabble-Maintenance:1**; все non-/_gm пути (вкл. Connect/gRPC edge `/scrabble.edge.v1.Gateway/*`) → 503; `/_gm` → 200 (минует); тоггл флага без релоуда (per-request stat). - `ansible-playbook --syntax-check` (core 2.19.4) прошёл; `docker compose config` (base+prod) VALID, `/srv/maint` смонтирован ro. ## Дальше - Оверлей в приложении (in-session юзер статичную страницу не видит) — **отдельным UI-PR** после (с брейнштормом дизайна + ревью на контуре). Заголовок-детект уже здесь. - Swap на прод-хостах — твой `ansible-playbook` прогон.
developer added 1 commit 2026-07-03 20:10:10 +00:00
feat(deploy): prod OOM swap cushion + edge maintenance page
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 18s
CI / ui (pull_request) Successful in 1m5s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m39s
c8601c0115
Two prod-deploy hardening measures (owner-requested):

- Swap file (Ansible common role, swap_size=1G, vm.swappiness=10). The per-container
  memory caps enforce that one service can't eat all RAM, but they overcommit the
  1.9 GiB main host (~2.8 GiB of caps), so a simultaneous spike could hit the kernel
  OOM-killer (and it might pick postgres). A small swap absorbs the overshoot.
  Idempotent, builtin-only (no ansible.posix).

- Edge maintenance page. prod-deploy.sh raises a flag around the rolling swap /
  migration window that the caddy edge serves a static 503 "технические работы" page
  from (deploy/caddy/maintenance.html), for the user-facing routes only — /_gm
  (Grafana) stays reachable. Cleared on any exit (success, health failure + rollback,
  or error) by a shell trap so it can never stick on. The 503 carries Retry-After +
  an X-Scrabble-Maintenance marker so a follow-up SPA overlay can tell a planned
  window apart from a transient error (the static page only catches a fresh load; an
  in-session user needs the app-side overlay). Not zero-downtime — the single
  stateful backend still blips — but the window is graceful instead of raw 502s.

Verified: caddy validate; the gate 503s every non-/_gm path incl. the Connect/gRPC
edge and serves the page + markers; /_gm bypasses; toggling needs no reload
(per-request stat). Ansible --syntax-check + compose config (base+prod) pass.
owner approved these changes 2026-07-03 20:13:30 +00:00
Dismissed
developer added 1 commit 2026-07-03 20:17:31 +00:00
Merge remote-tracking branch 'origin/development' into feature/prod-hardening
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 1m4s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m40s
597e200f37
developer dismissed owner's review 2026-07-03 20:17:32 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

owner approved these changes 2026-07-03 20:28:09 +00:00
developer merged commit 75fe07865a into development 2026-07-03 20:28:29 +00:00
developer deleted branch feature/prod-hardening 2026-07-03 20:28:29 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#170