iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
AI Engineering

OpenShift AI 簡易入門30天系列 第 27 篇

Day 27:綠燈不等於做完

  • 分享至 

  • xImage
  •  

這是什麼、解決什麼問題

假綠 = 檢查點顯示成功,但事情沒有發生。

它比失敗危險,因為失敗會叫你,假綠不會。
你會在幾個月後、通常是在別人問你的時候,才發現。

這篇把我在自己 lab 上撞到的五種整理出來——
它們有共同的結構,認得那個結構,就能自己看出新的。


什麼時候你會用到

  • 設計驗收清單(Day 26)
  • 檢討「為什麼這個問題沒被抓到」
  • 每次你要寫一個檢查點的時候

形態一:看 log,不看產物

pipeline 印了 ALL DONE,退出碼 0,UI 上綠色。
但那個 step 的訓練根本沒跑。

因為 ALL DONE 是程式最後一行 print,
它證明程式跑到最後一行,不證明中間做了什麼。

檢查要改成:去看產物存不存在、大小合不合理、時間戳對不對。

# ❌ 看這個
oc logs <pod> | grep "DONE"
# ✅ 看這個
aws s3 ls s3://models/output/ --recursive

形態二:看結果,不看門檻是誰填的

品質閘門顯示「通過」。但門檻是這次自己填進去的。

threshold = current_score - 0.01    # ❌ 永遠會過

這種寫法看起來很合理(「不要比上次差太多」),
但它讓每一次都合格,只要退步得夠慢。

檢查要改成:門檻的來源是什麼?誰核定的?什麼時候改的?
能不能在這次執行中被改?


形態三:檢查的範圍小於系統的範圍

你檢查了 A、B、C 三個元件,全綠。
而系統其實有 A 到 F 六個。

這種最難發現,因為檢查本身是對的,只是不完整。

檢查要改成:從系統盤點出發,不從既有的檢查清單出發。

# 系統上實際有什麼
oc get pods -A --field-selector status.phase=Running -o name | wc -l
# 你的清單涵蓋幾個

形態四:檢查在資料層,壞在呈現層

資料是對的、API 查得到、資料庫裡也有。
但畫面上是空白的。

我撞到的版本是:Prometheus 有資料,
Grafana 九個面板全空——因為 datasource 的 uid 沒指定,
Grafana 自己生了一個,而 dashboard JSON 裡寫死的是 prometheus。

⚠️ 我原本寫「隨機的」,那是錯的(Day 17 對帳時查清楚了):
那個 uid 是從 datasource 的名字算出來的,同一個名字每次都一樣。

這個差別會改變你的處置方式:

如果是 那你要
隨機 每次部署後去查一次,寫進 dashboard
從名字算出來(實際) 可以事先算好寫死,或乾脆在 datasource 裡明確指定 uid

「查一次」和「可以固定」是兩種完全不同的維運成本。

檢查要改成:用眼睛看最終的呈現。
API 通不代表使用者看得到。


形態五:寫入成功、讀得回來、內容是空的

API 回 201 Created,GET 回來也有那個物件。
但你送的欄位不見了。

原因是 API 對不認識的欄位不報錯,直接忽略——
我用 camelCase 送了幾個欄位,它期待的是別的形式,
於是我得到一個成功建立、但少了一半資料的紀錄。

檢查要改成:寫進去之後讀回來比對內容,不只比對存在。

resp = create(payload)
got = get(resp["id"])
assert got["author"] == payload["author"]    # ← 這一行

五種的共同結構

每一種都是同一件事:檢查的對象,比你以為的淺一層。

形態 你檢查了 應該檢查
一 程式跑完 產物存在
二 有沒有通過 門檻是誰定的
三 清單上的 系統上的
四 資料在 使用者看得到
五 物件在 內容對

左欄都是「有沒有發生」,右欄都是「發生的是不是我要的」。

