4.7 KiB
4.7 KiB
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 瞬斷無法寫入 DB(id=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
- 種子: