Files
admin/.tasks/mssql-vds-migration.md
vitya 86a94d7f9d tasks(vds-migration): decompose umbrella → 3 child tasks
- mssql-vds-migration : Express edition, BACKUP/RESTORE method, mssql.kzntsv.site:1433
- minio-imgproxy-vds-migration : MinIO upgrade 2020→latest, mc mirror, includes imgproxy+nginx
- iis-cutover-to-vds-services 🔵: atomic web.config repoint (1 file → 11 hosts), blocked on both migrations
- umbrella mssql-minio-migration-to-vds 🟢: decomposed (kept for history)

Discovery: 5 prod DBs ≤ 968 MB (Express OK), .ldf logs 12 GB → SHRINKFILE
pre-cutover. VDS: 79 GB free, 5.8 GB RAM avail. ownCloud capped 1G.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 09:02:49 +03:00

78 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# mssql-vds-migration
## Goal
Перенести MSSQL контейнер с [[../entities/windows-recovery-host]] на [[../entities/vds-kzntsv]] (`/opt/stacks/databases/mssql/`), Express Edition для прода, доступ снаружи через `mssql.kzntsv.site:1433` (traefik TCP passthrough), интеграция в существующий `vds-backup-rsync-kreknin` pipeline.
Это **MSSQL-only половина** umbrella'ы `mssql-minio-migration-to-vds` (декомпозирована 2026-05-22). Вторая половина — `minio-imgproxy-vds-migration`.
## Key files / refs
- **Source:** docker container `mssql` на windows-recovery-host, image `mcr.microsoft.com/mssql/server:2019-latest`, volume `mssql_mssql_data` (26.6 GB total, real data ~2.4 GB, остальное .ldf logs).
- **Source DBs** (verified via `docker exec mssql ls /var/opt/mssql/data/`, 2026-05-22):
- `MoreThenCms.mdf` 867 MB + log 9.9 GB
- `StayerCalculator.mdf` 504 MB + log 1.2 GB
- `StayerPrice.mdf` 38 MB + log 215 MB
- `TireService.mdf` 8 MB + log 8 MB
- `stostayer.mdf` 968 MB + log 264 MB
- **Max .mdf 968 MB < 10 GB Express limit ✓ all fit**
- **Target:** `/opt/stacks/databases/mssql/{data,docker-compose.yml,.env}` на VDS, паттерн как у postgres (`/opt/stacks/databases/postgres/data` bind, network `proxy` + `shared-dbs`).
- **Image:** `mcr.microsoft.com/mssql/server:2022-latest` Express Edition (`MSSQL_PID=Express`).
- **CMS connection strings:** `Data Source=localhost,1433``Data Source=mssql.kzntsv.site,1433` в IIS web.config / appsettings.
- **TLS:** self-signed, traefik raw-TCP passthrough — pattern [[../.wiki/concepts/db-tls-self-signed-via-traefik-raw-tcp]] + [[../.wiki/concepts/traefik-tcp-passthrough-vs-starttls]].
- **Backup pipeline:** `/opt/stacks/backup/scripts/run.sh` на VDS — добавить новые ноги (см. acceptance 6).
## Decisions
- **Edition: Express** (user 2026-05-22). Max DB size 10 GB соблюдён всеми текущими базами. RAM cap Express = 1.4 GB built-in. Дополнительно `MSSQL_MEMORY_LIMIT_MB=2048` (user-confirmed), но Express всё равно сам зажмёт до 1410.
- **Method: BACKUP DATABASE … WITH COMPRESSION, COPY_ONLY** → scp `.bak` → RESTORE на VDS. Не detach/attach — кросс-edition (Developer → Express) supported только через backup/restore. Compression ≈ 80% reduction, ожидаемый transfer ~500 MB.
- **Pre-cutover SHRINKFILE на .ldf** — срежет 12 GB logs до минимума (не для transfer — для cleanup source перед миграцией; transfer идёт через .bak, который и так не включает inactive log space).
- **Hostname: `mssql.kzntsv.site`** (не `mssql.vds.kzntsv.site` — user decision 2026-05-22). DNS A-record указать на VDS IP.
## Acceptance
1. **Pre-cutover на source** (windows-host):
- `BACKUP LOG <db> WITH TRUNCATE_ONLY` + `CHECKPOINT` + `DBCC SHRINKFILE` для .ldf всех 5 prod DBs.
- Verify `du -sh /var/opt/mssql/data/*_log.ldf` → каждый < 100 MB.
- **WARNING:** SHRINKFILE с TRUNCATE_ONLY ломает log-chain → no point-in-time restore до следующего FULL backup. Делается **только** в migration window, новый FULL снимается сразу после RESTORE на VDS.
2. **MSSQL container на VDS** запущен:
- `mcr.microsoft.com/mssql/server:2022-latest`, `ACCEPT_EULA=Y`, `MSSQL_PID=Express`, `MSSQL_MEMORY_LIMIT_MB=2048`, `SA_PASSWORD` из `pass show mssql-vds/sa-password` (новый pass entry).
- Volume bind `/opt/stacks/databases/mssql/data:/var/opt/mssql:rw`.
- Networks `proxy` + `shared-dbs`. Traefik labels TCP entrypoint `mssql` :1433 → HostSNI(`*`).
3. **Traefik static config** (`/opt/stacks/proxy/traefik/traefik.yml`):
```yaml
entryPoints:
mssql:
address: ":1433"
```
+ ufw allow 1433/tcp.
4. **5 prod DBs restored** на VDS:
- `BACKUP DATABASE … WITH COMPRESSION, COPY_ONLY` на source → 5 `.bak` файлов.
- scp → `/opt/stacks/databases/mssql/data/backups/` на VDS.
- `RESTORE DATABASE … FROM DISK='/var/opt/mssql/backups/<db>.bak' WITH MOVE`.
- Verify `SELECT name, state_desc FROM sys.databases` → все 5 ONLINE, `DBCC CHECKDB('<db>')` → 0 errors на каждой.
5. **CMS connection strings updated** в web.config (или эквиваленте), 8 sites smoke:
- 200 OK + asset loading + admin/assets/getList (известный hot-path).
- **Pre-cutover benchmark обязателен** — admin assets UI / search / catalogs latency измерены до и после, **degradation <2x** target. Если worse — discuss перед commit'ом cutover (10-30ms WAN vs localhost).
6. **Backup pipeline на VDS расширен** (`/opt/stacks/backup/scripts/run.sh`):
- `mssql_dump_full` ежедневно (BACKUP DATABASE WITH COMPRESSION для каждой DB → tar.gz → rsync nightly).
- `mssql_tx_log_backup` ежечасно (BACKUP LOG для каждой DB через `docker exec mssql /opt/mssql-tools/bin/sqlcmd …`) → rsync hourly. **Достигает target RPO 1ч.**
7. **ntfy push verified** для расширенного pipeline (включает MSSQL dump size/duration).
8. **Source windows-host MSSQL** — после 48ч uptime на VDS: stop container (read-only fallback пропустить — pass), через неделю — `docker rm + docker volume rm mssql_mssql_data`.
9. **Documented** в [[../.wiki/concepts/mssql-on-vds]] (создать): architecture, rollback recipe (revert connection strings + start windows-host MSSQL container), migration runbook.
## Open questions
- [ ] **DNS A-record `mssql.kzntsv.site` → VDS IP** (89.253.255.94) — сделать через REGRU API или manual?
- [ ] **Hermes service на windows-host** — зависит от local MSSQL? Если да — мигрируется заодно или ломается. См. [[../.wiki/entities/vds-kzntsv]] Open issues.
- [ ] **CMS connection-string location** — web.config? appsettings? hardcoded в DLL? Если hardcoded — нужен rebuild (build env вопрос). См. note в [[../.wiki/concepts/cms-admin-assets-root-folder-seed]] §"Долгосрочный TODO".
## Risks
- **WAN latency IIS→MSSQL:** 10-30ms vs localhost. Большинство CMS-операций batchey, не latency-sensitive. **Pre-cutover benchmark обязателен** (acceptance 5).
- **Express Edition limits:** 10 GB/DB, 1.4 GB RAM, 1 socket / 4 cores. Max .mdf сейчас 968 MB — запас 10x. Если `stostayer` начнёт расти — early warning через monitoring (separate task).
- **MSSQL Linux compat:** некоторые edge-case T-SQL отличаются (CLR, FileStream, full-text). Smoke обязателен — `EXEC sp_helpdb` + проверить нет ли CLR assemblies / FileStream filegroups в prod DBs.
- **TLS overhead:** raw-TCP через traefik adds <1ms — negligible.
- **VDS RAM tight:** owncloud `anon` 282 MB + gitea 834 MB + verdaccio 226 MB + DBs 285 MB + traefik 52 MB + redis 6 MB = ~1.7 GB реально используется (page-cache reclaimable). MSSQL 2 GB влезает с запасом 4 GB до OOM.
- **Disk free на VDS не проверен** (ops-mcp read-only docker). Нужно ~3 GB MSSQL restored + ~5 GB free для backup'ов. **Проверить `df -h /opt/stacks` ssh'ем перед стартом.**
- **Cutover rollback:** revert возможен только если windows-host MSSQL container оставлен running (read-only желательно но не критично) 48ч после cutover. Acceptance 8 это закладывает.
## Notes
- **Зависит от:** `minio-imgproxy-vds-migration` (нет — независимы).
- **Зависимая follow-up:** списать `cms-stopgap-backup-daily` cron после успешного first VDS backup-pipeline run.
- **Atomic revert (full):** revert CMS web.config → windows-host MSSQL; восстановить cms-stopgap-backup-daily cron; на VDS — `docker compose down -v` для mssql stack; удалить mssql ноги из `run.sh`; remove traefik mssql entrypoint; ufw deny 1433/tcp.