認得這個結構之後,寫任何一個檢查點都可以自問:
我檢查的是「有沒有」,還是「對不對」?


怎麼把它變成可操作的規則

寫檢查點的時候,套這三個問題:

  1. 這個訊號,在事情沒發生的時候會不會也出現?
    會 → 換一個訊號。
  2. 這個判定的標準,能不能被被檢查的東西自己改?
    能 → 標準要外部化。
  3. 這個檢查,涵蓋了系統的全部還是一部分?
    一部分 → 說清楚哪一部分。

⭐ 一個誠實的補充

我把 lab 的檢查寫成一支腳本(37 個檢查點)跑第一次,
顯示 5 個失敗。查下去,其中 4 個是腳本自己的錯——
jsonpath 在雙引號裡的巢狀引號沒跳脫,還有一個是
oc logs deploy/X 只讀了三個 pod 中的一個。

這也是一種假綠的反面:假紅。
而它們的成因一樣——你以為你在檢查 A,實際上檢查的是別的東西。

所以清單修好之後我加了一條:檢查工具本身也要被檢查。
最簡單的做法是故意弄壞一個東西,確認腳本會抓到。


怎麼確認你沒有假綠

做法 說明
1 每個檢查點套上面三個問題
2 故意弄壞,確認會被抓到 ⭐ 最有效的一項
3 檢查工具跑在乾淨環境一次 排除工具自身的 bug
4 找人重跑一次 發現隱含的前提

第 2 項是所有方法裡投報率最高的:
護欄要驗過它會擋,才算存在。


常見問題

Q:這樣檢查會不會太慢?
A:會慢一點。但假綠的代價是「幾個月後在別人面前爆開」,
兩個成本不在同一個量級。

Q:能不能用測試框架處理?
A:可以,而且該做。
但框架不會替你決定要檢查什麼——
一個測試 assert response.status_code == 200 一樣是形態五。

Q:五種以外還有嗎?
A:一定有。這五種是我自己撞到的,不是完整的分類。
但共同結構應該是穩定的,用那個結構去看新的情況比背這五種有用。

Q:其中幾種是你自己犯的?
A:兩種。形態二那個「門檻減 0.01」是我寫的,
形態四那個 Grafana uid 也是我設的。
這不是別人的問題,是設計檢查的人容易犯的問題。


本篇在 ODH 3.6.0-ea.1 上對帳(共用區塊寫的 3.5.0 是 Day 1–9 的版本)。

  • 叢集:CRC 2.63.0 · OpenShift 4.22.7 · Kubernetes v1.35.6
    單節點 13 vCPU / 40 GiB / 120 GB,叢集內沒有 GPU
  • Operator:opendatahub-operator.v3.5.0(即 RHOAI 3.x 的上游開源版)、
    cert-manager-operator.v1.20.0(3.x 的必要相依,2.x 不需要)
  • 開啟的元件:kserve、aipipelines、dashboard、workbenches、modelregistry
  • 叢集外:Harbor v2.15.2(私有 registry)、MinIO(S3),跑在宿主的 podman 上
  • 宿主:Framework Laptop 16(Ryzen AI 7 350 · 8C/16T · 64 GB · 1 TB NVMe)

⚠️ ODH ≠ RHOAI:元件同源,但 namespace 與部分名稱不同
(這裡是 opendatahub,商用版是 redhat-ods-*)。指令邏輯可照用,字串要自己對一次。


補充資料

  • 🧪 這篇用到的 YAML/腳本:https://github.com/ryanGTR/openshift-ai-30days
  • 🤖 lab 服務的那個模型(從零手刻的小 GPT):https://github.com/ryanGTR/llm-from-scratch

你們最近一次「以為做完了其實沒有」,是怎麼被發現的? 留言或到原文留言都可以,我會回。


上一篇
Day 26:怎麼寫 AI 平台的驗收清單
下一篇
Day 28:模型上線前該有哪些門
系列文
OpenShift AI 簡易入門30天 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言