thread-master/docs/product/haixun-deployment/plan.md

182 lines
8.3 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.

# Plan: 設定驅動的多主機正式部署
> Status: `draft-for-review`
> Source: `requirements.md`, `spec.md`
> Last updated: `2026-07-18`
> Implementation: not started; this plan does not authorize a live deployment
## 1. 交付策略
1. 先建立設定 schema、preflight 與空 VM bootstrap再碰正式服務。
2. 先完成 WireGuard 與 Registry確保後續 image 只需本機 build、遠端 pull。
3. 資料層先行Atlas connectivity、Redis persistence、MinIO persistence/bucket/backup。
4. 將現有共同 release 拆成 frontend、backend、worker、crawler、ops images。
5. 先單節點驗證,再做 frontend/backend rolling pool 與 Edge 動態 upstream。
6. first deploy、一般 deploy、config-only deploy、rollback 必須是不同明確路徑。
7. 所有 live 操作前先在全新 Ubuntu 24.04 VM 的 staging inventory 演練。
## 2. 里程碑
### M0 - 文件、設定契約與安全邊界
- 建立 `deployment.yml.example` 與 Vault schema。
- 定義 host role、覆寫規則、WireGuard 自動配號、image tag 與目錄契約。
- 實作 `doctor`/`preflight`,拒絕缺 IP、重複 IP、DNS 未指向、SSH/sudo 不可用與 unsupported OS。
- 定義正式環境防火牆矩陣、Atlas 固定出口與 TLS 前置條件。
完成定義:不連線部署即可驗證完整設定;錯誤訊息能指出欄位與 host。
### M1 - 空 VM bootstrap
- 用 Ansible raw task 支援無 Python 的 Ubuntu 24.04。
- 安裝 Python、Docker/Compose、WireGuard、UFW、chrony、fail2ban、unattended-upgrades。
- 建立 `/opt/haixun`、`/etc/haixun`、`/var/lib/haixun`、服務帳號與權限。
- 設定 Docker log rotation、daemon 啟動、Registry trust/login hook。
- 防火牆先保留 SSH再按 role 套規則。
- bootstrap 可重跑,且不修改/清除 data volume。
完成定義:七種角色的空 VM 都可從只有 SSH/sudo 到 bootstrap ready第二次執行為 no-op 或安全更新。
### M2 - WireGuard、Registry 與本機 build pipeline
- 依 inventory 自動分配 WireGuard IP建立 peer 並驗證連通。
- 配置固定出口節點供 Atlas 連線。
- 部署帶 TLS/auth/persistent volume 的自架 Registry。
- Edge/Registry DNS 檢查與 Let's Encrypt 自動申請/續期。
- 新增 frontend/backend/worker/crawler/ops Dockerfile 與 Buildx build/push 指令。
- image 使用 git SHA保存上一個成功 tag 供 rollback。
完成定義:遠端 VM 不具備 source tree 也能 pull 並啟動測試 imageRegistry 重啟後 image 仍存在。
### M3 - Atlas、Redis、MinIO 與 first data initialization
- production 移除本機 Mongo 假設,所有 runtime 讀取 Atlas URI。
- Redis 獨立 Composeauth、AOF、volume、health、backup/restore。
- MinIO 獨立 Composevolume、health、bucket/policy idempotent init、backup/restore。
- ops image 提供 migration/init/seeder。
- seeder 改為由 Vault 設定 admin email/display name/password既有資料不覆寫。
- 將現有 backup、monitoring、reset 腳本從本機 Mongo 假設拆開Atlas 備份交由 Atlas Backup/PITR。
完成定義:空 Atlas database 可按 migration -> init -> seed 建立重跑不重複資料、不重設密碼Redis/MinIO restart 後資料保留。
### M4 - 應用角色拆分與無狀態修正
- frontend image 只含 production static build。
- backend image 含 gateway 與固定 extension ZIP path。
- worker image 含 Go worker、Node profile scraper、相容 Chromium。
- crawler sidecar 可設定 bind address、有 health endpoint只走 private Docker network。
- role-specific env/template 只下發所需 secret。
- gateway readiness 補 Mongo + Redisfrontend 提供 build versionworker 啟動檢查 identity/connectivity。
完成定義frontend/backend/worker 可分別 build、push、deploy、restart刪除任一 app container 後可從 image/config 重建且無業務資料遺失。
### M5 - 多節點、Edge 與一般部署
- Edge 依 inventory 產生 frontend/backend upstream。
- backend/frontend 採 `serial: 1` rolling recreatereadiness 後才加入流量。
- worker 支援指定 host 或整組新增/更新worker ID 唯一。
- config-only deploy 原子同步設定並只 recreate 指定角色。
- status/logs/restart/rollback 以 role/host 過濾。
- migration `run_once` 且先於 backend recreate失敗立即停止。
完成定義:增加一個 IP 可加入新 worker增加 frontend/backend IP 可健康註冊;部署期間其他健康節點持續服務。
### M6 - First deploy orchestrator、備份與演練
- `make first-deploy` 串接 M0-M5 checkpoint但每一步仍可單獨重跑。
- 建立 Redis/MinIO/Registry restore runbook 與 Atlas restore 責任邊界。
- 提供首次部署報告host、role、WG IP、image tag、health、TLS、backup 與單點警告。
- 在全新 staging VM 完成安裝、失敗續跑、config-only、加節點、rollback、重啟持久性與公網封鎖測試。
- live deployment 必須由使用者另行確認,不因完成程式碼而自動執行。
完成定義:從設定檔與空 VM 到完整 staging 可用,不登入遠端手動安裝或改設定。
## 3. 預計檔案落點
```text
apps/web/Dockerfile
apps/backend/Dockerfile.gateway
apps/backend/Dockerfile.worker
apps/backend/Dockerfile.ops
apps/backend/crawler/Dockerfile
deploy/prod/
Makefile
ansible.cfg
deployment.yml.example
secrets.vault.yml.example
inventory/
playbooks/
bootstrap.yml
first-deploy.yml
deploy.yml
database.yml
status.yml
roles/
common/
wireguard/
registry/
edge/
frontend/
backend/
worker/
redis/
minio/
templates/
scripts/
doctor.sh
preflight.sh
build.sh
push.sh
deploy.sh
```
現有單機 production scripts 在新流程驗收前不直接刪除;實作時先標示 legacy確認沒有現役依賴後再決定移除避免中斷既有環境。
## 4. 驗證矩陣
| ID | 驗證 |
|----|------|
| DEP-01 | 空 Ubuntu 24.04 無 Python VM 可 bootstrap |
| DEP-02 | bootstrap 重跑不清資料、不重建 secret |
| DEP-03 | 只填 SSH IP 即可自動配置 WireGuard IP |
| DEP-04 | Registry TLS/auth/persistence 正常 |
| DEP-05 | 應用 image 全由本機 build遠端無 source/build |
| DEP-06 | Atlas migration/init/seed 順序正確且可重跑 |
| DEP-07 | seed 不覆寫既有管理員密碼 |
| DEP-08 | Redis/MinIO restart 後資料保留 |
| DEP-09 | config-only deploy 不產生新 image且新設定生效 |
| DEP-10 | backend/frontend rolling deploy 保留健康服務 |
| DEP-11 | 新增 worker IP 後只有新 host 被 bootstrap/deploy |
| DEP-12 | 新增 backend/frontend 後 Edge 只加入健康節點 |
| DEP-13 | migration 失敗時 backend 保持舊版 |
| DEP-14 | rollback 可切回上一個成功 image tag |
| DEP-15 | 公網無法直連 Redis/MinIO private API/backend/crawler |
| DEP-16 | crawler sidecar 可用且 host 無公開 crawler port |
| DEP-17 | Atlas 連線顯示固定出口 IP |
| DEP-18 | 備份與還原演練有可驗證結果 |
## 5. 風險與後續
| 風險 | 第一版處理 |
|------|------------|
| Redis/MinIO/Registry/Edge 單點 | 明示風險、持久化、備份、restore runbookHA 後續里程碑 |
| 全 mesh 新增節點需更新 peers | 由 Ansible inventory 統一生成並分批套用 |
| Atlas 固定出口節點故障 | 第一版接受單點;文件化切換出口與 allowlist 流程 |
| Outbox 全域 lock 限制 worker 擴縮 | 部署不誤稱 Outbox 已水平擴充;另立應用 task 改 due query/claim/concurrency |
| 外部發文 at-least-once 重複 | 不在部署層假裝解決,保留既有 lease 風險並另案處理 |
| seeder 目前寫死管理員資料 | M3 先修成 Vault 可設定,再允許 first deploy seed |
| health 目前只檢查 Redis | M4 補 Mongo readiness避免壞節點進 upstream |
| 舊單機腳本仍可能在使用 | 新流程先並存並標 legacy不自動刪除或改動現役服務 |
## 6. 實作前仍需填入的實際值
- 所有 VM SSH IP、user、port、private key。
- Edge、Registry 網域與已完成的 DNS A/AAAA record。
- Atlas SRV URI、database user 與固定出口 allowlist。
- Registry、Redis、MinIO、JWT、加密、Crawler、Provider、SMTP 等 Vault secret。
- 初始管理員 email、display name、password。
- 各 VM CPU architecture、磁碟掛載與備份目的地。
上述值未備齊時可完成程式與 staging 測試,但不得執行正式 first deploy。