Files
han-app/VM2_services/documentation/module-10-deployment-vm2.md
T

186 lines
12 KiB
Markdown
Raw 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.
# module-10-vm2. Runbook развёртывания ВМ2 Processing
> Статус: целевой runbook репозитория ВМ2.
> Общий контракт (VPC/SG, PG, S3, роли `deploy`, TLS процедура, порядок cutover) — [`arch-10-deployment.md`](../../architectory/arch-10-deployment.md).
> ВМ1 — [`module-10-deployment-vm1.md`](../../VM1_app/documentation/module-10-deployment-vm1.md). Не переносить команды ВМ1 и не шарить Compose/IAM/secrets.
## 1. Границы
ВМ2 владеет nginx public `80/443` (только exact CRM webhook) и private `8443` (Message Safety), `message-safety` API/worker, `clamd`/`freshclam`, `bitrix-sync`, Redis Safety, Collector. Guest API, Keycloak, SPA и SMS callback здесь не разворачиваются.
`<BACKEND_ROOT>` / `<BACKEND_REPO_URL>` — репозиторий ВМ2. Public ACME host — `<PROCESSING_PUBLIC_HOST>`. Private DNS `processing.internal` не публикуется.
## 2. Sizing и load gates
Начальный sizing без local Grafana: 4 vCPU, 8 ГБ RAM, 80 ГБ SSD, 4 ГБ swap; Redis 512 МиБ; Collector 512 МиБ + 510 ГБ queue; свободный диск ≥30%.
До real traffic — load test module-05 §15.4:
- sustained 10 text checks/s: p95 ≤2 с, p99 ≤5 с;
- sustained 2 file checks/s на 5 worker slots: среднее processing ≤2.5 с, p95 ≤60 с, public wait ≤300 с;
- 100 pending принимаются; 101-й file POST — retryable `503` без новой task;
- RPS overflow — `429 + Retry-After`;
- long Safety poll не блокирует WS/read API ВМ1;
- если gate не пройден — увеличить slots/CPU/clamd scan lanes; production traffic не открывать.
Monthly availability SLO Safety в MVP не задаётся. Scale-out/ВМ3: sustained CPU/RAM >70%, queue age >30 с, провал performance gates, contention `bitrix-sync` или независимый release cadence. Workers масштабируются первыми по queue depth, `clamd` — scan lanes.
## 3. Hardening и egress
Arch-10 §5 / arch-06. Public Docker ports — `80,443`. Private `8443` не internet SG.
Default-deny egress. Bootstrap window для registry/OS, затем закрыть. Оставить: S3, approved Bitrix portal (`bitrix-sync`), signature CDN (`freshclam`), DNS/NTP, SigNoz `4317`, PG. Постоянный open egress запрещён.
Отдельный IAM principal Selectel: только VM2 secret names.
## 4. Release layout и `.env` ВМ2
Checkout exact SHA. Структура: root Compose, `nginx`, Safety, `bitrix-sync`, Redis Safety, `observability`. Frontend-static нет.
Секреты ВМ2 (не в `.env` ВМ1):
- PG DSN роли Safety/`bitrix_sync` + CA;
- `MESSAGE_SAFETY_REDIS_URL`;
- Safety mode file `/etc/han-chat/message-safety-mode.env` (не repository `.env`);
- S3 **read-only quarantine** credentials;
- internal TLS PEM `8443`;
- Bitrix sync webhook tokens, portal credentials, `BITRIX_WEBHOOK_ALLOWED_CIDRS`;
- OTEL exporter secrets.
`BITRIX_SYNC_ENABLED=false` до §9. Paired tokens local app ВМ1 здесь не живут.
## 5. Images
Один immutable image API+worker Safety, отдельные containers. MVP: 1 API + 1 worker с 5 file-worker slots. Build без production secrets. Frontend на ВМ2 не собирается.
## 6. Root Compose ВМ2
Сервисы: public/private nginx, `message-safety-api`, `message-safety-worker`, `clamd`, `freshclam`, `bitrix-sync`, Redis Safety, local `otel-collector`.
Networks: `public` (только nginx webhook/ACME), `backend`, `egress` (freshclam, bitrix-sync, Safety worker → S3/PG/DNS, collector → SigNoz), `observability`. Safety API/clamd/Redis без общего internet egress.
Volumes: Redis Safety data (rebuildable), ClamAV signatures, ACME public, `otel-queue` + init. Frontend-static нет. Published: nginx 80/443; `8443` только SG ВМ1/ops.
Compose gate — arch-10 применительно к этому Compose.
## 7. TLS ВМ2
Public: arch-10 §9, `-d <PROCESSING_PUBLIC_HOST>`. HTTP webhook paths — без redirect с query token ([`module-03-nginx-vm2.md`](module-03-nginx-vm2.md)).
Private `8443`: сертификат internal CA, SAN = private DNS. Не Let's Encrypt. Caller ВМ1 проверяет CA bind.
## 8. Миграции Safety
Stub не создаёт PG tables. Production v2: schema `message_safety`, lease/fencing smoke. Первая migration создаёт `config_versions` и seed version 1; readiness без ровно одной valid active version не открывается.
Config-only rollout — отдельный root-owned job под config-admin role: immutable draft, JSON Schema, artifacts, approvals, транзакционный activate. Runtime — только `SELECT` к config. Rollback не реактивирует retired row: клон в новую monotonic version.
## 9. Controlled rollout `bitrix-sync`
До `BITRIX_SYNC_ENABLED=true`:
1. custom Contact fields и env names; universal CRM `UF_CRM_<digits>``ufCrm_<digits>`;
2. smart process конфликтов и `bitrix_sync.settings`;
3. входящий webhook техпользователя, права module-07 §13;
4. два HTTP-webhook на `https://<PROCESSING_PUBLIC_HOST>/bitrix/sync/webhook/...?token=...`; query/body не в журналах; local app handler не создавать;
5. expand migrations `han_app` (делает ВМ1/api-backend) затем `bitrix_sync`; GRANT и negative tests;
6. `cutover_watermark`; отменить pending до него с `initial_full_sync_cutover`;
7. не создавать backfill;
8. image с sync disabled: `/health/live`, `sync_disabled`, smoke Bitrix methods;
9. открыть на nginx ВМ2 только два exact routes для `BITRIX_WEBHOOK_ALLOWED_CIDRS`; valid/invalid source IP; нет запросов на ВМ1;
10. включить sync; canary post-watermark; нет CRM ID в App DB;
11. canary window: queue age, 429, DLQ, webhook lag, reconciliation, source-IP rejects.
Rollback: закрыть webhook или `503`; `BITRIX_SYNC_ENABLED=false`; ВМ1 не изменяется; mapping не удалять; schema не downgrade.
### Изменение source IP Битрикс24
Сигнал: всплеск Contact из reconciliation + `webhook_rejected_total{reason="source_ip"}`.
1. Сопоставить bounded-retention журнал rejects; query/body не извлекать.
2. Подтвердить адрес как инфраструктуру Битрикс24; query token сам по себе недостаточен.
3. Минимальный CIDR в version-controlled allow-list, review, `nginx -t` через deployment unit.
4. Safe reload; приём webhook без query/body в logs.
5. Rejects прекратились, lag нормализовался.
6. Ошибочное расширение — rollback allow-list. Автодобавление IP запрещено.
## 10. Ordered startup ВМ2
1. Redis Safety, `otel-queue-init`, Collector;
2. `clamd`/`freshclam`, Safety API/worker, `bitrix-sync`;
3. nginx последним: оба TLS, exact webhook, capability health, signature age, negative ingress/egress.
До enablement `bitrix-sync``sync_disabled`. Safety v2 capability `text|links|files|worker`. Redis Safety не core gate readiness.
## 11. Public smoke ВМ2
```bash
curl -I http://<PROCESSING_PUBLIC_HOST>/
curl -i https://<PROCESSING_PUBLIC_HOST>/internal/sync/v1/status
curl -i https://<PROCESSING_PUBLIC_HOST>/bitrix/sync/webhook/contact
openssl s_client -connect <PROCESSING_PUBLIC_HOST>:443 -servername <PROCESSING_PUBLIC_HOST>
```
Expected: HTTP redirect/ACME policy; internal 404; GET webhook 405/404; отдельный cert. POST webhook — отдельный form-urlencoded test allowed/denied IP без query token в history.
Private `8443` проверяется с ВМ1/ops, не из интернета.
## 12. Observability ВМ2
[`module-09-observability-vm2.md`](module-09-observability-vm2.md) + arch-07. Paging: MOCK, Safety config, sync DLQ, queue age.
## 13. Cutover, rollback, reprovision
Cutover gates: private TLS chain/SAN; Safety v2 PG migration и lease/fencing smoke; capability `text|links|files|worker`; S3 Gate 4 (Safety read-only); performance §2; egress negative tests. Approvals: Safety Service, Rule Pack, Security, Product, Operations. Только после них ВМ1 переключает `MESSAGE_SAFETY_URL`.
При потере ВМ2 fail-open запрещён. Reprovision из immutable image; отдельный IAM; Redis пустой; gates повторяются. RTO ≤4 ч; restore rehearsal ≥2 раза в год.
Rollback ВМ2 не требует изменения nginx ВМ1. Caller rollback — runbook ВМ1.
## 14. Emergency MOCK и Freshclam
`deploy` без root login:
```bash
sudo /usr/local/sbin/han-message-safety-mode mock --text-free true --file-free true
sudo /usr/local/sbin/han-message-safety-mode mock --text-free true --file-free false
sudo /usr/local/sbin/han-message-safety-mode mock --text-free false --file-free true
sudo /usr/local/sbin/han-message-safety-mode mock --text-free false --file-free false
sudo /usr/local/sbin/han-message-safety-mode standard
```
Helper `root:root 0755`; sudoers только этот executable. Config `root:han-message-safety 0640`, GID `10001`. Нет auto-expiry; incident не закрывать без `standard` и canary. File в MOCK — `scan_status=bypassed`, не `clean`. `deploy` не пишет Compose/Docker.
`freshclam`: controlled egress только к signature CDN. Seed `max_signature_age_hours=240`, schema max `720`. Stale/failed update выключает только `files` и alert. Новая база — integrity/EICAR, atomic activate; regression — предыдущая валидная база.
## 15. Rollback, ops, incidents ВМ2
Redis Safety restore — empty/clean, lazy cache ([`module-04-redis-vm2.md`](module-04-redis-vm2.md)). Routine: signature age, Safety queue, sync DLQ/webhook lag, Collector, disk, egress still deny.
Incident: Safety timeout — checkpoint, не новый task id; Bitrix down — circuit/DLQ, webhook `503`; MOCK page — вернуть standard; cert processing host и private CA.
Потеря ВМ2: новая VM в VPC, hardening, private DNS, secrets из VM2 IAM, empty Redis, Safety migrations, nginx webhook+8443, **не** менять public routes ВМ1 до готовности; затем повторить cutover gates.
## 16. Definition of Done ВМ2
Дополнительно к arch-10 §12:
- Compose/nginx/Redis Safety/Collector прошли профильные compose/nginx gates;
- private `8443` fail-closed до cutover, затем только источники ВМ1;
- webhook allow-list и preflight `BITRIX_SYNC_ENABLED` согласованы;
- capability/load gates module-05;
- MOCK helper и Freshclam rehearsal;
- observability ВМ2 + redaction (нет query/body/file content);
- cutover §13 не объявлен выполненным только документацией.
## 17. TBD ВМ2
D-TBD5 Safety v2; D-TBD6 bitrix-sync cutover; performance gates уже в §2.
## 18. Ссылки
- Контракт: [`arch-10-deployment.md`](../../architectory/arch-10-deployment.md).
- ВМ1: [`module-10-deployment-vm1.md`](../../VM1_app/documentation/module-10-deployment-vm1.md).
- Указатель: [`module-10-deployment-runbook.md`](module-10-deployment-runbook.md).
- Safety / sync / nginx: [`module-05-message-safety.md`](module-05-message-safety.md), [`module-07-bitrix-sync.md`](module-07-bitrix-sync.md), [`module-03-nginx-vm2.md`](module-03-nginx-vm2.md).