Files
ewoooc/docs/adr/ADR-013-aiops-autoheal.md
OoO 749eace426
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
移除未使用 Paramiko 依賴
2026-05-13 11:32:04 +08:00

116 lines
4.7 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-013: AIOps 自動修復閉環架構
**狀態**: Accepted
**日期**: 2026-04-19
**提案者**: Antigravity
---
## 背景與問題
EwoooC 系統已有 L1 Hermes 告警派發,但告警只能「通知」,無法「自癒」。
`psycopg2.OperationalError: could not translate host name "momo-postgres"` 這類明確的基礎設施問題發生時,仍需人工 SSH 登入修復,缺乏自動化閉環。
---
## 決策
建立三層 AIOps 閉環架構:
```
Exception → Incident(DB) → PlayBook 匹配 → Auto-Heal 執行 → HealLog(DB) → KM 沉澱(ai_insights) → Telegram 通知
```
### 新增元件
| 元件 | 類型 | 說明 |
|------|------|------|
| `database/autoheal_models.py` | Model | Incident / Playbook / HealLog 三張表 |
| `migrations/013_autoheal.sql` | Migration | 建表 + 種子 PlayBook 植入 |
| `services/auto_heal_service.py` | Service | 核心引擎(分類、匹配、執行、沉澱) |
| `database/manager.py` | 修改 | 加入 `_init_autoheal_tables()` |
| `scheduler.py` | 修改 | 三個核心任務植入 `handle_exception` |
| `utils/ssh_helper.py` | Helper | 共用 CLI `ssh` 執行層,供 AutoHeal / AiderHeal 使用 |
### PlayBook 動作類型
| action_type | 說明 |
|---|---|
| `DOCKER_RESTART` | 透過 SSH 跳板 restart 指定容器 |
| `SSH_CMD` | 執行白名單內的任意 SSH 指令 |
| `ALERT_ONLY` | 僅發 Telegram 告警,人工介入 |
| `WAIT_RETRY` | 紀錄後等待排程重試 |
### 安全設計
- SSH 指令白名單2026-04-29 起僅允許明確列入 allowlist 的 read-only 診斷指令;高副作用容器操作需走受控 PlayBook 與保護清單
- `momo-db` / `momo-postgres` 永遠是 protected resource不得被自動 restart / stop / recreate
- DB / DNS 類離線 playbook 若無法安全修復,降級為 `ALERT_ONLY``WAIT_RETRY`
- 冷卻機制:同 PlayBook 在 `cooldown_min` 內不重複觸發
- 升級機制:達到 `max_retries` 後 incident.status = `escalated` 並通知人工
### KM 沉澱格式
每次修復後寫入 `ai_insights`
- `insight_type = "auto_heal_playbook"`
- 包含事件、症狀、行動、結果、教訓五要素
- 自動排入 `embedding_retry_queue` 完成 RAG 向量化
---
## 取捨
2026-05-13 實作修訂:現行程式碼已標準化到 `utils/ssh_helper.py`,以 CLI `ssh` + `ProxyJump` 參數組裝執行AutoHeal 與 AiderHeal 共用同一層;因此 `paramiko` 不再是 runtime 依賴。若未來要重新引入 Paramiko必須同時補回 helper 實作、requirements 與回歸測試。
---
## 結果
- P1/P2 等級的 DB_UNREACHABLE / DNS_FAIL 類問題可在 30 秒內完成自動修復
- 所有修復知識自動沉澱至 RAG KM提升未來 AI 的判斷品質
- 覆蓋任務:`run_auto_import_task` / `run_icaim_analysis_task` / `run_weekly_strategy_task`
---
## 部署後記2026-04-19 實測)
### 踩坑修正(共 5 個 hotfix commit
| 問題 | 原因 | 修正 |
|---|---|---|
| `UndefinedTable: playbooks` | 建表順序 `[Incident, Playbook, HealLog]` FK 衝突 | 改為 `[Playbook, Incident, HealLog]` |
| `DetachedInstanceError` HealLog/Incident | `commit()` expire_on_commit 後 lazy-load 失敗 | `session.refresh(obj); session.expunge(obj)` |
| `TypeError: NoneType:.0f` | fallback HealLog 缺 `duration_ms` | except 分支補 `duration_ms=duration_ms` |
| compose=True 雙重呼叫 bug | `_execute_playbook` 先呼叫 compose馬上覆寫為 docker restart | 刪除 use_compose 分支 |
| `No authentication methods available` | paramiko 找不到 SSH key | key 複製至 `/app/config/autoheal_id_ed25519`rw mount不需重建容器 |
### SSH 認證鏈設定
```
momo-scheduler → id_ed25519 → 110 (wooo) → tunnel → 188 (ollama) → docker restart
```
`ollama@188``id_ed25519.pub` 已加入 `authorized_keys`(第 11 行)。
### 實測結果
```
result=success duration=3110ms # DNS_FAIL → docker restart momo-db 成功
```
heal_log 在 restart momo-db 後因 DB 瞬斷無法寫入 DBid=7~9 遺失屬設計邊界Telegram 通知仍正常推播。
### 2026-04-29 安全修訂
上述 `DNS_FAIL → docker restart momo-db` 屬早期實測紀錄,現在不再允許作為自動修復策略。最新規則:
- `momo-db` / `momo-postgres` 是資料層 protected resource。
- AutoHeal 寫 DB 失敗時不可讓自癒流程 crash需保留 Telegram / log / fallback 記錄。
- `CODE_FIX`、resource action 與 ElephantAlpha orchestration 必須橋接 AutoHeal不得直接執行危險副作用。
- raw `ai_insights` 寫入後必須 enqueue embedding讓自癒知識進入 RAG。
### 新增 DB 表
- `migrations/014_telegram_users.sql` — EventRouter 推播對象(替代 .env 硬編碼)
- 種子:`telegram_id=-1003940688311, is_admin=true`