iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0
AI 自動化

讓 AI 接手工程師的 SOP:30 天 AI 自動化實戰系列 第 11

Day 11:讓 AI 主導混沌實驗

  • 分享至 

  • xImage
  •  

前一篇,AI 完成第一次 Ingest,並從程式碼與部署設定找出第一批弱點。後續用相同流程掃描其他 Service 後,Wiki 已經累積更多實驗候選。
今天要驗證 AI 能不能從 Wiki 選出一條弱點,提出假設、設計混沌實驗,再根據 metrics 寫出觀察報告?

實驗只能在測試環境執行,PostgreSQL、Kafka 與 Loki 禁止成為攻擊目標。人類會在實驗前確認設計,遇到異常時接管;其餘流程由 AI 主導。
接下來會從實驗報告中,挑出幾段比較完整、也比較有趣的內容來說明。


EXP-002:讓 teller-service 到 account-service 的呼叫延遲 10 秒

AI 從 Wiki 選中 teller-service 呼叫 account-service 的 API 路徑。這條路徑剛好有兩個弱點:TEL-W001 是沒有 Circuit Breaker,TEL-W002 是 HTTP client 沒有設定 timeout。

它提出的假設是:如果 teller-service 呼叫 account-service 時多出 10 秒網路延遲,teller-service 的 thread 會持續等待;並發量夠高時,連健康檢查都可能拿不到 thread。

AI 因此設計 NetworkChaos,讓 teller-service 呼叫 account-service 的流量延遲 10 秒。核心設定如下:

spec:
  action: delay
  selector:
    labelSelectors: { app.kubernetes.io/name: teller-service }
  direction: to
  target:
    selector:
      labelSelectors: { app.kubernetes.io/name: account-service }
  delay: { latency: "10s" }

這份設定只會在 teller-service 發往 account-service 的封包加上延遲。AI 也會觀察 account-service 本身,以及其他 Service 呼叫 account-service 的結果。只有 teller-service 到 account-service 的延遲上升,其他流量維持正常,才能確認故障沒有超出預定範圍。

AI 會把假設、Chaos YAML、觀測指標與停止條件整理進實驗文件,執行前再由人類確認設計。

接下來會看到兩份文件。EXP-002.md 是實驗紀錄,包含事前假設、設計與執行後回填的結果;EXP-002-report.md 是 AI 在實驗完成後整理的觀察報告,讀起來比較像給人看的版本。


在實驗前寫下假設

先來看看 AI 在 EXP-002.md 寫下哪些預期現象。

AI 在實驗前寫下的 EXP-002 假設

圖:EXP-002 實驗設計文件中的假設,內容在正式注入前完成。

簡單地說,AI 預測 10 秒延遲會一路傳到使用者,造成業務成功率下降,也會讓越來越多 teller-service thread 卡在等待 account-service。同時,account-service 本身與其他 Service 呼叫 account-service 的流量應該維持正常。後面的觀察會逐項回來比對。


測量穩態

正式執行時,AI 先用 k6 維持 60 個 VUs(Virtual Users,k6 用來模擬同時操作系統的虛擬使用者),跑 45 秒正常流量,收集故障注入前的基準值(Baseline)。當時 teller-service → account-service 平均延遲約 16ms,teller-service 處理一筆請求平均約 41ms,轉帳、存款與提款成功率都是 100%。

實驗完成後,AI 將這些數字整理進 EXP-002-report.md 的「穩態」章節,再和故障注入期間的結果比較。

AI 整理進 EXP-002 報告的穩態

圖:AI 將故障注入前量到的 Baseline 整理成報告中的穩態。


開始實驗與觀察現象

穩態確認完成後,AI 維持 60 個 VUs,開始注入 10 秒網路延遲。NetworkChaos 持續 240 秒,期間持續送出轉帳、存款與提款請求,並記錄服務狀態與 metrics。

實驗結束後,AI 將 metrics、trace 與 k6 結果整理成五個觀察現象。以下先看現象一到三:

EXP-002 報告中的觀察現象一到三

圖:AI 寫進 EXP-002 報告的現象一到三,保留原始內容。

簡單地說,AI 確認 teller-service 呼叫 account-service 時,確實多出完整的 10 秒延遲。一筆轉帳會連續呼叫 account-service 兩次,所以使用者大約要等 20 秒。從使用者端的 k6 測試結果來看,轉帳成功率降到 75%;但從 trace 整理出的 teller-service SERVER spanmetrics 顯示,teller-service 完成的請求幾乎都成功。這個差異代表只看服務端的 metrics,會低估使用者實際遇到的失敗。

接著是現象四、實驗期間數據、圖表與現象五:

EXP-002 報告中的觀察現象四到五

圖:AI 寫進 EXP-002 報告的現象四、原始時間順序數據、圖表與現象五。

這張圖確認 account-service 本身維持正常,故障範圍符合原本設計。NetworkChaos 在 T+240 秒停止後,teller-service 的延遲仍未完全恢復,錯誤率在恢復尾段反而上升。堆積的請求在故障解除後繼續逾時,讓影響又延續約 60 秒。

不過,AI 回頭比對假設四時,發現「200 條 thread 全部被卡住」還缺少證據。teller-service 全程維持 Ready,也沒有重啟。60 個 VUs 中只有約 27% 的操作會經過被延遲的路徑,還不足以把 200 條 thread 全部卡住。

