docs(.wiki): iis-migration rollback + post-mortem + xml-escape concept
Phase 9 — rollback миграции на host-IIS из-за Docker port-loop (host.docker.internal:80 от traefik container резолвится обратно в сам traefik через NAT, https.yml http-catchall middleware отдавал 301 -> TOO_MANY_REDIRECTS). Prod снова через VM. - iis-migration-2026-05-19-postmortem: 10 ошибок миграции + recipe для следующей попытки (backend port НЕ :80, smoke с MaximumRedirection 0, тест из НЕ-LAN, parallel VM x N часов, atomic revert plan) - webconfig-password-xml-escape: новая gotcha — & в conn-string пароле требует & в Web.config (XML reserved char) - iis-host-migration-2026-05-19: Phase 9 rollback chronology + что осталось на хосте inert - snolla-recovery-vm: статус -> active prod (обратно) - windows-recovery-host: host IIS sites -> inert artifacts - recovery-architecture-snapshot: chain снова через VM, traefik backends восстановлены из .bak-phase3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,120 @@ Production-трафик 10 главных доменов теперь идёт *
|
||||
- Backup конфигов traefik: `*.yml.bak-phase3-2026-05-19`.
|
||||
- Скрипты Phase 2 и Phase 3 — в истории чата сессии (не сохранены отдельным файлом, идемпотентны на повторный запуск).
|
||||
|
||||
## Phase 4 — реорг `C:\sites\` + перенос stayer'ов (вечер 2026-05-19)
|
||||
|
||||
Пользователь возмутился разбросом (`C:\sites\` только для snolla, `C:\stayer\` для stayer). Реорганизация ради единой иерархии:
|
||||
|
||||
- `C:\sites\MoreThenCms.Web` → `C:\sites\snolla` (rename)
|
||||
- `C:\stayer\MoreThenCms.Web` → `C:\sites\stostayer` (move)
|
||||
- `C:\stayer\stostayer.old` → `C:\sites\stostayer.old` (move)
|
||||
- `C:\stayer\Snolla.IdentityManager` → `C:\sites\snolla-identity-manager` (move + kebab-rename)
|
||||
- Удалены: `C:\stayer\Mis.StoStayer.{Price,TireService,Calculator}.{Api,Web}` (sub-apps не нужны).
|
||||
- `C:\stayer\` полностью удалён.
|
||||
|
||||
IIS sync:
|
||||
- Site `MoreThenCms.Web` → переименован в `snolla` (`Set-ItemProperty IIS:\Sites\... -Name name`)
|
||||
- AppPool `MoreThenCms.Web` — **rename невозможен in-place**, пересоздан как `snolla` с тем же набором properties (.NET v4.0 Integrated, `ApplicationPoolIdentity`), site rebound, старый pool удалён.
|
||||
- `physicalPath` всех 3 sites обновлён под `C:\sites\<name>`.
|
||||
- Web.config sitePath patches:
|
||||
- `C:\sites\snolla\Web.config`: `C:\sites\MoreThenCms.Web\` → `C:\sites\snolla\`
|
||||
- `C:\sites\stostayer\Web.config`: `C:\stayer\MoreThenCms.Web\` → `C:\sites\stostayer\`
|
||||
- ACL re-grant + cleanup stale ACE для `IIS AppPool\MoreThenCms.Web`.
|
||||
|
||||
## Phase 5 — stostayer.old DB-conn патч (запутанная история conn-string'ов в stayer\)
|
||||
|
||||
Локальный smoke `:8091` падал в timeout. Причина: `C:\sites\stostayer.old\web.config` имел `Data Source=10.0.2.2` (адрес VBox NAT gateway, на хосте не резолвится) с user=`snolla` — фактически идентичная нашему MSSQL контейнеру конфигурация, только адрес неправильный. Patch: `10.0.2.2` → `localhost`. После — `:8091` → 200.
|
||||
|
||||
Это **наша ошибка** Phase 2 — пропустили patch этого файла, так как фокус был только на `MoreThenCms.Web\Web.config`.
|
||||
|
||||
## Phase 6 — stostayer DB-conn миграция на новый сервер (`www.stostayer.ru`)
|
||||
|
||||
Локальный smoke `:8090` тоже timeout — но по другой причине. `C:\sites\stostayer\Web.config` указывал на `89.253.219.2,1433` (внешний production MSSQL), оказался **полностью недоступен**: TCP timeout, ping fail, traceroute затухает на 8-м hop у `139.45.230.171`. На VM (через тот же путь) тоже не работал — пользователь подтвердил.
|
||||
|
||||
Пользователь предоставил новые creds: `www.stostayer.ru,1433` / `stayer_site` / `^I9D)LB)DK)8J#xBDG$t}W&_ioaT!M!LF`. Тест из не-elevated PS: TCP reachable, SQL login OK (SQL Server 2022). Patched Web.config.
|
||||
|
||||
**Pitfall:** после patch IIS отдавал HTTP 500. Причина — символ `&` в пароле, который **в XML является зарезервированным**. ASP.NET Web.config XML парсер падал на парсинг conn-string. Fix: `&` → `&` (XML entity escape). См. [[webconfig-password-xml-escape]].
|
||||
|
||||
## Phase 7 — отключение traefik routes для stayer'ов
|
||||
|
||||
Пользователь решил: stayer'ы наружу светить не нужно вообще (даже после миграции на хост). `stostayer.yml` и `oldstostayer.yml` переименованы в `*.yml.disabled` — traefik file-provider не подхватывает, route gone. Site'ы на хосте `:8090/:8091` остаются для возможного внутреннего использования.
|
||||
|
||||
Backup yml для этих изменений: `*.yml.bak-stayer-switch-2026-05-19` (содержит вариант с переключением на `:8090/:8091` — на случай если решим включить обратно).
|
||||
|
||||
## Phase 8 — VM savestate
|
||||
|
||||
После того как 100% prod-трафика идёт через host-IIS, VM `snolla-recovery` заморожена через `VBoxManage controlvm "snolla-recovery" savestate`. VMState = `saved`. Конфигурация и диски сохранены — resume за 5-10 сек если что-то понадобится. Не удалена.
|
||||
|
||||
## Финальное состояние (2026-05-19 конец сессии)
|
||||
|
||||
```
|
||||
C:\sites\
|
||||
├── snolla\ (was MoreThenCms.Web in C:\inetpub\wwwroot, was in vm-sites\wwwroot\MoreThenCms.Web)
|
||||
├── stostayer\ (was C:\stayer\MoreThenCms.Web)
|
||||
├── stostayer.old\ (was C:\stayer\stostayer.old)
|
||||
└── snolla-identity-manager\ (was C:\stayer\Snolla.IdentityManager — deploy artifact, без живого consumer'а)
|
||||
|
||||
IIS sites/pools (имя=имя=пуло):
|
||||
snolla *:80 → C:\sites\snolla (pool snolla, .NET v4.0 Integrated, AppPoolIdentity)
|
||||
stostayer *:8090 → C:\sites\stostayer (pool stostayer)
|
||||
stostayer.old *:8091 → C:\sites\stostayer.old (pool stostayer.old)
|
||||
|
||||
Connection strings:
|
||||
snolla: Data Source=localhost → MSSQL container на хосте (DB MoreThenCms)
|
||||
stostayer: Data Source=www.stostayer.ru,1433 (user stayer_site) → внешний SQL Server 2022
|
||||
stostayer.old: Data Source=localhost → MSSQL container на хосте (DB stostayer, user snolla)
|
||||
|
||||
Traefik active routes: 10 главных доменов (snolla.com и др.) + rimiz.ru → host:80.
|
||||
Stayer routes (stostayer.snolla.com, old.stostayer.ru) DISABLED — приватны.
|
||||
Mёртвые: disk.yml, dsm.yml (192.168.1.10).
|
||||
|
||||
VM snolla-recovery: VMState=saved (frozen, ~92 GB на диске + ~3 GB savestate RAM dump).
|
||||
```
|
||||
|
||||
## Открытые вопросы (что унесли в следующую сессию)
|
||||
|
||||
- **`rimiz.ru` отдаёт 404** на host-IIS. CMS-routing не знает этот host — нужно копнуть БД (таблица CMS-сайтов, mapping host header → site).
|
||||
- **Snolla.IdentityManager** на хосте: папка перенесена, но IIS-сайт не создавался (по решению). Если CMS-код где-то дёргает `localhost:8089` или подобное — будет тихий fail. Симптомов пока нет.
|
||||
- **Phase 5 (из старого плана)**: URL Rewrite + ARR для фикса `:4443` в редиректах, Application Initialization (warm-start), log rotation `C:\inetpub\logs\`. Не блокеры.
|
||||
- **VM-cleanup**: если через ~неделю стабильной работы host'а проблем не будет — `VBoxManage unregistervm "snolla-recovery" --delete` освободит ~92 GB. NAT port forwards в OpenWRT (host:18080/18180/18181/18189) можно удалить.
|
||||
|
||||
## Связано
|
||||
|
||||
[[recovery-architecture-snapshot]] обновлён под новую chain. [[snolla-recovery-vm]] — статус демоут до stayer-only. [[windows-recovery-host]] — добавлены 3 native IIS sites. [[cms-config-rewrite-pattern]] — паттерн UTF-8 BOM подтверждён ещё раз.
|
||||
[[recovery-architecture-snapshot]] обновлён под полностью-host chain. [[snolla-recovery-vm]] — VMState=saved, все sites unused. [[windows-recovery-host]] — финальный layout `C:\sites\`. [[webconfig-password-xml-escape]] — новый concept про XML entity escape в conn-string'ах. [[cms-config-rewrite-pattern]] — UTF-8 BOM подтверждён ещё много раз.
|
||||
|
||||
---
|
||||
|
||||
## Phase 9 — RЕVERT (вечер 2026-05-19, после провала)
|
||||
|
||||
**Что случилось:** через ~10 минут после моего commit'a "done" пользователь открыл `https://www.pilorama98.ru/` → `502 Bad Gateway`. Дальше остальные домены показали `TOO_MANY_REDIRECTS`.
|
||||
|
||||
**Root cause** (расписан полностью в [[iis-migration-2026-05-19-postmortem]]):
|
||||
- Phase 3 я patched traefik backend `host.docker.internal:18080` → `host.docker.internal:80`.
|
||||
- Внутри traefik-контейнера `host.docker.internal:80` через Docker Desktop NAT резолвится **обратно в сам traefik** на его HTTP entrypoint :80 (potential Docker publish-port loopback gotcha).
|
||||
- traefik `https.yml` имеет http-catchall middleware `redirect-to-https` → traefik отвечает 301 на свой же запрос → loop.
|
||||
|
||||
**Реактивная цепочка ошибок** (~1 час):
|
||||
- Restart-WebAppPool, nuke workers, docker restart traefik → only sделали хуже (503).
|
||||
- Patched `host.docker.internal:80 → 192.168.1.143:80` → тот же loop (LAN-IP через NAT тоже возвращается в traefik).
|
||||
- Patched на `:8088` + добавил IIS binding → нужен `Stop+Start Website` чтобы binding applied, изначально забыл → IIS не listen → 503.
|
||||
- Думал что 301 от CMS (Pitfall 5 X-Forwarded-Proto), копал CMS код — реальный источник был самим traefik (headers без `Server: Microsoft-IIS` подсказывали).
|
||||
|
||||
**Revert (выполнен):**
|
||||
- `VBoxManage startvm "snolla-recovery"` — VM поднята из savestate (~10s + 90s warmup + recipe `ipconfig /release /renew` для застрявшего network adapter из [[vbox-windows-stability-tuning]]).
|
||||
- 11 главных yml восстановлены из `*.bak-phase3-2026-05-19` (`host.docker.internal:18080` → VM).
|
||||
- Stayer yml: `stostayer.yml.disabled / oldstostayer.yml.disabled` удалены, восстановлены из `*.bak-stayer-switch-2026-05-19` (`:18180/18181` → VM).
|
||||
- `docker restart traefik` (file-provider не подхватил reload автоматом).
|
||||
- Public smoke через VM-chain → 7/11 хостов отвечают (2 c 200, 5 с CMS-side редиректами на canonical — нормально для CMS-логики); проверено пользователем в браузере → работает.
|
||||
|
||||
## Финальное состояние (после revert)
|
||||
|
||||
Production снова на VM-chain (как было в начале сессии 2026-05-19). На хосте осталось:
|
||||
- `C:\sites\{snolla, stostayer, stostayer.old, snolla-identity-manager}` — ~11 GB, **inert** (не на prod-пути)
|
||||
- IIS sites/pools `snolla, stostayer, stostayer.old` — не получают трафика (traefik backend назад на VM)
|
||||
- traefik backups: `*.bak-phase3-2026-05-19`, `*.bak-stayer-switch-2026-05-19`, `*.bak-hostip-2026-05-19`
|
||||
- VM `snolla-recovery` — running, IIS активен, обслуживает 11 главных доменов + 2 stayer публично через port forwards.
|
||||
|
||||
**Артефакты для следующей попытки** (НЕ удалять):
|
||||
- Web.config'и в `C:\sites\` пропатчены правильно (sitePath, conn-strings, stostayer на новый DB) — можно переиспользовать.
|
||||
- IIS sites/pools уже настроены — переключение требует только traefik backend patch + tested correctly.
|
||||
- Recipe для правильной миграции — в [[iis-migration-2026-05-19-postmortem]].
|
||||
|
||||
Reference in New Issue
Block a user