技術債 #1: postmortem 發送失敗靜默吞掉 - 3 次指數退避重試 (2s → 4s → 6s) - 全失敗後送簡化降級通知到 SRE 群組 - 防止事後檢討默默消失 技術債 #2 (QueryBuilder 抽象): DEFER - 全專案僅 1 處用 outcome JSON path query - 違反「Don't design for hypothetical future requirements」 - 待第二 caller 出現再抽 技術債 #3 (E2E 測試): 已涵蓋 - test_gap_a4_placeholder_resolution.py TestMatchRuleRejection - Mission C prod 鏈路實測(KubePodCrashLooping) - Playwright K8s/Telegram staging 留待 staging 環境就緒 新增文件: - ADR-078-gap-a4-placeholder-resolution.md - LOGBOOK 2026-04-14 深夜收官條目 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
3.4 KiB
ADR-078: GAP-A4 規則模板 Placeholder 解析強化
日期: 2026-04-14(台北傍晚)
狀態: ✅ Accepted
作者: Claude Sonnet 4.6(首席架構師)+ 統帥戰場偵察 相關: ADR-064 Rule Engine、ADR-077 MASTER 藍圖收案、GAP-A1 kubectl 注入防護
問題
MASTER 藍圖收案後,統帥 log 巡察發現真正的隱性病灶:
auto_execute_blocked_unresolved_placeholder
action: kubectl rollout restart deployment HostHighCpuLoad ← target=alertname!
action: kubectl rollout restart deployment unknown
action: kubectl scale deployment unknown --replicas=3
大量告警在規則引擎路徑產生垃圾指令 → GAP-A1 防注入閘攔下 → 自動修復卡死 → 飛輪沉默 8.3 小時。
MASTER 藍圖未涵蓋此缺口,命名為 GAP-A4:規則 Action 模板 Placeholder 解析缺漏。
根因
alert_rule_engine._extract_vars() 解析邏輯在 Prometheus 告警缺 deployment label 時:
- 退回
alertname或"unknown"作為target - 填入
{target}placeholder → 產生kubectl rollout restart deployment HostHighCpuLoad
決策
三層防護
-
新增
_strip_pod_suffix()— Pod 名稱還原 Deployment/StatefulSet base name- Deployment:
awoooi-api-7d6b776f78-4sgjl→awoooi-api - StatefulSet:
postgresql-0→postgresql
- Deployment:
-
新增
_is_bad_target()— 垃圾 target 識別- 空/unknown/none/null
- 等於 alertname 本身
- IP:port、純 IP、含空白/括號/引號
-
重寫
_extract_vars()— 多層 label 查找(權威優先)deployment>app>statefulset>pod(去後綴)>container>service>target_resource -
match_rule()後置雙驗證- bad target → 清空
kubectl_command→ 降級 LLM - 殘留
{或}→ 清空kubectl_command→ 降級 LLM
- bad target → 清空
降級策略
規則引擎清空 kubectl_command 後,decision_manager 會自然降級到 LLM 路徑(OpenClaw/NemoTron),LLM 有能力從 log 內容推理真實 deployment 名稱。若 LLM 也無解,進 TYPE-4 人工扶梯。
結果
- Commit
10b74af - 33 個新單元測試,214/214 回歸全綠
- LOG:
rule_kubectl_command_discarded_bad_target取代auto_execute_blocked_unresolved_placeholder - 飛輪恢復運轉可能性大幅提升(LLM 會接手處理無 deployment label 的告警)
教訓
- 防注入閘是盡責的守門員,但會遮蔽上游 bug。遇到大量攔截日誌必須追上游。
- 測試告警需涵蓋缺 label 的 sad path。原單元測試只測 happy path。
- log 監控不能取代 metrics 告警。
auto_execute_blocked_unresolved_placeholder累積 8.3 小時才被人工發現,應加 Prometheus 告警規則。
後續
- 加 Prometheus 告警規則:
rule_kubectl_command_discarded_bad_targetrate > 5/min 觸發 TYPE-8M flywheel_health - 補 E2E 測試:真實 Alertmanager 發 HostHighCpuLoad → 驗證 target 正確降級
- 檢查其他規則(如 SSH 路徑)是否有類似 placeholder 解析問題
相關
- Memory: feedback_placeholder_resolution_rule.md
- 測試:
apps/api/tests/test_gap_a4_placeholder_resolution.py - 源碼:
apps/api/src/services/alert_rule_engine.py:94-180
Accepted by 統帥 @ 2026-04-14 台北深夜