Files

13 KiB
Raw Permalink Blame History

module-10-vm2. Runbook развёртывания ВМ2 Processing

Статус: целевой runbook репозитория ВМ2.
Общий контракт (VPC/SG, PG, S3, роли deploy, TLS процедура, порядок cutover) — arch-10-deployment.md.
ВМ1 — module-10-deployment-vm1.md и её fresh production runbook. Не переносить команды ВМ1 и не шарить Compose/IAM/secrets.

1. Границы

ВМ2 владеет nginx public 80/443 (только exact CRM webhook) и private 8443 (Message Safety), message-safety API/worker, bitrix-sync, Redis Safety и Collector в Compose. KESL 12.4 standalone и root-owned fail-closed broker работают на host VM2 вне Compose; broker слушает /run/han-kesl/scan.sock. 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/broker concurrency в пределах подтверждённой KESL capacity; 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; предел задаёт проверенная throughput host KESL/broker.

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), DNS/NTP, SigNoz 4317, PG; для host KESL — только approved update sources по операторскому KESL runbook. Постоянный 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

Сервисы Compose: public/private nginx, message-safety-api, message-safety-worker, bitrix-sync, Redis Safety, local otel-collector. clamd/freshclam удалены.

Networks: public (только nginx webhook/ACME), backend, egress (bitrix-sync, Safety worker → S3/PG/DNS, collector → SigNoz), observability. Safety API/Redis без общего internet egress. Worker получает только read/write bind Unix socket /run/han-kesl/scan.sock, а не доступ к host command execution.

Volumes: Redis Safety data (rebuildable), ACME public, otel-queue + init. KESL database/runtime не являются Compose volumes. 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).

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_<latin letters or digits>ufCrm_<latin letters or 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. Выполнить operator KESL runbook: проверить KESL 12.4 standalone, database date и ежечасное обновление.
  2. enable/start broker socket/service; проверить status и owner/group/mode /run/han-kesl/scan.sock.
  3. Redis Safety, otel-queue-init, Collector.
  4. Safety API/worker и bitrix-sync; files остаётся fail-closed до успешной проверки broker.
  5. nginx последним: оба TLS, exact webhook, capability health, KESL database age, negative ingress/egress.

До enablement bitrix-syncsync_disabled. Safety v2 capability text|links|files|worker. Redis Safety не core gate readiness.

11. Public smoke ВМ2

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 + 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 и KESL

deploy без root login:

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.

KESL обновляет базы на host ежечасно по отдельному operator KESL runbook. Seed max_signature_age_hours=240, schema max 720. Stale/failed update выключает только files и создаёт alert; scanner error не становится allow. Broker является custom integration: формат/exit semantics kesl-control --scan-file --action Inform и throughput подтверждаются target-VM gates.

15. Rollback, ops, incidents ВМ2

Redis Safety restore — empty/clean, lazy cache (module-04-redis-vm2.md). Routine: KESL version/database date и hourly update, broker/socket status, 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 и KESL/broker 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. Ссылки