Files
awoooi/docs/adr/ADR-073-flywheel-full-audit.md
OG T d32d494320 docs: 四階段細化實施步驟 + 架構轉型截圖定案 + 防偏差守則
規格書 v2.0 新增:
- §十一 四階段細化實施步驟(階段1~4各含驗收清單)
  - 階段1: CD解鎖+debounce+alertname+冷啟動Playbook+KM向量化(9步)
  - 階段2: DB Migration+classify_alert_early+outcome寫入(5步)
  - 階段3: 分診站+SSH路由+TYPE-1/E/F+action解析+risk_level(Tier3,7步)
  - 階段4: KMConversionService+手動修復記錄(4步)
- §十二 防偏差守則(不跳步驟/Tier3授權/不改範圍/異常立刻報告)

ADR-073 更新:架構轉型截圖定案(舊架構中斷→新架構分診飛輪)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 13:30:37 +08:00

306 lines
15 KiB
Markdown
Raw 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.
# ADR-073: AIOps 飛輪完整盤點 — 問題根因 + 長期解決方案
**狀態**: Accepted — 等待統帥批准實作(細化步驟已完成)
**日期**: 2026-04-12 (台北時間)
**更新**: 2026-04-12 晚 — 加入架構轉型截圖定案 + 四階段細化實施步驟
**作者**: Claude Sonnet 4.6 + 首席架構師
**觸發**: 資料庫審計顯示飛輪從未真正運轉
**完整規格**: `docs/superpowers/specs/2026-04-12-aiops-complete-flywheel-repair-design.md`(§十一 細化步驟、§十二 防偏差守則)
### 架構轉型核心2026-04-12 截圖定案)
```
舊架構(中斷路徑):
告警 → LLM 瞎目alertname=NULL→ 目標不明 Unknown → KM 空白
新架構(飛輪 V2.2
告警 → 分診工作站decision_manager 入口)
├─ TYPE-1資訊→ 純文字通知,不進修復流程
├─ TYPE-4DDrift→ Drift 卡片,不進修復流程
└─ TYPE-3需修復→ MCP 上下文 → LLM 推理 → 自動執行 → KM 向量化
```
**關鍵洞察**:分診工作站從 telegram_gateway 前移至 decision_manager 入口是防止「HostBackupFailed 產生 kubectl scale deployment unknown」的架構根治。
---
## 一、飛輪設計圖(截圖定案版)
### 正常模式(自主運行)
```
監控觀察 → 接入去重 → 環境診斷 → 推理匹配 → 執行燒橇 → 學習固化
↑ ↓
└─────────────────── 飛輪閉環 ──────────────────────────────┘
```
**六個節點定義**
| 節點 | 功能 | 對應程式碼 |
|------|------|-----------|
| 監控觀察 | Prometheus/Alertmanager 接收告警Fingerprint 去重 | `webhooks.py` alertmanager_webhook |
| 接入去重 | Debounce 30 分鐘,相同 fingerprint 只建一個 Incident | `webhooks.py` fingerprint + debounce |
| 環境診斷 | MCP 收集真實環境狀態SSH/K8s/Prometheus| `decision_manager._collect_mcp_context()` |
| 推理匹配 | 查 KM Playbook → 有匹配直接執行;無匹配呼叫 LLM 推理 | `decision_manager._dual_engine_analyze()` |
| 執行燒橇 | 透過 MCP Provider 執行修復動作 | `decision_manager._auto_execute()` |
| 學習固化 | 成功→生成 Playbook失敗→生成 Anti-Pattern寫入 KM | `decision_manager._generate_playbook_draft_if_new()` |
### 人工介入模式(需人工路徑)
```
推理匹配
├→ TYPE-3高風險審核: AI 找到方案但動作風險高 → 人工批准 → 執行 → 學習固化
└→ TYPE-4根因確認: AI 無法判斷 → 人工手動處理 → 記錄手動步驟 → 生成新 Playbook
```
**人工介入只發生在兩種情況**
1. `risk_level = critical` 或 DESTRUCTIVE_PATTERNS 命中 → TYPE-3 卡片
2. `confidence < 0.5` 或 MCP 全失敗 → TYPE-4 卡片,人工確認後轉 Playbook
---
## 二、資料庫實際數據2026-04-12 統計)
### Incidents132 筆)
| 欄位 | 數值 | 正常應有 |
|------|------|---------|
| severity P3 | 10882% | P3 應是少數 |
| severity P2 | 1814% | |
| severity P0 | 64% | |
| status INVESTIGATING | 8766% | 應該接近 0 |
| status RESOLVED | 4534% | |
| alertname | **全部 NULL** | 應有 alertname |
| alert_category | **全部 NULL** | 應有分類 |
| notification_type | **全部 NULL** | 應記錄卡片類型 |
| vectorized | **全部 False** | 應 True已向量化進 KM|
| outcome | **全部 null** | 應記錄修復結果 |
### Approvals380 筆)
| status | 數量 | 說明 |
|--------|------|------|
| EXECUTION_FAILED | 21155% | 超過一半執行失敗 |
| APPROVED | 13235% | 已核准,未執行或執行中 |
| REJECTED | 308% | 人工拒絕 |
| EXPIRED | 5 | 超時未處理 |
| **EXECUTION_SUCCESS** | **20.5%** | **實際成功修復只有 2 次** |
### Top Actions失敗根因
| action | 數量 | 問題 |
|--------|------|------|
| 未知操作 \|(空) | 93 | action 解析失敗,完全不知道要做什麼 |
| 重新啟動 postgres-primary-0 | 30 | 同一問題反覆重啟,未解決根因 |
| 重新啟動 postgresql-native | 25 | 同上 |
| 重新啟動 harbor-core-7d4b8c9f5-xk2m3 | 21 | Pod hash 寫死,每次不同 |
| OBSERVE | 16 | LLM 判斷無法修復,只觀察 |
### Playbooks = **0**
### Knowledge Entries699 筆)
- INCIDENT_CASE: 690有案例**但全部未向量化**,無法 RAG 查詢)
- RUNBOOK: 7
- BEST_PRACTICE: 2
---
## 三、飛輪每個節點的實際狀態 vs 設計目標
### 節點 1監控觀察 ✅ 部分正常
- Prometheus → Alertmanager → webhooks.py 接收 ✅
- **問題**alertname 存入 signals JSONB`signals->0->>'alertname'` 全為 NULL代表 signals 結構不對
### 節點 2接入去重 ⚠️ 部分異常
- Fingerprint 機制存在 ✅
- **問題**debounce window 只有 5 分鐘Prometheus 每 1 分鐘 fire 一次5 分鐘後重新建 Incident導致同一問題產生多個 Incident反覆發 Telegram
### 節點 3環境診斷 ❌ 未運作
- `_collect_mcp_context()` 已實作commit c439277
- **問題**`8be87b0` 的修復程式碼 CD 失敗未部署,目前 Pod 是舊 image`a86ecf3`),該 image 沒有 `_collect_mcp_context()`
- MCP Providers 雖然 enabled但沒有在分析前被呼叫
### 節點 4推理匹配 ❌ 嚴重問題
- LLM 分析有在跑Nemotron NIM
- **問題 A**Playbooks = 0`evaluate_auto_repair()` 在 Playbook 匹配步驟永遠失敗,**100% 走人工審核**
- **問題 B**`signals` JSONB 裡 alertname = NULLLLM 拿到的是空告警名稱
- **問題 C**target_resource 解析失敗DockerContainerUnhealthy → target = alertname or unknown
- **問題 D**LLM 習慣性回傳 `risk_level = high`,但 YAML 規則的 risk 沒有覆蓋 LLM 結果
### 節點 5執行燒橇 ❌ 從未成功0.5%
- `_auto_execute()` 三層安全守衛存在 ✅
- **問題 A**93 次 `未知操作|` → action 解析失敗LLM 回傳的 action 包含 `|` 分隔符,解析邏輯出錯
- **問題 B**`target = unknown``target = alertname` → 安全守衛攔截 → 發 `❌ 自動修復失敗`(而非 TYPE-4 卡片)
- **問題 C**K8s deployment 名稱含 hash`harbor-core-7d4b8c9f5-xk2m3`K8s 驗證失敗
- **問題 D**Docker/Host 層告警DockerContainerUnhealthy / HostBackupFailed走 K8s 路徑,根本路徑就錯
### 節點 6學習固化 ❌ 完全失效
- `_generate_playbook_draft_if_new()` 已實作commit 7eb49f9
- **問題 A**Playbooks 仍為 0代表觸發條件從未成立或有 exception 被靜默吞掉
- **問題 B**690 筆 INCIDENT_CASE 全部 `vectorized = False`RAG 查詢永遠找不到歷史案例
- **問題 C**outcome / target_resource / alert_category 全為 NULLKM 記錄的案例沒有分類,無法被有效查詢
- **問題 D**重複發生的告警postgres-primary-0 被重啟 30 次)沒有任何學習,每次重新走全流程
---
## 四、與設計定案的落差對照表
| 設計定案要求 | 實際狀況 | 落差等級 |
|------------|---------|---------|
| 告警 → 自動修復閉環 | Playbooks=0100% 人工審核 | 🔴 P0 |
| 重複告警不重複觸發 | 5 分鐘 debounce每次重建 | 🔴 P0 |
| 失敗 → 學習 → 建立規則 | 690 案例未向量化Playbook 從未生成 | 🔴 P0 |
| KM 三段資料完整 | outcome/vectorized 全 NULL | 🔴 P0 |
| target 動態解析Docker/Host| target = unknown/alertname | 🔴 P0 |
| NO_ACTION 告警不顯示按鈕 | HostBackupFailed 仍有六個按鈕 | 🟠 P1 |
| 通知類型正確分類 | notification_type 全 NULL | 🟠 P1 |
| severity/risk_level 正確 | P3 佔 82%risk 被 LLM 覆蓋 | 🟠 P1 |
| 人工修復後轉 Playbook | 無 handle_manual_fix_done 呼叫 | 🟠 P1 |
| 前端顯示飛輪狀態 | 截圖顯示 Playbook=0飛輪靜止 | 🟡 P2 |
---
## 五、長期解決方案(按優先順序)
### P0-A修復 CD + 部署新 image
**問題**`8be87b0` 的三大修復未上線
**解法**:確認 Harbor 有 `8be87b0` 的 web image若沒有重新觸發 build
**驗收**Pod image = 8be87b0`_collect_mcp_context` 存在於 /app/src
### P0-B修復 signals 結構 — alertname 存入正確欄位
**問題**`signals->0->>'alertname'` = NULL
**解法**`webhooks.py` 在建 Incident 時,確認 signal 的 alertname 正確寫入 JSONB或新增獨立欄位 `alertname VARCHAR(100)`
**驗收**:新 Incident 的 alertname 不為 NULL
### P0-Cdebounce window 延長到 30 分鐘
**問題**5 分鐘 debounce → 同一問題每 5 分鐘重新建 Incident + 發 Telegram
**解法**`webhooks.py` fingerprint debounce window 從 5 分鐘 → 30 分鐘
**驗收**:同一告警 30 分鐘內只有 1 個 INVESTIGATING Incident
### P0-D冷啟動 Playbook 生成
**問題**Playbooks = 0自動修復永遠失敗
**解法**:一次性腳本,讀取 approval_records 裡 EXECUTION_SUCCESS 的 2 筆 + APPROVED 的 top 10用 LLM 生成初始 Playbook 草稿,寫入 DB 標記 APPROVED
**驗收**Playbooks >= 10evaluate_auto_repair 至少有匹配
### P0-E690 筆 INCIDENT_CASE 向量化
**問題**vectorized = FalseRAG 永遠找不到歷史案例
**解法**:一次性腳本,批次向量化所有 `vectorized=False` 的 knowledge_entries
**驗收**vectorized = TrueRAG 查詢返回相關案例
### P0-FDocker/Host 層告警走 SSH MCP 路徑
**問題**DockerContainerUnhealthy → K8s 路徑 → deployment 不存在 → 失敗
**解法**`_auto_execute()` 判斷 alertname prefixDocker*/Host*)→ 走 SSH MCP `ssh_docker_restart`;不走 K8s 路徑
**驗收**DockerContainerUnhealthy 觸發 → SSH MCP 執行 → 成功
### P1-Aaction 解析修復93 筆「未知操作|」)
**問題**LLM 回傳含 `|` 的 action解析後為空
**解法**`_push_decision_to_telegram()` 的 action 佔位符替換邏輯,加 `|` 分隔符清理
**驗收**:新的 approval_records action 不出現「未知操作|」
### P1-BNO_ACTION → TYPE-1無按鈕
**問題**HostBackupFailed 仍有六個按鈕
**解法**`classify_notification()` 加判斷:`suggested_action == "NO_ACTION"` → TYPE-1
**驗收**HostBackupFailed Telegram 卡片無操作按鈕
### P1-Coutcome / alert_category / notification_type 寫入
**問題**:三個欄位全 NULLKM 無法分類
**解法**
- `_auto_execute()` 完成後寫 `incident.outcome`
- `webhooks.py` 建 Incident 時寫 `alert_category`(從 YAML 規則取)
- `_push_decision_to_telegram()` 發完寫 `notification_type`
### P1-Drisk_level YAML 優先覆蓋 LLM
**問題**LLM 習慣性回傳 highYAML 規則的 risk 沒有覆蓋
**解法**`_dual_engine_analyze()` 中,若 YAML 規則有 risk 值,優先用 YAML 的,不採用 LLM 的
**驗收**HostHighCpuLoadYAML risk=medium→ Telegram 顯示 MEDIUM
### P2-A前端飛輪狀態即時顯示
**問題**截圖顯示飛輪靜止Playbook=0成功率 0.5%,需人工介入
**解法**:前端飛輪元件(已有)連接以下 API
- `GET /api/v1/stats/flywheel` → 返回六節點狀態(活躍/靜止/錯誤)
- `GET /api/v1/stats/summary` → 返回 Playbook 數量、成功率、今日處理數
- WebSocket 推送:每次節點狀態變化即時更新
**驗收**飛輪動畫跟隨真實告警流轉動Playbook 數量即時更新
### P2-B前端顯示人工介入路徑
**問題**:截圖第二張「需人工介入」時,飛輪顯示 TYPE-4根因確認和 TYPE-3高風險審核路徑
**解法**飛輪元件增加「顯示人工干預路徑」toggle已有觸發時
- 紅色虛線顯示從「推理匹配」到「人工處理中心」的路徑
- TYPE-3 / TYPE-4 標籤顯示在對應節點旁邊
---
## 六、實作優先順序與批准等待
> 以下所有變更等待首席架構師批准後才開始實作
### Sprint ADR-073-A本週讓飛輪真的動起來
| # | 任務 | 風險等級 | 估計工時 |
|---|------|---------|---------|
| 1 | CD 修復 + 8be87b0 部署確認 | Tier 2 | 30 分鐘 |
| 2 | signals alertname NULL 修復 | Tier 2 | 1 小時 |
| 3 | debounce 5→30 分鐘 | Tier 2 | 30 分鐘 |
| 4 | 冷啟動 Playbook 生成腳本(一次性)| Tier 2 | 2 小時 |
| 5 | 690 筆 KM 向量化腳本(一次性)| Tier 1 | 1 小時 |
### Sprint ADR-073-B下週修復路由 + 通知品質
| # | 任務 | 風險等級 | 估計工時 |
|---|------|---------|---------|
| 6 | Docker/Host 告警 → SSH MCP 路徑 | Tier 3 | 3 小時 |
| 7 | action 解析「未知操作|」修復 | Tier 2 | 1 小時 |
| 8 | NO_ACTION → TYPE-1 無按鈕 | Tier 2 | 1 小時 |
| 9 | outcome/alert_category/notification_type 寫入 | Tier 3 | 2 小時 |
| 10 | risk_level YAML 優先 | Tier 2 | 1 小時 |
### Sprint ADR-073-C再下週前端飛輪即時化
| # | 任務 | 風險等級 | 估計工時 |
|---|------|---------|---------|
| 11 | `/api/v1/stats/flywheel` API | Tier 1 | 2 小時 |
| 12 | 前端飛輪元件連接真實 API | Tier 2 | 3 小時 |
| 13 | WebSocket 即時推送 | Tier 2 | 2 小時 |
---
### Sprint ADR-073-B 補充(整合 ADR-071 工作序2026-04-12 更新)
| # | 任務 | 風險等級 | ADR-071 對應 |
|---|------|---------|-------------|
| B-DB | DB Migration: incidents +9 欄位 | Tier 1 | ADR-071-A |
| B1 | 檢傷分類站前移decision_manager 入口)| Tier 3 | ADR-071-A0+B |
| B2 | TYPE-1 純資訊卡片 | Tier 2 | ADR-071-C |
| B3 | KMConversionServiceRESOLVED→KM→向量化| Tier 2 | ADR-071-G |
| B4 | TYPE-4 手動修復記錄 | Tier 2 | ADR-071-H |
### Sprint ADR-074監控補全依賴 ADR-073-A/B 完成後)
| # | 任務 | 告警名稱 | 嚴重度 |
|---|------|---------|-------|
| M1 | 飛輪健康度 Prometheus Exporter + 告警規則 | `FlywheelPlaybookZero` / `FlywheelExecutionSuccessLow` | P0 Critical |
| M2 | 主機間網路 Blackbox probe | `HostNetworkPartition` | P0 Critical |
| M3 | CoreDNS 解析失敗監控 | `CoreDNSResolutionFailed` | P0 Critical |
| M4 | Gitea CI/CD 管線失敗 webhook | `GiteaCIPipelineFailed` | P0 Critical |
| M5 | 備份還原週排程測試 | `BackupRestoreTestFailed` | P0 Critical |
| M6 | Docker 188 容器詳細健康 | `DockerContainerUnhealthyDetailed` | P1 Warning |
| M7 | Redis Streams 積壓 | `RedisStreamBacklogHigh` | P1 Warning |
| M8 | PostgreSQL 磁碟增長率 | `PostgreSQLDiskGrowthRate` | P1 Warning |
| M9 | Gemini API 錯誤率 | `GeminiAPIErrorRateHigh` | P1 Warning |
> **完整規格**: `docs/superpowers/specs/2026-04-12-aiops-complete-flywheel-repair-design.md`
---
## 七、驗收標準(飛輪真正運轉的指標)
完成後 7 天內,以下指標必須達到:
| 指標 | 當前 | 目標 |
|------|------|------|
| Playbooks 數量 | 0 | ≥ 20 |
| EXECUTION_SUCCESS 率 | 0.5% | ≥ 30% |
| 重複告警同 Incident 率 | < 10% | ≥ 70% |
| KM vectorized | 0% | ≥ 90% |
| alertname NULL | 100% | 0% |
| 飛輪節點有活動的告警 | 0 | ≥ 1 筆/小時 |