15 KiB
AWOOOI 主機角色與負載平衡評估
Version: v1.1 Last updated: 2026-06-13 Asia/Taipei Scope: 110 / 120 / 121 / 188;112 是 Kali,不納入本輪服務搬遷。
1. 結論
120 / 121 目前是 K3s control-plane AA,不是傳統一主一從 AS。
但這只代表 Kubernetes 控制面雙節點可用,不代表業務 workload 已經 AA。2026-06-13 00:13 live check 顯示:
| 項目 | 120 mon |
121 mon1 |
判讀 |
|---|---|---|---|
| K3s unit | k3s active、k3s-agent inactive |
k3s active、k3s-agent inactive |
兩台都是 server / control-plane |
| Kubernetes role | control-plane |
control-plane |
控制面 AA |
| Taint / schedulable | 無 taint、Unschedulable=false |
無 taint、Unschedulable=false |
120 可以排程 |
| CPU / memory | CPU 約 2%、Memory 約 8% |
CPU 約 3%、Memory 約 20% |
兩台都有餘裕,121 較高 |
| Pod 實際落點 | awoooi-api 2 顆、awoooi-web 1 顆、awoooi-worker 1 顆 |
awoooi-web 1 顆、auto-repair canary、部分 CronJob 歷史 Pod |
API 仍集中在 120,Web 已分散 |
專業判定:
控制面:AA。業務 workload:Web 已分散,但 API 兩個 replica 都在 120,不算完整 workload AA。資料層:不可直接視為 AA;若仍依賴 188 PostgreSQL 或 local-path PVC,120/121 只是承載層,不是資料高可用層。下一步:AWOOOI API / Web / Worker topology spread 已進 Gitea main 並由 ArgoCD 套用;後續才能規劃把 110 / 188 無狀態服務搬進 K3s,不先搬核心資料庫。
2. 現況負載與角色
2.1 110
110 是目前最混合、最需要拆角色的主機。
| 類別 | Live evidence | 負載/風險 |
|---|---|---|
| Public gateway / edge | 80/443、多個 public route upstream |
改 Nginx / firewall 影響面最大 |
| Registry / image supply | Harbor 5000、registry / portal / jobservice / db / redis |
K3s image pull 依賴它,不適合先搬 |
| Source / CI | Gitea 3001、runner / build 相關目錄 |
build / dump 期間會推高 CPU |
| Observability / incident tools | Prometheus、Alertmanager、Sentry / Snuba / Kafka / ClickHouse | 容器多、啟動順序複雜 |
| Product services | StockPlatform v2、agent-bounty、Tsenyang、VTuber、Bitan 等 | 多數可逐步轉 K3s,但資料層需先分離 |
| Backup control | /backup/scripts/*、每日備份與 offsite sync |
本輪恢復完成前不可搬 |
2026-06-12 15:19 live check:110 RAM 62Gi、root disk 89%、load 約 2.79 / 3.01 / 3.25;正在跑 Gitea dump 時 top CPU 包含 gitea dump、ClickHouse、Docker、Kafka。
2026-06-13 00:14 live check:110 systemctl is-system-running=running、failed units 0、load 約 4.45 / 3.28 / 2.89、Swap 166Mi/7.8GiB;top CPU 主要是 Gitea、ClickHouse、Kafka、Docker 與一個 prisma db push 工作。判讀:110 不在服務故障狀態,但仍是高混合負載主機,第一批應先移走無狀態 app 層與 build/preview 類工作。
2.2 188
188 是資料、AI、觀測與自動化中心。
| 類別 | Live evidence | 負載/風險 |
|---|---|---|
| Data layer | PostgreSQL 5432、Redis 6379、momo DB、product DBs |
多服務依賴,不可直接熱搬 |
| momo | momo-scheduler、momo-pro-system、Telegram bot |
有資料一致性與匯入流程風險 |
| AI / workflow | OpenClaw、LiteLLM、Open WebUI、n8n | 可拆,但需 provider route / secrets / queue 邊界 |
| Observability | SignOz、ClickHouse、Zookeeper、Grafana、Prometheus、Alertmanager、Loki | stateful 且啟動重,不適合第一批 |
| Product services | VibeWork、Tsenyang、agent-bounty 等 | 可按 stateless / stateful 拆分 |
2026-06-12 15:19 live check:188 RAM 62Gi、root disk 52%、Swap 約 2Gi/8Gi;top CPU 包含 momo-scheduler、Next.js、ClickHouse。
2026-06-13 00:14 live check:188 systemctl is-system-running=degraded,failed units 是 certbot.service 與 snap.certbot.renew.service;cold-start 仍確認 PostgreSQL、Redis、momo、SignOz、Docker services 綠。判讀:這是 TLS 自動續期治理債,不是本輪 K3s workload balancing 的業務服務阻斷。
2.3 120 / 121
120 / 121 是 K3s control-plane pair,目前最適合承接標準化容器 workload。
| 類別 | 目前狀態 | 判讀 |
|---|---|---|
| K3s control-plane | 120 / 121 都 Ready control-plane |
控制面 AA |
| Workload placement | API / Web 已分散在 120 / 121;Worker 單副本在 121 | AWOOOI core workload 已完成第一階段均衡 |
| 記憶體餘裕 | 120 約 29Gi available;121 約 27Gi available |
有承接空間 |
| Storage | root 各約 490G,本輪 120 剛做 root fsck 後恢復 | 不應立刻承接核心 stateful |
| Network | VIP 192.168.0.125 / NodePort 已用於 AWOOOI |
適合承接 ingress 後方 app |
3. 可以搬、暫緩搬、禁止直接搬
3.1 第一批:可優先搬到 K3s 的服務
條件:無狀態、可重新 build、已有容器 image、資料庫可先留在原 host、health endpoint 清楚。
| 優先序 | 候選 | 來源主機 | 建議策略 | 原因 |
|---|---|---|---|---|
| P1-A | Tsenyang website | 110 / 188 都有部署痕跡 | 先做單一 canonical deployment,再進 K3s | 靜態/Next 類服務,資料風險低 |
| P1-A | VTuber web/admin/api | 110 | app 先搬;DB 留 110,備份通過後再評估 DB | 可降低 110 Docker container 數 |
| P1-A | Bitan app / PostgREST edge | 110 | app edge 先搬;PostgreSQL 暫留 110 | public route 可用 K3s NodePort / ingress |
| P1-B | StockPlatform web/admin/api/edge | 110 | app 層先搬;Postgres/Redis 暫留 110 | 目前 110 服務多,拆 app 有效 |
| P1-B | agent-bounty web / worker | 110 / 188 | 先統一來源與 port,再搬 app;DB/Redis 暫留 | 兩台都有部署痕跡,需先消除重複角色 |
| P1-B | 輕量內部工具 / preview | 188 | 容器標準化後搬 | 對核心資料面影響小 |
第一批完成標準:
- 每個 deployment 有
requests/limits。 - replicas >= 2 的服務必須有 pod anti-affinity 或 topology spread。
- 120 / 121 上 Pod 落點 max skew <= 1。
- public route、internal VIP、health endpoint、Alertmanager visibility、備份矩陣都通過。
3.2 第二批:可以規劃,但不能在恢復期直接搬
| 候選 | 來源主機 | 需要先完成 |
|---|---|---|
| Product-specific PostgreSQL / Redis | 110 / 188 | backup / restore drill、RPO/RTO、PVC 策略、回滾路徑 |
| Langfuse / analytics 類服務 | 110 | DB / object storage / secret route 梳理 |
| n8n / workflow | 188 | workflow export、credential escrow evidence、callback URL 切換 |
| Open WebUI / AI 工具 | 188 | model provider route、volume backup、外部 endpoint fallback |
| Docker registry mirror / cache | 110 / 188 | image retention、auth、K3s pull secret、Harbor 分工 |
3.3 不建議直接搬的核心
| 對象 | 原因 | 正確路徑 |
|---|---|---|
| Harbor | K3s image supply 依賴它;搬壞會反過來讓 K3s deploy 失敗 | 先做 replica / mirror / restore 演練 |
| Gitea | source-of-truth / CI 影響大,dump / runner / SSH / webhook 邊界多 | 先獨立備份與 restore drill |
| Sentry / Snuba / Kafka / ClickHouse | stateful、容器多、啟動順序敏感 | 先拆 consumer load,再評估專用 observability host |
| SignOz ClickHouse / Zookeeper | stateful 且重 IO | 需要獨立 storage 與 retention plan |
| AWOOOI / momo 主 PostgreSQL | 多系統依賴且資料一致性要求高 | 先建立 replica / tested restore,不做熱搬 |
/backup 控制面 |
本輪恢復與 DR 證據中心 | 等 DR scorecard complete 後另開遷移案 |
4. 新資料庫能不能放 120 / 121
可以,但要分等級。
| 等級 | 是否可放 | 條件 |
|---|---|---|
| Dev / staging / demo DB | 可以 | 明確標示非 production;每日備份;可接受重建 |
| 新產品的低風險 production DB | 可以試點 | 必須先完成 backup、restore drill、PVC 保留策略、監控與 offsite sync |
| 核心 production DB | 暫不建議 | 目前 120/121 只有兩節點 control-plane,若使用 local-path PVC,Pod 可重建不代表資料可 failover |
| 高可用 production DB | 需要另案 | 需要 PostgreSQL operator、replica、storage replication 或外部 DB HA,不是單純 kubectl apply postgres |
判定原則:
Kubernetes 可以重排 Pod,不等於資料會跟著安全重排。
沒有 restore drill 的 DB,不算可遷移完成。
沒有 storage replication 的 stateful workload,不算 AA。
5. 120 / 121 Workload 均衡修正
目前不是 taint 或 cordon 問題,因為 120 / 121 都 schedulable。主要原因是 120 長時間不可用後,既有 Running Pod 不會自動搬回來;live deployment 也尚未帶 topologySpreadConstraints,所以 scheduler 只有 soft anti-affinity,仍可能把同一服務副本放在同一台。
5.1 立即可做的只讀檢查
ssh wooo@192.168.0.120 '
sudo kubectl get nodes -o wide
sudo kubectl get pods -A -o wide
sudo kubectl top nodes
sudo kubectl top pods -A --sort-by=cpu
'
5.2 受控修正順序
- 等 P0 備份鏈、offsite verifier、cold-start scorecard 通過。
- 在 AWOOOI
awoooi-prodAPI / Web / Worker 補topologySpreadConstraints。 - replicas >= 2 的服務使用
topologyKey: kubernetes.io/hostname,目標 120 / 121 分散。 - 單副本服務先不強制搬,除非有明確重啟窗口。
- 以 rolling restart 或下一次 deploy 觸發重排,不用暴力 delete 全部 Pod。
- 觀察
kubectl get pods -A -o wide、public route、Alertmanager、cold-start scorecard。
5.3 2026-06-13 Gitea / ArgoCD Live 狀態
已在 Gitea main commit acaae999 fix(k8s): add prod workload topology spread 補上:
k8s/awoooi-prod/05-deployment-web.yamlk8s/awoooi-prod/06-deployment-api.yamlk8s/awoooi-prod/08-deployment-worker.yaml
2026-06-13 12:43 live refresh 發現 ScheduleAnyway 仍可能讓 awoooi-api 兩顆副本合法同落 120;cold-start 仍綠,但不能宣稱 API workload balanced。
修正策略改為 maxSkew: 1、minDomains: 2、topologyKey: kubernetes.io/hostname、whenUnsatisfiable: DoNotSchedule。120 / 121 都 Ready 時,API / Web replicas=2 必須跨節點;Worker 單副本仍可跑,未來擴副本時也必須分散。
2026-06-13 13:00 追加判讀:只把 spread 改硬仍不夠。API rollout 時舊 Pod 仍在 120 terminating,新 ReplicaSet 兩顆都排到 121,scheduler 當下因舊 Pod 尚在而視為不違反 skew;舊 Pod 消失後 live API 反而變成 121 集中。因此 API / Web 也必須使用 maxSurge: 0、maxUnavailable: 1,讓 rollout 先釋出一格再排新 Pod,避免新舊 ReplicaSet 交錯造成最終偏斜。
2026-06-13 12:59 live verification:ArgoCD revision 60f653a0 synced;API / Web 均 ready=2/2,strategy maxSurge=0 / maxUnavailable=1,spread minDomains=2 / DoNotSchedule。awoooi-api pod 分別在 mon / mon1,awoooi-web pod 分別在 mon / mon1。完整 cold-start rerun PASS=83 WARN=0 BLOCKED=0。
驗證:
kubectl kustomize k8s/awoooi-prod可渲染三個topologySpreadConstraints。git diff --check通過。- ArgoCD
awoooi-prod已同步到 revisionacaae99986aee2e1f5630984981ccb0f2b676bb8,operationSucceeded。 - Live deployment 的 API / Web / Worker 均需有
topologySpreadConstraints。 awoooi-apireplicas=2:120 / 121 各一顆,否則是SERVICE_OK_PLACEMENT_DRIFT。awoooi-webreplicas=2:120 / 121 各一顆。awoooi-workerreplicas=1:可在任一節點;若 replicas > 1,必須跨 120 / 121 分散。- Rollout 後冷啟動:2026-06-13 00:34 final scorecard
PASS=83 WARN=0 BLOCKED=0。00:33 曾因 110known_hosts對 120 / 188 過期而短暫 blocked,已在備份後刷新 host key trust。
補充:rolling update 當下 API 新 Pod 先集中到 121,因為舊 Pod 正在 120 Terminating;後續以單顆 stateless API Pod 受控重排,最終達到 120 / 121 各一顆。沒有執行全 namespace delete、Docker restart、Nginx reload 或 firewall 變更。
建議的分散目標:
| Workload | 目標 |
|---|---|
awoooi-api replicas=2 |
120 / 121 各一個,whenUnsatisfiable=DoNotSchedule |
awoooi-web replicas=2 |
120 / 121 各一個,whenUnsatisfiable=DoNotSchedule |
awoooi-worker replicas=1 |
可留任一節點;多副本時 whenUnsatisfiable=DoNotSchedule |
| ArgoCD / Velero / kube-system 單副本 | 不急搬;先保持穩定 |
| DaemonSet | 120 / 121 各一個,已符合 |
6. 遷移階段與完成度
| 階段 | 狀態 | 完成度 | 說明 |
|---|---|---|---|
| A. 角色判定 | DONE | 100% | 120/121 已確認是 K3s control-plane AA;workload 尚未均衡 |
| B. 服務盤點 | DONE | 100% | 110 / 188 主要服務、port、container 類型已盤點 |
| C. 遷移分層 | DONE | 100% | 分為可優先搬、可規劃、禁止直接搬 |
| D. 實際 workload 均衡 | LIVE_VERIFIED | 100% | API / Web hard topology spread 與 no-surge rollout 已進 Gitea main / ArgoCD live;API/Web 皆 120 / 121 各一顆 |
| E. 第一批無狀態服務遷移 | NOT_STARTED | 0% | 需另開變更窗口與 rollback plan |
| F. Stateful 遷移 | BLOCKED_BY_DESIGN | 0% | 需要 storage / backup / restore / HA 設計 |
目前總結:評估完成 100%;AWOOOI core workload 均衡實作 100%;第一批服務遷移實作 0%。下一階段仍只應先搬無狀態 app 層,不搬核心資料服務。
7. 建議優先順序
| 優先序 | 工作 | 目的 |
|---|---|---|
| P0 | 完成 120 回復後備份鏈與 cold-start scorecard | 先證明平台回到可恢復基線 |
| P1 | 保持 AWOOOI prod topology spread,觀察後續 deploy 是否維持 120 / 121 分散 | 防止 API/Web 再度單邊集中 |
| P1 | 建立「第一批無狀態服務」K3s 遷移清單與 rollback plan | 安全釋放 110 Docker 壓力 |
| P2 | 先搬 app 層,不搬 DB;DB 仍走既有備份與連線 | 降低變更風險 |
| P2 | 對新 DB 建立 backup / restore drill 模板 | 讓未來新資料庫可安全落 K3s |
| P3 | 評估 Harbor / Gitea / Sentry / SignOz 的專用節點或 HA 架構 | 不把重 stateful 混進恢復期 |
8. 禁止事項
- 不在 P0 恢復鏈未完成時搬資料庫。
- 不用
kubectl delete pod --all當成重平衡手段。 - 不把 local-path PVC 的 Pod 重建誤認為資料高可用。
- 不把 Harbor / Gitea / Sentry / SignOz 直接丟進 120 / 121 來「平均負載」。
- 不在未補 backup / restore drill 前宣稱新 DB production ready。
- 不因為 120 / 121 是 control-plane AA,就宣稱整體服務 AA。