182 lines
8.3 KiB
Markdown
182 lines
8.3 KiB
Markdown
# 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 並啟動測試 image;Registry 重啟後 image 仍存在。
|
||
|
||
### M3 - Atlas、Redis、MinIO 與 first data initialization
|
||
|
||
- production 移除本機 Mongo 假設,所有 runtime 讀取 Atlas URI。
|
||
- Redis 獨立 Compose:auth、AOF、volume、health、backup/restore。
|
||
- MinIO 獨立 Compose:volume、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 + Redis;frontend 提供 build version;worker 啟動檢查 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 recreate,readiness 後才加入流量。
|
||
- 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 runbook;HA 後續里程碑 |
|
||
| 全 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。
|