- close [resilience-roadmap-design] 🟢 — roadmap expanded via interactive workshop with user (per-service RTO/RPO matrix for 10 services, CMS backup 2-phase plan, IIS migration track, 4 secondary topics documented as recommendations) - file 3 impl-tasks ⚪ ready (spawned by roadmap-design): - cms-stopgap-backup-daily — Phase 1, plug RPO=∞ via daily rsync to kreknin - mssql-minio-migration-to-vds — Phase 2 enabler, achieves RPO 1h target - windows-hosting-vendor-research — design-task for IIS migration off home host - unblock [admin-infra-project-review] 🔵 → ⚪ (last blocker cleared) - expand .wiki/concepts/future-resilient-architecture-goals.md with §Workshop pass 1 (canonical) above original §Pre-workshop placeholder (historical) Key user-decisions zafiksirovany in workshop: - CMS RTO 4h / RPO 1h (not 1h/15min — overkill for one-person infra) - MSSQL+MinIO migrate to VDS (not Windows-side managed hosting) - MSSQL Always-On AG rejected — log shipping every 60min sufficient - IIS long-term dies with snolla-on-node; transitional via managed Windows host - Cloud off-site = Yandex Object Storage when needed (kreknin already off-site) - Monitoring = Uptime Kuma on VDS, high-priority among not-filed Acceptance per spec (user confirmed plan + concrete impl-tasks top-3 + doc committed) — met. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
21 KiB
title, type, tags, sources, updated
| title | type | tags | sources | updated | |||||
|---|---|---|---|---|---|---|---|---|---|
| Future Resilient Architecture — roadmap | concept |
|
|
2026-05-21 |
Future Resilient Architecture
Roadmap "выстроить отказоустойчивую архитектуру чтобы инциденты типа 2026-05-18 не повторялись". Документ живой — переоценивается после каждого incident'а и major-migration'а.
Структура:
- §Workshop pass 1 (2026-05-21) — текущий зафиксированный план, decisions per service. Это canonical часть документа.
- §Pre-workshop placeholder (2026-05-19) — изначальные наброски без user-confirmation, оставлены для history. Не source of truth.
Workshop pass 1 — 2026-05-21
Roadmap expanded from placeholder to concrete decisions + impl-tasks. Workshop session с user (vitya) 2026-05-21. Каждое decision ниже = user-confirmed, не unilateral recommendation. Trace разговора зафиксирован в [resilience-roadmap-design] close-note (см. .tasks/STATUS.md).
Per-service RTO/RPO matrix
Globальные RTO/RPO разнесены per service — cost-of-downtime у разных сервисов разный. Числа = target, не факт. Откалибруются после first incident в новой архитектуре.
| Сервис | RTO (max downtime) | RPO (max data loss) | Rationale |
|---|---|---|---|
| CMS прод-сайты (snolla/labtools/pilorama98/tandemmebel/emspb/kupimknigi/maljarka — 8 hosts) | 4 ч | 1 ч | клиентский трафик = деньги; больше 4ч → звонки клиентов |
| CMS DB (MSSQL) | 4 ч | 1 ч | orders + контент; час правок переживёшь, день — нет |
CMS content (IIS files C:\sites\* + MinIO) |
4 ч | 24 ч | картинки/asset'ы меняются редко |
| OpenWRT router | 1 ч | n/a | сетевой SPOF — без него весь public IP мёртв, tied к CMS |
| Traefik (на windows-host) | 4 ч | n/a | живёт на том же host'е что CMS, RTO одинаковый |
| Gitea | 8 ч | 24 ч | один пользователь, полдня без push переживёшь |
| Verdaccio | 8 ч | 24 ч | без деплоев фронтов полдня — ок |
| Registry | 24 ч | n/a (rebuild) | "новых наделаю" decision при VDS bootstrap, см. ../sources/vds-kzntsv-bootstrap-2026-05-20 §3.3 |
| Shared DB-park (PG/Maria/Mongo/Redis на VDS) | 8 ч | 24 ч | dev/staging, не прод-трафик |
| ntfy | 4 ч | n/a | алерт-канал; без него слепой но не сломанный |
Decisions зафиксированы (что отвергнуто):
- 99.99% uptime / continuous replication / hot-standby для CMS — отвергнуто как непропорционально дорогое для one-person infra.
- MSSQL Always-On AG — отвергнуто (требует Enterprise license), log shipping каждые 60 мин достаточно для RPO 1ч.
- MSSQL → PostgreSQL миграция — оставлено как long-term option (упомянуто в §Pre-workshop placeholder), не приоритет — отдельный major project, требует CMS-side rewrite.
Калибровочные факты:
- 2026-05-18 incident: RTO факт = 15 ч, RPO факт = 9 дней (Hyper Backup от 2026-05-09).
- Target 4ч / 1ч для CMS = огромный шаг от текущей baseline.
- Прогресс 2026-05-20: VDS поднят → infra (gitea/verdaccio/registry/DB-park) уже decoupled с windows-host SPOF. CMS — пока нет.
CMS backup pipeline — 2-фазный план
Текущий статус (2026-05-21): CMS прод (sites + MSSQL + MinIO) на ../entities/windows-recovery-host не имеет ни одного бэкапа нового состояния — последний Hyper Backup 2026-05-09 был с мёртвой синки. RPO факт = ∞ (если host сгорит сейчас — теряем всё).
Фаза 1 — stop-gap (1-2 дня работы, на этой неделе): Impl-task: ../../.tasks/cms-stopgap-backup-daily.
- MSSQL: ежедневный
BACKUP DATABASE FULL→ локальныйD:\backup\→ ночной rsync на ../entities/kreknin-synology - IIS files (
C:\sites\*): ежедневный rsync → kreknin - MinIO data dir: ежедневный rsync → kreknin
- Cron через Windows Task Scheduler + SSH-pipe (паттерн как у ../../.tasks/vds-backup-rsync-kreknin)
- Достигаемый RPO = 24ч (плохо vs target 1ч, но лучше чем ∞ и достаточно как мост до Фазы 2)
- Не строить ничего изощрённого — это патч на 2-4 недели до миграции MSSQL/MinIO.
Фаза 2 — proper RPO 1ч после миграции на VDS (1-2 недели работы): Impl-task: ../../.tasks/mssql-minio-migration-to-vds.
- MSSQL container на ../entities/vds-kzntsv как часть
/opt/stacks/databases/рядом с pg/maria/mongo/redis - MinIO контейнер на VDS отдельным stack'ом
/opt/stacks/storage/ - CMS app в IIS на windows-host ходит через TCP на
mssql.vds.kzntsv.site:1433/minio.vds.kzntsv.site:9000— connection strings меняются, остальное прозрачно (паттерн уже работает для DBs через traefik raw-TCP, см. traefik-tcp-passthrough-vs-starttls + db-tls-self-signed-via-traefik-raw-tcp) - Backup pipeline = расширение существующего
/opt/stacks/backup/scripts/run.shна VDS: добавитьsqlcmd BACKUP LOGежечасно + ежедневный full в существующий rsync-pipeline к kreknin - Достижение RPO 1ч = tx log backup каждые 60 мин (или 15 — tunable)
- Risk: сетевая латентность IIS→MSSQL теперь WAN (10-30ms vs localhost). Большинство CMS-операций batchey, не latency-sensitive — но pre-cutover benchmark обязателен для hot-paths (admin assets UI / search / каталоги).
Stop-gap pipeline списывается после Фазы 2 — backup data будет идти через VDS-pipeline.
IIS migration track
Текущий статус: IIS на ../entities/windows-recovery-host — temp-solution recovery 2026-05-19 (изначально recovery-host был VM, переехали на native IIS host для стабильности — см. ../sources/iis-host-migration-2026-05-19). Домашняя машина = SPOF + физический риск (пожар / залив / кража / power-loss).
Target end-state (долгосрочный): snolla CMS переписан на node → IIS не нужен вообще, всё в docker на VDS. Это dev-работа, вне scope этой roadmap'ы. Прогресс отслеживается отдельно user'ом.
Переходный план: managed Windows hosting (RU-провайдер), куда переедет IIS до завершения node-rewrite'а.
Impl-task (research-only): ../../.tasks/windows-hosting-vendor-research (1 день).
- Output: 1-pager с recommended vendor + plan / cost estimate / migration recipe outline.
- Comparison candidates: Rusonyx (у тебя уже там VDS), Selectel, FirstVDS, Beget.
- Critical constraints: RDP-доступ, .NET Framework 4.8 native, IIS 10, external MSSQL/MinIO connectivity (на VDS после Фазы 2).
После research → файлим follow-up impl-task iis-migration-to-managed-windows-hosting (большая, mes+ работы) — но не сейчас, пока на windows-host'е работает + stop-gap backup'ы плюсуют RPO 24ч safety net.
Cloud off-site backup target (3-й уровень 3-2-1)
Recommendation (не файлится impl-таской пока): Yandex Object Storage (~1.6₽/GB/мес Standard tier, S3-compatible — работает с restic / rclone / duplicati). РФ-юрисдикция → нет cross-border сюрпризов.
Альтернатива rejected: Backblaze B2 — дешевле (~$5/TB/мес) но cross-border payment friction + sanctions risk.
Defer impl: ../entities/kreknin-synology уже географически off-site (другая локация). Cloud добавится поверх kreknin'а, когда захочется паранойи "kreknin тоже может сгореть" или после первого incident'а где kreknin не помог. До этого: kreknin = "1 off-site" из 3-2-1.
Future impl-task: cloud-offsite-backup-yandex-object — ⚪ ready (не file'нута), создать когда руки дойдут.
Network resilience
Recommendation (не файлится impl-таской): defer multi-WAN. Провайдер исторически стабилен. OpenWRT mwan3 + 4G/LTE USB-modem = страховка ~3-5к₽ единоразово + симка ~200₽/мес, но low-probability event. Возвращаемся после первого incident'а с потерей провайдера.
Cloudflare Tunnel (free tier, IP-абстракция, no DDoS-protection): отдельный вопрос для workshop pass 2 — добавляет vendor dependency на edge, trade-off обсуждается отдельно когда станет интересно (особенно после миграции MSSQL/MinIO на VDS — тогда windows-host станет thin web-layer, легче абстрагировать его IP).
Future impl-tasks (не file'нуты):
network-mwan3-4g-failover— ⚪ ready, file когда подгорит провайдеромcloudflare-tunnel-edge-abstraction— workshop pass 2 решение
Monitoring stack
Recommendation (не файлится impl-таской, но приоритет high среди not-filed): Uptime Kuma на VDS. Docker, ставится за 30 мин на /opt/stacks/monitoring/, push-нотификации через ntfy (уже работает vds-ops topic — см. ../../.tasks/vds-ntfy-push). Покрывает HTTP/TCP/ping/DNS healthchecks + cert-expiry warnings.
Anti-recommend: Prometheus + Grafana — overkill для one-person infra, full-stack observability нужен когда 20+ сервисов. Внешний (Pingdom/UptimeRobot) — платный, лучше self-host раз VDS уже есть.
Initial monitor set (для impl):
- HTTP 200 OK на 8 CMS hosts (snolla.com, labtools.ru/pro, pilorama98.ru, tandemmebel.ru, emspb.ru, kupimknigi.spb.ru, maljarka.tandemmebel.ru)
- HTTP 200 на инфра-hosts: git.kzntsv.site, verdaccio.kzntsv.site, registry.kzntsv.site, ntfy.vds.kzntsv.site
- TCP на DB-park ports: postgres/mariadb/mongo/redis (5432/3306/27017/6379)
- Ping на windows-recovery-host (94.19.247.14) и VDS (89.253.255.94)
- Cert-expiry warnings (Uptime Kuma встроено)
Желательно установить ДО того как windows-host опять упадёт — чтобы инцидент был "ntfy push 2 мин назад", а не "мне Серёга позвонил".
Future impl-task (не file'нута): monitoring-uptime-kuma-deploy — ⚪ ready, приоритет high среди not-filed.
Runbook coverage matrix
Текущее покрытие (post-mortem chronologies с step-by-step recipe):
- ../sources/nas-recovery-session-2026-05-18 — NAS-loss recovery
- ../sources/iis-host-migration-2026-05-19 — IIS migration recipe
- ../sources/vds-kzntsv-bootstrap-2026-05-20 — VDS bootstrap
Missing runbooks:
- VDS-loss recovery (если Rusonyx упал / аккаунт потерян)
- Cert-expiry (acme.json renewal failure, manual DNS-01 через REGRU)
- DB-corruption restore (per-service: MSSQL, postgres, mariadb, mongo)
- Ransomware-recovery (encrypted backups restore protocol)
- OpenWRT-loss (новый роутер, restore configs)
Defer: runbook'и для текущей переходной архитектуры устареют через 2 мес (после mssql-minio-migration-to-vds + iis-migration-to-managed-windows-hosting). Пишем после стабилизации архитектуры — иначе тратим время на документацию которая не доживёт до использования.
Future impl-task (не file'нута): runbook-coverage-matrix-design — ⚪ ready, file после migrations завершены.
Top-3 impl-tasks filed (2026-05-21)
- ../../.tasks/cms-stopgap-backup-daily ⚪ — Фаза 1, plug RPO=∞ за 1-2 дня.
- ../../.tasks/mssql-minio-migration-to-vds ⚪ — Фаза 2 enabler, achieves RPO 1ч target.
- ../../.tasks/windows-hosting-vendor-research ⚪ — design-task для IIS-переезда (1 день research, output = recommendation + cost).
Workshop pass 2 — open agenda
Что не обсуждалось в этом проходе (для следующего workshop'а когда руки дойдут):
- Cloudflare Tunnel — edge abstraction trade-off
- Off-site cloud target — конкретный configure (decision уже сделано, ждёт kreknin-incident'а или паранойи)
- Hermes service — defer, ждёт уточнения user
- snolla node-rewrite progress — dev-track, периодически переоценивать impact на этот roadmap (если близко к completion → managed Windows hosting миграция отменяется)
- DR drill cadence — failover тесты раз в квартал (упомянуто в §Pre-workshop placeholder, не закрыто)
Pre-workshop placeholder (2026-05-19) — historical draft
Note: ниже — изначальные наброски до workshop pass 1. Не source of truth, оставлены для history. Concrete decisions — в §Workshop pass 1 выше.
Что сейчас не так
См. recovery-architecture-snapshot → раздел "Single Points of Failure". Кратко:
- ⚠️ Windows-PC = SPOF
- ⚠️ Один public IP
- ⚠️ Один MSSQL primary без replica
- ⚠️ Один MinIO single-node
- ⚠️ Backup только Hyper Backup на одну синку (Kreknin), сейчас она cold
- ⚠️ Backup нового рабочего состояния (CMS data на recovery-host) отсутствует
- ⚠️ Нет off-site backup (cloud)
Цели верхнего уровня
- RTO (Recovery Time Objective) — сколько максимум downtime клиенты должны видеть при отказе.
- Текущий по факту: ~15 часов (что и было).
- Целевой: < 1 час для одиночного отказа, < 4 часов для каскадного.
- RPO (Recovery Point Objective) — сколько максимум данных потерять при отказе.
- Текущий: до 24 часов (если успеет бэкап после изменения) — больше если бэкап не успел.
- Целевой: < 1 час, в идеале continuous (replication).
- Стоимость — bounded by разумным % от выручки клиентов.
- Operational simplicity — никаких heroic ops по 15 часов в случае проблемы.
Технические направления (наброски)
Backup-стратегия 3-2-1
Стандарт: 3 копии данных, 2 разных media, 1 off-site.
- Копия 1: primary storage (live) на NAS / Windows-PC
- Копия 2: local backup target (kreknin-synology остаётся, плюс отдельный)
- Копия 3: cloud off-site — Backblaze B2 / Yandex Object Storage / AWS S3 Deep Archive / Hetzner Storage Box
- Все backups encrypted client-side
- Retention: 7 daily / 4 weekly / 12 monthly
Compute resilience
Варианты:
A. Multi-host on-prem: 2-3 физических машины с виртуализацией (Proxmox VE), HA-кластер, VMотом migration. Дорого, но автономно.
B. Cloud-first: перенос CMS-стека в managed Kubernetes (Yandex Cloud / VK Cloud / hetzner) — managed MSSQL / managed S3 / managed Postgres. Простота операций, но vendor lock-in.
C. Гибрид: primary on-prem (Synology с CMR), warm standby в cloud (готовый к failover за 5 мин). Compromise.
Database resilience
MSSQL options:
- Always On Availability Groups (требует Enterprise license — недёшево)
- Log Shipping (бесплатно, но manual failover)
- MSSQL → PostgreSQL миграция? (если есть полная свобода — выгоды Open Source + распространённые managed предложения).
Для recovery-сценария: continuous backup через VDI + native MSSQL TDE backup → S3.
Network resilience
- Multi-WAN на OpenWRT: primary провайдер + 4G/LTE USB-modem как failover. OpenWRT mwan3 package.
- Cloudflare Proxy / Tunnel: перенаправление публичного трафика через Cloudflare edge. Помогает с DDoS и переключением IP без DNS-changes.
- Static IP пересмотр: разные провайдеры → multi-homed setup.
Monitoring + auto-recovery
- Healthchecks на каждый layer (TCP, HTTP, deep DB query) — Prometheus + Alertmanager или Uptime Kuma.
- Watchdog скрипты — auto
ipconfig /release/renewв VM, autodocker compose restartконтейнера если healthcheck падает > N min. - Telegram-уведомления на инциденты (для пользователя в реал-тайм когда что-то фейлится).
Документация и runbook
- Runbook на каждый процедурный сценарий (failover, restore, network swap).
- Регулярные failover drills раз в квартал — буквально нажать "восстановиться" и засечь время.
- Wiki эта — стартовая точка.
Что НЕ цели
- Перестройка с нуля «потому что сейчас не идеально». Текущая архитектура работает, замена должна быть инкрементальной.
- 99.99% uptime — нереалистично для one-person infrastructure, и не нужно для CMS-сайтов клиентов.
Следующие шаги (когда дойдут руки)
- Заменить WD40EFAX на CMR-диски, пересобрать пул dead-synology-diskstation.
- Включить ежедневный Hyper Backup из нового пула на kreknin-synology.
- Добавить cloud-backup target (Yandex Object Storage наиболее очевидный для RU-юрисдикции).
- Настроить monitoring/alerts.
- Документировать runbooks.
Связано со всеми остальными страницами этого wiki.
Прогресс 2026-05-20
✅ Decouple инфра-сервисов от windows-recovery-host SPOF. Поднят отдельный облачный VDS vds-kzntsv (Rusonyx 160 NVMe), туда мигрированы gitea / verdaccio / docker-registry + shared DB park (Postgres/MariaDB/Mongo/Redis). windows-recovery-host теперь хостит только production CMS. Это не полный multi-host resilience (VDS сам по себе SPOF), но critical infra decoupling сделан.
Запланированы follow-up tasks (см. .tasks/):
vds-backup-rsync-kreknin— ежедневный 05:00 MSK rsync VDS → kreknin с email-нотификацией.vds-ntfy-push— self-hosted push на Android для backup status и monitoring.vds-gc-cron— cron GC для verdaccio + registry чтобы не повторился incident 99G на registry.
Следующая фаза по originally outlined ladder — добавить cloud off-site backup target (Backblaze B2 / Yandex Object Storage) поверх kreknin'а, и replicated MSSQL для production CMS.