上一篇完成固定規則的實作。程式會依序執行 checks.yaml 裡的查詢,套用門檻,再將所有結果寫入 result.json。
今天會先提供 AI 查詢 Prometheus、Loki 與 Kubernetes 的工具,再替 cli.py 加入 brief、tool 與 save 三個調查指令,最後將執行順序寫成 Skill。
固定規則擅長判斷數值有沒有超過門檻,單一查詢往往不足以說明當下的狀況。
例如:PV 使用率達到 99%,可能是昨天才從 70% 快速增加到 99%,也可能已經停在 99% 很久。兩種情況都會被判定為 FAIL,處理的急迫程度卻不一樣。AI 還要查看一段時間的空間變化與 PVC 目前的狀態,才能整理出這次發生什麼事。
所以提供六個範圍明確的調查工具:
| 工具 | 用途 |
|---|---|
query_metric_range |
查詢一段時間的 Prometheus metrics,回傳最高、最低、平均、起訖值與最大變化 |
list_log_jobs |
列出 Loki 目前有哪些 log 來源,以及查詢時可以使用的 job 名稱 |
query_logs |
指定 job、關鍵字與時間範圍,查詢對應的 log |
get_events |
查詢指定 namespace 內的 Kubernetes Event |
list_resources |
列出 Pod、Node、Deployment、Job、PVC 等資源 |
describe_resource |
查看單一 Kubernetes 資源當下的狀態 |
job 是 Loki 用來區分 log 來源的 label。AI 要查 log 時,會先用 list_log_jobs 查看現有的 log 來源,再將查到的 job 名稱交給 query_logs。如果直接使用不存在的名稱,查詢會只得到空結果。
AI 會自行決定下一步查什麼,因此工具必須限制查詢時間、資料量、操作權限與呼叫次數:
result.json 使用相同時間範圍。AI 透過 brief 取得任務、用 tool 查資料,再用 save 將結果寫回 result.json。
AI 開始調查前,程式會先透過 brief 組出這個巡檢項目的調查提示詞。這份提示詞會告訴 AI 要調查什麼、目前有哪些巡檢結果,以及調查完成後要用什麼格式回覆。
前面提到的 PV 使用率,在 checks.yaml 裡的 check id 是 pv-usage。固定規則執行後,這個 id 也會寫入 result.json:
{
"id": "pv-usage",
"title": "PV 使用率",
"status": "FAIL",
"summary": "2/12 項未通過;最差 pyroscope/export-1-pyroscope-minio-0 = 最高 99.12%,超過 75% 共 21.3 小時(目前 99.12%)(另有 1 項)"
}
由於本次結果是 FAIL,接下來將 pv-usage 交給 brief:
./.venv/bin/python cli.py brief \
reports/YYYY-MM-DD/result.json \
pv-usage
第一個參數是本次巡檢的 result.json,第二個參數是要從檔案裡取出的 check id。
縮短後的輸出如下:
巡檢期間:2026-09-17T04:29:09.817376+00:00 → 2026-09-18T01:49:15.817376+00:00
叢集:lab
請調查以下未通過的檢查項。
## pv-usage PV 使用率
狀態:FAIL
規則層摘要:2/12 項未通過;最差 pyroscope/export-1-pyroscope-minio-0 = 最高 99.12%,超過 75% 共 21.3 小時(目前 99.12%)(另有 1 項)
判定所用的查詢:
1 - kubelet_volume_stats_available_bytes / kubelet_volume_stats_capacity_bytes
1 - min_over_time(kubelet_volume_stats_available_bytes[76806s]) / kubelet_volume_stats_capacity_bytes
sum_over_time(((1 - kubelet_volume_stats_available_bytes / kubelet_volume_stats_capacity_bytes) > bool 0.75)[76806s:1m]) * 60
明細:
pyroscope/export-0-pyroscope-minio-0 = 0.991245010436307 [FAIL]
pyroscope/export-1-pyroscope-minio-0 = 0.991245010436307 [FAIL]
## 同層其他檢查項的狀態
container-restarts:PASS
container-oomkilled:PASS
pv-forecast:PASS
workload-replicas:PASS
調查完成後,在回覆的最後附上一個 JSON 區塊。
brief 最後還會指定 AI 回覆的格式:
{
"findings": "結論(兩到三句)+ 證據(項目清單,最多五條)",
"confidence": "high | medium | low",
"unresolved": ["想查但工具查不到的具體項目"]
}
brief 的輸出會完整交給 AI,作用就像這次調查任務的 user prompt。前半段提供叢集、巡檢期間、規則判定、未通過明細與同層項目的狀態,最後要求 AI 使用指定的 JSON 格式回傳調查結果。
以上面的輸出為例,固定規則已經確認兩顆 PV 的最高使用率、目前使用率與超標時間。pv-forecast 仍然是 PASS,代表預測結果沒有顯示它們會繼續快速增加。AI 接下來要查看實際的空間變化,再確認 PVC 目前是否正常。
取得 brief 後,AI 會自己決定查詢順序。這次需要確認 PV 的空間是否持續減少,因此先使用 query_metric_range 查詢兩顆 PV 的可用空間:
./.venv/bin/python cli.py tool \
reports/YYYY-MM-DD/result.json \
pv-usage \
query_metric_range \
'{"promql":"kubelet_volume_stats_available_bytes{namespace=\"pyroscope\",persistentvolumeclaim=~\"export-[01]-pyroscope-minio-0\"}"}'
指令會先顯示這個巡檢項目已經使用的工具呼叫次數:
[工具呼叫次數 1/8 檢查項 pv-usage]
縮短後的工具輸出如下:
{
"series": 2,
"result": [
{
"labels": {
"namespace": "pyroscope",
"persistentvolumeclaim": "export-0-pyroscope-minio-0"
},
"min": 45494272,
"max": 45600768,
"first": 45535232,
"last": 45555712,
"max_change": 102400
},
{
"labels": {
"namespace": "pyroscope",
"persistentvolumeclaim": "export-1-pyroscope-minio-0"
},
"min": 45490176,
"max": 45596672,
"first": 45531136,
"last": 45555712,
"max_change": 102400
}
]
}
tool 會將大量時間序列整理成最低值、最高值、起訖值與最大變化。兩顆 PV 的可用空間都維持在約 45.5 MB,巡檢期間只在約 100 KiB 的範圍內波動,也沒有持續減少。
AI 還可以使用 describe_resource 確認 PVC 目前是 Bound。每次工具呼叫都會記錄在 reports/YYYY-MM-DD/.budget.json,每個巡檢項目最多使用八次。這份計數用來限制本次巡檢。正常完成 Skill 後,下一次巡檢會重新計算。
工具呼叫次數用完後,AI 必須根據已經取得的資料整理結論。仍然無法確認的問題會放進 unresolved。
AI 完成一個項目的調查後,會先整理成結構化 JSON:
{
"findings": "兩顆 PV 的使用率都維持在 99.12%,可用空間沒有持續減少。\n\n**證據**\n- 可用空間的起始值與結束值都約 45.5 MB\n- 巡檢期間最大變化約 100 KiB\n- PVC 目前狀態為 Bound",
"confidence": "high",
"unresolved": [
"現有工具無法確認磁碟裡的檔案內容,以及使用量停止增加的原因"
]
}
findings 說明這次查到的狀況與證據,confidence 記錄 AI 對結論的信心程度,unresolved 保留現有工具無法確認的問題。
接著使用 save 寫回對應的巡檢項目:
./.venv/bin/python cli.py save \
reports/YYYY-MM-DD/result.json \
pv-usage \
/tmp/inv-pv-usage.json
save 會檢查 JSON 格式、必要欄位、confidence 的值,以及 findings 是否包含 **證據** 段落。驗證通過後,才會將內容寫入 result.json 的 investigation 欄位,並重新產生 report.md。
investigation.tool_calls_used 會記錄工具呼叫次數。產生報告後,就能看到 AI 為這個項目呼叫了幾次工具。
AI 只負責寫入調查內容。status 由固定規則產生,risk 與 advice 則定義在 checks.yaml。
Skill 主要撰寫每日巡檢的執行順序:
確認 Prometheus、Loki 與 read-only Kubernetes 權限
→ 執行 report 產生 result.json
→ 列出 WARN、FAIL 與 UNKNOWN
→ 每個項目執行 brief
→ 視需要呼叫 tool
→ 執行 save 寫回調查結果
→ 回報 report.md 的重點
Skill 內還有三項規則:
PASS 不需要交給 AI 調查。UNKNOWN 超過三項時,合併成 unknown-group 調查共同原因。cli.py tool 執行,保留時間範圍、資料量、read-only 權限與工具呼叫次數的限制。checks.yaml 定義查詢與門檻,cli.py report 將判定寫入 result.json。Skill 讓 AI 調查未通過的項目,再透過 save 寫回結果並產生 report.md。
下一篇會用真實叢集執行一次完整巡檢,看看 AI 調查與最後產生的報告是否符合預期。
今天就先寫到這,我們明天見!