因此,AI 將假設四標成 load-limited,代表這次負載不足,還不能確認 200 條 thread 全部被卡住後,健康檢查真的會失敗。


Run 1 缺乏證據,AI 再跑一次

Run 1 沒有讓 200 條 thread 全部被卡住,所以 AI 設計了 Run 2。這次將負載提高到 280 個 VUs,而且全部只打轉帳,讓每個請求都經過被延遲的路徑。

AI 預期 10 秒延遲會讓 teller-service 的 thread 長時間無法釋放。當 200 條 thread 全部被卡住,Prometheus 與健康檢查也會拿不到 thread,最後由 Kubernetes 重啟 teller-service。

NetworkChaos 的注入時間則從 240 秒縮短為 120 秒。AI 預期這段時間足以觀察一次重啟,也能避免 teller-service 持續進入 CrashLoop。

以下是 AI 寫進報告的完整 Run 2 時間順序:

AI 產生的 EXP-002 Run 2 時間順序報告

圖:AI 根據 Run 2 完整觀測資料整理出的事件時間順序。

正式注入前,280 個 VUs 已經讓 tomcat_threads_busy_threads 到達 199,但 teller-service 仍然維持 Ready,Prometheus 也抓得到 metrics。這代表高負載已經用掉大部分 thread,但請求仍能快速完成並釋放資源,服務還撐得住。

注入延遲後,情況開始改變:

T+2s    busy 到達 200
T+39s   Prometheus 抓不到 metrics,teller-service 變成 NotReady
T+75s   liveness 失敗,Kubernetes 第一次重啟 teller-service
T+122s  NetworkChaos 完成恢復
T+194s  Kubernetes 第二次重啟 teller-service
T+240s  busy 回到 1,Prometheus 與 readiness 恢復
T+358s  teller-service 持續維持正常

所以看到 busy=200,還不能直接判斷 teller-service 已經撐不住。這次真正的失效訊號依序是 Prometheus 抓不到 metrics、teller-service 變成 NotReady,最後由 liveness 觸發重啟。Pod UID 全程沒有改變,代表 Kubernetes 重啟的是同一個 Pod 裡的 teller-service container。

AI 原本預期 120 秒的注入時間只會造成一次重啟。實際執行時,第一次重啟發生在 T+75 秒;NetworkChaos 在 T+122 秒顯示 AllRecovered=True,代表 10 秒延遲已經解除。

不過,高負載仍在持續,teller-service 最後在 T+194 秒發生第二次重啟。從 busy 再次到達 200 來看,持續送入的 280 個 VUs,加上前面還沒處理完的請求,讓服務在恢復期間又一次到達上限。原本預期的單次重啟沒有成立,這也是這次實驗多觀察到的結果。

第二次重啟後,teller-service 在 T+240 秒恢復成 busy=1up=1 與 Ready。後續高負載一度再次讓 busy 到達 200,readiness 也短暫波動,但沒有發生第三次重啟。負載在 T+325 秒結束,觀測持續到 T+358 秒,teller-service 全程維持正常。

恢復後重新送出一筆轉帳,API 回傳 201,耗時約 0.066 秒。account-service、exchange-service 全程維持 Ready,PostgreSQL、Kafka 與 Loki 的 restart count 也沒有增加,故障範圍仍符合原本設計。

回到假設四,Run 2 完整確認了這條因果鏈:10 秒延遲讓 teller-service 的 thread 長時間無法釋放,接著影響 Prometheus 與健康檢查,最後觸發 Kubernetes 重啟 teller-service。AI 猜錯的是重啟次數,核心假設仍有完整證據支持。


AI 根據結果提出修復建議

兩輪測試完成後,AI 根據觀測證據排出修復順序:

EXP-002 報告中的行動建議

圖:AI 根據 EXP-002 結果整理出的修復優先順序與驗收條件。

AI 將 Circuit Breaker 與 HTTP client timeout 列為 P0。對下一篇最重要的是 P2:修復後必須重跑相同實驗,確認 Circuit Breaker 能在 100ms 內 fast-fail,16 秒延遲與複合效應也要消失。


結論

這篇確認了 AI 能主導一場混沌實驗:從 Wiki 選擇弱點、提出假設、產生 Chaos YAML,到整理觀測證據與更新報告。

Run 1 的負載不足,AI 將假設標記為 load-limited,再調整條件執行 Run 2。Run 2 補齊了 thread 被占滿、健康檢查失敗與 container 重啟的完整因果鏈,也觀察到原先沒有預期的第二次重啟。對於第二次重啟的原因,AI 清楚標示為根據 metrics 與事件順序做出的推論。

人類負責設定測試環境、安全紅線、實驗前 review,以及發生異常時接管。AI 則主導實驗設計、觀測、判讀、報告與 Wiki 更新。

AI 最後更新 EXP-002-report.md,並將實驗狀態更新為 reflectedTEL-W001 也從程式碼掃描出的弱點,補上 executed-confirmed 的實驗證據。

下一篇會看看 AI 如何把這份修復建議變成驗收實驗。

今天就先寫到這,我們明天見!


上一篇
Day 10:Ingest 與弱點掃描
下一篇
Day 12:驗收 AI 提出的修復
系列文
讓 AI 接手工程師的 SOP:30 天 AI 自動化實戰18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言