- ADR-037 監控增強架構 - MONITORING_MASTER_PLAN 主計畫 - MASTER_EXECUTION_SCHEDULE 執行排程 - Phase D/E/Worker HPA Runbooks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
571 lines
27 KiB
Markdown
571 lines
27 KiB
Markdown
# AWOOOI 整體整合架構統合設計
|
||
|
||
> **文件類型**: 統合架構設計(Single Source of Truth for Integration)
|
||
> **優先級**: 🔴 統帥最高指令
|
||
> **建立**: 2026-03-29 13:27 (台北)
|
||
> **核心命題**: 所有節點必須在同一座大腦的神經網路中協同運作,不允許孤島。
|
||
|
||
---
|
||
|
||
## 第一部分:現況誠實盤點(精確)
|
||
|
||
### 已確認:比稽核報告更樂觀的部分
|
||
|
||
| 項目 | 稽核報告誤判 | 真實現況 |
|
||
|------|------------|---------|
|
||
| Worker SIGTERM 處理 | 報告說「缺失」 | ✅ **已實作**(`signal_worker.py:450-455`)— `signal.signal(SIGTERM)` + `shutdown_event` |
|
||
| Worker 優雅關機流程 | 報告說「需要實作」| ✅ **已實作**(`stop()` 方法,有心跳機制) |
|
||
| SignOz Webhook 路由 | 報告說「未部署」| ✅ **已路由**(`main.py:419`)|
|
||
|
||
### 已確認:比稽核報告更嚴峻的部分
|
||
|
||
| 項目 | 稽核報告版本 | 真實缺口 |
|
||
|------|------------|---------|
|
||
| Worker stop() timeout | 未提及 | ❌ **只有 5 秒**,AI 分析 30-60 秒會被強殺 |
|
||
| K8s terminationGracePeriodSeconds | 未提及 | ❌ **未設定**,K8s 預設 30 秒不夠用 |
|
||
| ESLint i18n 強制 | 說「CI 攔截」| ❌ **只有 TODO 注解**(`.eslintrc.js:20-22`),未實際安裝 plugin |
|
||
| Visual Regression 跨平台 | 說「截圖比對」| ❌ **Mac 與 CI Linux 字體渲染不同**,baseline 不能在 Mac 產生 |
|
||
| PostgreSQL HA | 說「Streaming Replication」| ❌ **無切換機制**,主庫掛了需要人工介入 |
|
||
| Redis HA | 完全未提及 | ❌ **無 Sentinel**,Redis 單點故障 |
|
||
| SSE Event Sourcing | 只設計了事件類型 | ❌ **F5 刷新後 GenUI 卡片全消失** |
|
||
| Kali 整合 | Cronjob 被動 | 🟡 層次太低,應升格為 SecurityAgent |
|
||
|
||
---
|
||
|
||
## 第二部分:完整整合地圖
|
||
|
||
### 2.1 系統神經網路拓撲
|
||
|
||
```
|
||
外部事件輸入
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Alertmanager :9093 Sentry :9000 SignOz :3301 │
|
||
│ GitHub Actions Kali Scanner K8s Events │
|
||
└──────────┬──────────────┬──────────────┬──────────────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌────────────────────────────────────────────────────────────────┐
|
||
│ AWOOOI API (K3s :32334) │
|
||
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌─────────────┐ │
|
||
│ │Alertmanager│ │Sentry │ │SignOz │ │Kali(未來) │ │
|
||
│ │Webhook │ │Webhook │ │Webhook │ │Webhook │ │
|
||
│ └────┬─────┘ └────┬─────┘ └─────┬─────┘ └──────┬──────┘ │
|
||
│ │ │ │ │ │
|
||
│ └──────────────┴──────────────┴────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||
│ │ Signal Worker (Redis XREADGROUP) │ │
|
||
│ │ ← 消費 awoooi:signals stream │ │
|
||
│ │ → IncidentEngine (聚合 / GraphRAG / 持久化) │ │
|
||
│ └──────────────────────────┬───────────────────────────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||
│ │ OpenClaw (192.168.0.188:8089) │ │
|
||
│ │ 決策引擎: RCA → Blast Radius → Risk → Action │ │
|
||
│ │ 工具: kubectl / SSH / Prometheus / SigNoz │ │
|
||
│ └──────┬─────────────────────┬────────────────────────────┘ │
|
||
│ │ │ │
|
||
│ ▼ ▼ │
|
||
│ Telegram Bot Approval DB (PostgreSQL) │
|
||
│ 統帥通知 審核佇列 │
|
||
└──────────────────────────────────────────────────────────────────┘
|
||
│
|
||
統帥批准 / 拒絕
|
||
│
|
||
┌────────────▼────────────┐
|
||
│ Auto-Repair Actions │
|
||
│ restart/scale/rollback │
|
||
└─────────────────────────┘
|
||
```
|
||
|
||
### 2.2 前端整合地圖
|
||
|
||
```
|
||
AWOOOI Web (K3s :32335 / Next.js)
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ │
|
||
│ ┌── Dashboard (/) ─────────────────────────────────────────┐ │
|
||
│ │ AutonomyIndexPanel ← GET /api/v1/stats/autonomy │ │
|
||
│ │ SystemPulseRow ← GET /api/v1/stats/overview │ │
|
||
│ │ DecisionZone ← SSE /api/v1/approvals/stream │ │
|
||
│ └──────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌── Omni-Terminal ─────────────────────────────────────────┐ │
|
||
│ │ Input Area → POST /api/v1/terminal/command │ │
|
||
│ │ ThinkingStream ← SSE /api/v1/terminal/stream/{id} │ │
|
||
│ │ GenUI Renderer ← event: render_ui │ │
|
||
│ │ Event Replay ← Redis List (Last-Event-ID) │ ← ❌ 缺失
|
||
│ └──────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌── Knowledge Base (/knowledge-base) ─────────────────────┐ │
|
||
│ │ ❌ 空白頁面,缺後端 API │ │
|
||
│ └──────────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ [深度調查跳脫入口] │
|
||
│ → SigNoz: http://192.168.0.188:3301 (新分頁) │
|
||
│ → Grafana: http://192.168.0.188:3000 (新分頁) │
|
||
│ → Sentry: http://192.168.0.110:9000 (新分頁) │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 第三部分:六大缺口的系統整合修復方案
|
||
|
||
### 缺口 1:Worker terminationGracePeriodSeconds 不足
|
||
|
||
**問題根源**:`signal_worker.py` 的 `stop()` 等 5 秒,但 AI 分析任務最長 60 秒。K8s 預設 `terminationGracePeriodSeconds: 30`。兩個值都不夠,且彼此沒有對齊。
|
||
|
||
**與整體整合的依賴**:
|
||
- Worker 縮容影響:HPA 縮容時 → K8s 發 SIGTERM → `stop()` 被調用 → 5 秒後強殺
|
||
- 上游依賴:Sentry 分析任務、Alertmanager 分析任務都在 Worker background task 中執行
|
||
- 下游影響:PostgreSQL 寫入可能不完整(Incident 狀態 Dirty)
|
||
|
||
**修復:三層數值對齊**
|
||
|
||
```yaml
|
||
# k8s/awoooi-prod/08-deployment-worker.yaml
|
||
# 修改 terminationGracePeriodSeconds
|
||
spec:
|
||
template:
|
||
spec:
|
||
terminationGracePeriodSeconds: 90 # 給 Worker 足夠時間完成當前任務
|
||
containers:
|
||
- name: awoooi-worker
|
||
lifecycle:
|
||
preStop:
|
||
exec:
|
||
command: ["/bin/sh", "-c", "sleep 5"] # 給 K8s 時間發 SIGTERM
|
||
```
|
||
|
||
```python
|
||
# apps/api/src/workers/signal_worker.py
|
||
# 修改 stop() 的 timeout 與 K8s terminationGracePeriodSeconds 對齊
|
||
|
||
async def stop(self) -> None:
|
||
if not self._running:
|
||
return
|
||
self._running = False
|
||
if self._task:
|
||
try:
|
||
# 從 5 秒改為 75 秒(比 terminationGracePeriodSeconds=90 少 15 秒緩衝)
|
||
await asyncio.wait_for(self._task, timeout=75.0)
|
||
except TimeoutError:
|
||
logger.warning("signal_worker_stop_timeout_forcekill")
|
||
self._task.cancel()
|
||
except asyncio.CancelledError:
|
||
pass
|
||
logger.info("signal_worker_stopped")
|
||
```
|
||
|
||
**整合驗證指令**:
|
||
```bash
|
||
# 模擬 K8s 縮容,確認 Worker 優雅關機
|
||
kubectl scale deployment awoooi-worker -n awoooi-prod --replicas=0
|
||
kubectl logs -n awoooi-prod $(kubectl get pod -n awoooi-prod -l app=awoooi-worker -o name) --tail=20
|
||
|
||
# 預期看到:
|
||
# shutdown_signal_received signal=15
|
||
# signal_worker_shutting_down
|
||
# signal_worker_shutdown_complete
|
||
# (整個流程在 90 秒內完成)
|
||
```
|
||
|
||
---
|
||
|
||
### 缺口 2:ESLint i18n 強制攔截(eslint-plugin-i18next)
|
||
|
||
**問題根源**:`.eslintrc.js:20-22` 只有 TODO 注解,未安裝 `eslint-plugin-i18next`。
|
||
|
||
**與整體整合的依賴**:
|
||
- 這是 i18n 清零後的**防護層**:清零是清過去的債,ESLint 是防未來的債
|
||
- 需在 `pnpm build` 和 `pnpm lint` CI 步驟中阻擋
|
||
- 影響:所有前端開發流程(AI 生成代碼也必須通過)
|
||
|
||
**修復:安裝並啟用 Plugin**
|
||
|
||
```bash
|
||
# Step 1: 安裝
|
||
cd apps/web
|
||
pnpm add -D eslint-plugin-i18next
|
||
```
|
||
|
||
```javascript
|
||
// apps/web/.eslintrc.js 修改後
|
||
module.exports = {
|
||
extends: [
|
||
'@awoooi/eslint-config/react',
|
||
'next/core-web-vitals',
|
||
'plugin:i18next/recommended', // ← 新增
|
||
],
|
||
plugins: ['i18next'], // ← 新增
|
||
parserOptions: {
|
||
project: './tsconfig.json',
|
||
tsconfigRootDir: __dirname,
|
||
},
|
||
rules: {
|
||
'@next/next/no-html-link-for-pages': 'off',
|
||
'no-console': 'off',
|
||
|
||
// 🚨 i18n 鐵律:所有 JSX 文字必須透過 t() 函式
|
||
// 違反此規則 = PR 阻擋(error 級別)
|
||
'i18next/no-literal-string': ['error', {
|
||
markupOnly: true, // 只攔截 JSX 文字節點(非 JS 字串)
|
||
ignoreAttribute: [ // 技術屬性不攔截
|
||
'className', 'id', 'href', 'src', 'type', 'key',
|
||
'data-testid', 'aria-label', 'placeholder'
|
||
],
|
||
}],
|
||
|
||
'@typescript-eslint/no-explicit-any': 'warn',
|
||
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
|
||
'@typescript-eslint/consistent-type-imports': 'warn',
|
||
'no-constant-condition': 'warn',
|
||
},
|
||
ignorePatterns: [
|
||
'node_modules', '.next', 'out', 'dist', 'test-results',
|
||
'*.config.js', '*.config.ts',
|
||
],
|
||
}
|
||
```
|
||
|
||
**與 CI 整合(必須加入 cd.yaml)**:
|
||
|
||
```yaml
|
||
# .github/workflows/cd.yaml 在 Build 之前加入 Lint 步驟
|
||
- name: 🔍 ESLint i18n 強制檢查
|
||
run: |
|
||
cd apps/web
|
||
pnpm lint
|
||
# 失敗 = 有硬編碼字串 = 直接阻擋部署
|
||
```
|
||
|
||
**⚠️ 重要**:第一次啟用 `eslint-plugin-i18next` 後,**現有的 40+ 違規會立刻全部報錯**。因此必須先完成 i18n 清零,再啟用此 Rule。**正確順序**:
|
||
1. i18n 清零(一次性修復 40+ 違規)
|
||
2. 安裝 eslint-plugin-i18next(啟用防護)
|
||
3. 加入 CI Lint 步驟
|
||
|
||
---
|
||
|
||
### 缺口 3:Visual Regression 跨平台渲染問題
|
||
|
||
**問題根源**:Mac(M1/M2/M3)vs GitHub Actions(Linux Ubuntu)的字體渲染引擎不同(CoreText vs FreeType),導致截圖像素不吻合。
|
||
|
||
**與整體整合的依賴**:
|
||
- Baseline 快照必須統一來源(CI Docker 環境)
|
||
- 每次更新 Baseline 必須是可審計的(透過 PR),不能在本機靜默更新
|
||
|
||
**修復:Docker 強制基準線更新 + threshold 調整**
|
||
|
||
```json
|
||
// apps/web/package.json 新增 scripts
|
||
{
|
||
"scripts": {
|
||
"test:visual:update": "docker run --rm -v $(pwd):/work -w /work -p 3000:3000 mcr.microsoft.com/playwright:v1.44.0-jammy pnpm exec playwright test --update-snapshots --project=chromium --grep @visual",
|
||
"test:visual": "pnpm exec playwright test --project=chromium --grep @visual"
|
||
}
|
||
}
|
||
```
|
||
|
||
```typescript
|
||
// apps/web/playwright.config.ts 修改截圖比對設定
|
||
export default defineConfig({
|
||
expect: {
|
||
toHaveScreenshot: {
|
||
threshold: 0.05, // 允許 5% 差異(吸收跨平台微小差)
|
||
maxDiffPixelRatio: 0.05,
|
||
// 強制使用 CI 環境的字體設定
|
||
},
|
||
},
|
||
use: {
|
||
// 截圖時的視窗大小固定,避免不同螢幕 DPI 差異
|
||
viewport: { width: 1280, height: 720 },
|
||
deviceScaleFactor: 1, // 強制 1x,避免 Retina 差異
|
||
},
|
||
});
|
||
```
|
||
|
||
**強制規範(加入 .awoooi-agent-rules.md 條款)**:
|
||
|
||
```markdown
|
||
## 條款 21:Visual Regression Baseline 更新規範
|
||
|
||
🚨 絕對禁止在本機 Mac 環境執行 `--update-snapshots`
|
||
✅ 更新 Baseline 必須透過以下流程:
|
||
|
||
1. 在本機執行:`pnpm test:visual:update`(Docker 環境)
|
||
2. Docker 生成的 .png 截圖自動存入 tests/e2e/__snapshots__/
|
||
3. 提 PR,標注 📸 VISUAL_UPDATE
|
||
4. 統帥視覺審核截圖後方可合併
|
||
```
|
||
|
||
---
|
||
|
||
### 缺口 4:PostgreSQL HA(Patroni / CloudNativePG)
|
||
|
||
**問題根源**:PostgreSQL 在 .188 上是單一 Docker 容器,K3s 的 Datastore 也依賴它(ADR-033)。資料庫掛掉 = K3s 控制面 + AWOOOI 資料同時失效。
|
||
|
||
**與整體整合的依賴**:
|
||
- PostgreSQL 是 AWOOOI 的 Episodic Memory(Incidents、Approvals、Audit Logs)
|
||
- PostgreSQL 也是 K3s 的 HA Datastore(120/121 節點的 K3s 元數據)
|
||
- Auto-Repair 對 PostgreSQL 執行 `docker restart` 是**危險的**(可能 Dirty Page)
|
||
|
||
**修復路線圖(三階段)**:
|
||
|
||
```
|
||
Phase DB-A(1週,低風險):
|
||
監控補強
|
||
├── 啟用 PG slow query log (log_min_duration_statement = 2000ms)
|
||
├── 加入 pg_stat_statements extension 並接入 Prometheus
|
||
└── 關閉 auto_repair.postgres.restart(防止 Dirty Page)
|
||
|
||
Phase DB-B(1月,中風險):
|
||
備份策略
|
||
├── Velero + PostgreSQL Volume Snapshot(已有 Velero,需加 Volume 備份)
|
||
└── 確認 WAL archiving 到 MinIO(WAL-E/WAL-G)
|
||
|
||
Phase DB-C(Q2,需評估):
|
||
HA 策略評估
|
||
├── 方案 A:CloudNativePG(K8s 原生 PostgreSQL Operator)
|
||
│ → 在 K3s 中部署 CloudNativePG,主從自動切換
|
||
├── 方案 B:Patroni + keepalived(VM 層 HA)
|
||
│ → 在 .188 和備用機上部署 Patroni
|
||
└── 方案 C:Citus(分片,過於複雜,暫不考慮)
|
||
|
||
推薦:方案 A (CloudNativePG),與 K3s 最整合
|
||
```
|
||
|
||
**立即可執行的防護措施**:
|
||
|
||
```yaml
|
||
# k8s/awoooi-prod/manual-remediation/postgres-recovery.yaml
|
||
# 建立 PostgreSQL 緊急修復 Playbook(人工操作)
|
||
|
||
# 事件:PostgreSQL 掛了
|
||
# 動作:
|
||
# 1. OpenClaw 發告警 + Telegram
|
||
# 2. AlterManager 生成 CRITICAL Approval(不自動修復)
|
||
# 3. 統帥核准後,執行以下指令:
|
||
# ssh root@192.168.0.188 'docker restart awoooi-postgres'
|
||
# kubectl rollout restart deployment/awoooi-api -n awoooi-prod
|
||
# kubectl rollout restart deployment/awoooi-worker -n awoooi-prod
|
||
```
|
||
|
||
---
|
||
|
||
### 缺口 5:Redis HA(Sentinel 模式)
|
||
|
||
**問題根源**:Redis 在 .188 上是單一容器(port 6380),無備援。Redis 同時承載:
|
||
- Working Memory(Incident 聚合狀態)
|
||
- SSE Terminal Event Store(未來的 Event Source)
|
||
- Sentry Dedup Cache(10分鐘去重 TTL)
|
||
- Anomaly Counter(ADR-037 核心數據)
|
||
|
||
**與整體整合的依賴**:
|
||
- Redis 掛掉 = Signal Worker 無法消費事件 = 整個告警鏈路中斷
|
||
- AOF 啟用對性能有影響,需要評估
|
||
|
||
**修復路線圖**:
|
||
|
||
```
|
||
Phase Redis-A(立即,0風險):
|
||
確認 AOF 配置
|
||
├── ssh root@192.168.0.188 'docker exec awoooi-redis redis-cli CONFIG GET appendonly'
|
||
└── 確認 appendonly yes(否則重啟後 Working Memory 歸零)
|
||
|
||
Phase Redis-B(1月,中等工程量):
|
||
Redis Sentinel 部署(在 .110 上部署 Sentinel + Replica)
|
||
├── .188:Master(現有)
|
||
├── .110:Replica + Sentinel
|
||
└── OpenClaw 使用 redis-sentinel:// URI,自動發現 Master
|
||
|
||
配置變更:
|
||
# AWOOOI API 連線改用 Sentinel
|
||
REDIS_URL=redis-sentinel://sentinel1:26379/awoooi-master
|
||
```
|
||
|
||
**立即可執行的防護措施**:
|
||
|
||
```bash
|
||
# 確認 Redis AOF 狀態
|
||
ssh root@192.168.0.188 'docker exec awoooi-redis redis-cli CONFIG GET appendonly; \
|
||
docker exec awoooi-redis redis-cli CONFIG GET appendfsync; \
|
||
docker exec awoooi-redis redis-cli INFO persistence | grep aof'
|
||
|
||
# 若 appendonly = no,立即啟用(需重啟 Redis)
|
||
ssh root@192.168.0.188 'docker exec awoooi-redis redis-cli CONFIG SET appendonly yes'
|
||
# 注意:CONFIG SET 是即時生效的,不需要重啟
|
||
```
|
||
|
||
---
|
||
|
||
### 缺口 6:SSE Event Sourcing(Terminal 狀態不丟失)
|
||
|
||
**問題根源**:Omni-Terminal 的 SSE 串流是無狀態的,F5 刷新後所有 `render_ui` GenUI 卡片消失。
|
||
|
||
**與整體整合的依賴**:
|
||
- 這是 Agentic Workspace 用戶體驗的底層設施
|
||
- 依賴 Redis List 作為 Event Store(如果 Redis 無 AOF,重啟後也丟)
|
||
- 必須與 SSE 三種事件類型設計同步建立
|
||
|
||
**修復:三層機制**
|
||
|
||
```
|
||
Layer 1: 後端 Event Store(Redis List)
|
||
terminal.py → 每個 SSE 事件同步寫入 Redis List
|
||
Key: terminal:events:{command_id}
|
||
TTL: 3600 秒(1小時)
|
||
|
||
Layer 2: 前端 Reconnect(Last-Event-ID)
|
||
useTerminalSSE → EventSource 自動帶 Last-Event-ID
|
||
後端收到後:從 Redis 撈出錯過的事件 → Replay → 接上即時 Stream
|
||
|
||
Layer 3: 本地 Zustand 持久化
|
||
useTerminalStore → 用 zustand/middleware/persist 持久化到 sessionStorage
|
||
F5 刷新 → 從 sessionStorage 恢復 GenUI 卡片(UI 層快速恢復)
|
||
同時 → SSE 重連補齊 Server 端新事件
|
||
```
|
||
|
||
**後端實作關鍵代碼**:
|
||
|
||
```python
|
||
# apps/api/src/api/v1/terminal.py 補充 Event Store 機制
|
||
|
||
import json
|
||
from src.core.redis_client import get_redis
|
||
|
||
async def stream_with_persistence(command_id: str, event_type: str, data: dict):
|
||
"""
|
||
SSE 事件輸出 + 同步寫入 Redis Event Store
|
||
確保 F5 刷新後可以 Replay
|
||
"""
|
||
redis = get_redis()
|
||
|
||
event_payload = {
|
||
"type": event_type,
|
||
"data": data,
|
||
"timestamp": now_taipei_iso()
|
||
}
|
||
|
||
# 寫入 Redis List(RPUSH append to right)
|
||
key = f"terminal:events:{command_id}"
|
||
await redis.rpush(key, json.dumps(event_payload))
|
||
await redis.expire(key, 3600) # 1 小時後自動清理
|
||
|
||
# 返回 SSE 格式字串
|
||
return f"id: {redis.llen(key)}\nevent: {event_type}\ndata: {json.dumps(data)}\n\n"
|
||
|
||
|
||
@router.get("/stream/{command_id}/replay")
|
||
async def replay_terminal_events(command_id: str, last_event_id: int = 0):
|
||
"""
|
||
從指定 ID 開始 Replay 錯過的事件(用於 F5 重連)
|
||
"""
|
||
redis = get_redis()
|
||
key = f"terminal:events:{command_id}"
|
||
|
||
# 取出 last_event_id 之後的所有事件
|
||
events = await redis.lrange(key, last_event_id, -1)
|
||
|
||
async def generate():
|
||
for i, event_json in enumerate(events):
|
||
event = json.loads(event_json)
|
||
yield f"id: {last_event_id + i + 1}\nevent: {event['type']}\ndata: {json.dumps(event['data'])}\n\n"
|
||
|
||
return StreamingResponse(generate(), media_type="text/event-stream")
|
||
```
|
||
|
||
---
|
||
|
||
## 第四部分:整合依賴關係圖(執行順序)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 整合執行優先序 │
|
||
├──────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ 🔴 P0 立即執行(本週,阻塞後續工作) │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 1. 確認 Redis AOF 狀態(5min) │ │
|
||
│ │ 2. Worker terminationGracePeriodSeconds 修正(1h) │ │
|
||
│ │ 3. i18n 清零(4h)← 必須先於 ESLint Plugin 安裝 │ │
|
||
│ │ 4. ESLint i18n Plugin 安裝並啟用(1h) │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
│ ↓(完成後解鎖) │
|
||
│ │
|
||
│ 🟠 P1 短期(2-3週) │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 5. Sentry Comment Token 配置(2h) │ │
|
||
│ │ 6. SignOz 告警規則部署到 .188(2h) │ │
|
||
│ │ 7. Worker HPA YAML 部署(30min) │ │
|
||
│ │ 8. E2E CI Weekly 排程(30min) │ │
|
||
│ │ 9. Visual Regression Docker 基準線建立(2h) │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
│ ↓(完成後解鎖) │
|
||
│ │
|
||
│ 🟡 P2 中期(Month 2) │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 10. Omni-Terminal SSE Event Sourcing(8h) │ │
|
||
│ │ 11. Storybook 10 心組件(8h) │ │
|
||
│ │ 12. Nexus AI 自治率 UI(8h) │ │
|
||
│ │ 13. FinOps Dashboard UI(8h) │ │
|
||
│ │ 14. Redis Sentinel 部署(1天) │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
│ ↓(完成後解鎖) │
|
||
│ │
|
||
│ ⚪ P3 長期(Q2-Q3) │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ 15. CloudNativePG 評估與導入(2天+) │ │
|
||
│ │ 16. Kali SecurityAgent(MCP Tool 化) │ │
|
||
│ │ 17. Knowledge Base 後端全建 │ │
|
||
│ │ 18. Phase 4 視覺靈魂注入 │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 第五部分:整合風險矩陣
|
||
|
||
| 風險 | 可能性 | 影響 | 緩解措施 |
|
||
|------|--------|------|---------|
|
||
| **ESLint 啟用後大量報錯** | 100%(有 40+ 違規) | CI 完全阻塞 | 先清零再啟用,正確順序執行 |
|
||
| **Worker timeout 修改引發 Pod 啟動異常** | 低 | 服務中斷 | 先在 Dev namespace 測試 |
|
||
| **Redis AOF 啟用影響性能** | 中 | 延遲微增 | 使用 `appendfsync everysec`(非 `always`)|
|
||
| **Visual Regression Docker 第一次 Baseline** | — | 需要 1-2h 產生基準線 | 排在非尖峰時段執行 |
|
||
| **PostgreSQL 無 HA 期間主庫故障** | 低 | 完全停機 | 備份策略(Velero)+ Playbook 就位 |
|
||
| **SSE Event Sourcing Redis 依賴** | — | Redis 故障時 Event 丟失 | 先解決 Redis AOF,再實作 Event Sourcing |
|
||
|
||
---
|
||
|
||
## 第六部分:監控機制與前端的整合設計原則
|
||
|
||
(承接 `MONITORING_ARCHITECTURE_DEEP_DIVE.md` 的「三義分離原則」)
|
||
|
||
**整合設計的核心約束**:
|
||
|
||
```
|
||
1. 監控數據 → 後台靜默消化,不直接呈現給統帥
|
||
└─ 99%:Prometheus/SigNoz/Sentry 原始數據
|
||
└─ 1%:AI 無法自動處理 → 浮現為 ApprovalCard
|
||
|
||
2. 前端不直接查詢 Prometheus/SigNoz
|
||
└─ 所有監控數據透過 AWOOOI API 統一封裝
|
||
└─ API 層:/api/v1/stats/overview, /api/v1/slo, /api/v1/finops
|
||
|
||
3. 深度調查只能透過「智能跳脫」(新分頁)
|
||
└─ GenUI 卡片提供 ExternalLinks 按鈕
|
||
└─ 絕對禁止 iframe 嵌入 Grafana/SigNoz
|
||
|
||
4. AI 自治率指數是前端唯一的「監控摘要」入口
|
||
└─ Dashboard (/) 最頂部:AutonomyIndexPanel
|
||
└─ 用一個數字替代所有圖表
|
||
```
|
||
|
||
---
|
||
|
||
*「整合不是把所有工具接在一起,而是讓所有工具服務同一個大腦。」* 🦞
|