Cloud-Native Kubernetes Engineering
從 Kubernetes 核心邏輯(klog verbosity 修補)到 ecosystem 上的 operator 模式、多叢集編排、高可用網路、自動擴縮。 理解 controller-runtime、CRD lifecycle、Ansible 部署、Operator pattern。
02 · Open Source
Kubernetes GitHub Org Member · Nephio (Linux Foundation Networking) TSC Member · OpenTelemetry GitHub Org Member · Zephyr RTOS M5Stack Platforms Maintainer
六項核心工程能力,皆建立在已合併的上游貢獻之上。每一項能力均附有可公開查證的 GitHub 證據,呈現的不只是技術知識,而是經上游維護者審查、接受並納入正式專案的實際工程交付。
除開源工程貢獻外,亦參與國際學術服務,包括完成 Journal of Open Source Software (JOSS) 正式同儕審查,以及擔任 IEEE WF-PST 2026 Technical Program Reviewer。
以上為已合併貢獻的定值。進行中的 PR 是動態的,直接看 GitHub 上的即時清單。
Variant Analysis
9 個缺陷變體 · 6 個獨立維護的上游專案 · 8 項修正已合併
我不把單一缺陷的修正視為終點。從第一個資源會計錯誤出發,我將根因抽象為一組可重用的審查不變量:資源需求與配額計算在加總、乘法、數值轉換、共享配置與生命週期變更時,必須保持數值可表示、狀態一致,且不能因溢位、截斷、漏算或重複計數而失真。
接著,我以這組不變量系統性檢查其他排程器與 Dynamic Resource Allocation (DRA) 實作,最終在六個獨立維護的上游專案中辨識出九個缺陷變體。
九項問題均由我發現並回報;其中八項的修正由我提交、經上游維護者審查後合併,且每一支都附帶回歸測試,另一項雖已確認根因並備妥修正,因該 scaler 即將 deprecate 而由維護者以 wontfix 結案。下方逐項列出從回報到修正的連結,呈現問題重現、根因分析、修正設計到上游交付的完整證據鏈。
配額會計把一個實際上無法滿足的 device 判成可配置
roundUpRange 的 min+step*n 對大 capacity 請求 int64 溢位成負 · 回報 #140441 → 修復 #140442
構造過的 step 值通過守衛後直接除零,打掛 allocator
守衛用精確的 Quantity.Sign()、算術卻用超出 int64 就截斷的 Quantity.Value(),兩者對同一個值判斷不一致 · 回報 #140472 → 修復 #140666
低估佇列需求而擋掉本應成立的 reclaim,受害的是同佇列的正常工作負載
使用者可控的 device count 能繞過 capacity plugin 的配額
超額 Workload 被 admit,並汙染 ClusterQueue 的已用配額
同一條路徑的第二處,counter 扣款仍可溢位
counter-charge 的乘法未設守衛,是 #12897 修完後補上的第二輪 · 回報 #12908 → 修復 #12909
driver 自行發布的 counter 值不受 apiserver 驗證,負值或超界量直接算錯配額
maxValue.Value() 在乘法之前就把超出 int64 的量截成垃圾(1e19 變 0、2^63 變負),飽和乘法救不回來;且該保護只在 count > 1 時啟用 · 修復 #12945(follow-up,無獨立 issue)
單字元的 vendor 或 class 名稱就足以讓解析 panic
validateVendorOrClassName 切出 name[1:0],低界大於高界;兄弟函式本來就有這道守衛 · 回報 #320 → 修復 #321
總 lag 落在分區邊界時封頂失效,多要一個 replica
封頂用整數 floor 除法比較、HPA 卻以 ceil 算 replica,兩者取整在邊界分歧而漏夾 · 回報 #7930;已備妥 >= 修正與回歸測試,維護者因該 liiklus scaler 即將 deprecate(#7929)而以 wontfix 結案(非否定 bug)
跨專案追蹤缺陷變體之外,我也在 Kubernetes 核心 DRA allocator 中沿著資源會計不變量持續向下檢查。五項已合併修正涵蓋數值表示與溢位(#140666、#140442)、跨 driver 的 counter-cache 身分碰撞(#140435)、候選拒絕與回溯時的狀態洩漏(#140431),以及持久化共享裝置的 counter 重複計算(#140437)。
五支 PR 均已合併至 master、帶有 release-note 標籤並列入 v1.37 milestone;每支均關閉一個由我回報的 issue,並附有針對原始失效路徑的回歸測試。
這條 int64 溢位家族後來被上游收攏成正式工作項。SIG API Machinery 維護者 jpbetz 在 #141166 開了官方 burndown、系統性追蹤整個 resource.Quantity int64 accessor 溢位 class(乘法 wrap、負值捨入方向、String() 掉後綴、指數截 32-bit 等),並具名 CC 我。我供稿其第一項——#141170 的 baseline accessor 測試矩陣:記錄 Value/MilliValue/ScaledValue 等每個 accessor 今日的實際回傳、對錯誤值標 TODO,讓後續每項修正都對「已知基準」做 diff 而非憑記憶。此為 open PR、不計入頁首數字。
Capabilities
每一張卡片代表一項工程能力,下方列出代表性 PR 作為「我做過、且被合併」的證據。
從 Kubernetes 核心邏輯(klog verbosity 修補)到 ecosystem 上的 operator 模式、多叢集編排、高可用網路、自動擴縮。 理解 controller-runtime、CRD lifecycle、Ansible 部署、Operator pattern。
OpenTelemetry SDK(Go / C++ / Android)instrumentation、Jaeger UI 大型 refactor、metrics backend(Cortex)、儀表板(Perses)。 擅長在既有 codebase「補上」trace propagation 與 verbosity-correct 的 logging。
Nephio (LFN) Technical Steering Committee Member,參與專案技術治理與方向決策。 工程貢獻涵蓋 Intent-based 網路功能部署、KRM 套件編排(kpt porch)、Nephio CI/CD 測試基礎設施、O-RAN SC 整合測試。
在 Jaeger UI 跑 20 個 PR 的系統性 refactor series:把 React class components 轉成 hooks-based functional components, 跨 plexus graph library 與 trace views。能在大型 codebase 做漸進式 migration 而不破壞既有功能。
Keycloak(Java IAM)、Harbor container registry 以 dependency injection 重構提升可測性、OPA / conftest 政策驗證、 Aserto policy registry CLI、kgateway API gateway。整套 zero-trust / supply-chain security 鏈條的工程能力。
Distributed compute(Ray)、LLM serving(vLLM)、ML on Kubernetes(Kubeflow pipelines / trainer、Koordinator scheduler)、 event-driven autoscale(KEDA)、eBPF / sched_ext 客製化 scheduler(Gthulhu)、向量資料庫全文模糊檢索(Milvus)、批次/gang 排程配額溢位加固(Volcano、Kueue)。 專注「把 ML workload 跑在 cloud-native infra 上」與「kernel 層級 CPU 排程最佳化」這層問題。
Stack
Recent
按時序列出所有 upstream merged PRs 標題與日期。點 PR 編號跳到 GitHub 看 diff。
eci_to_orbital 用 std::acos 吃 dot-product 比值算出的 cosine,合法幾何在 apoapsis 仍可能因浮點 round-off 使引數微超 [-1,1](實測 -1.0000000000000004)→ acos 回 NaN、汙染 eccentric/mean anomaly,整組軌道要素與衍生的 SIB19 ephemeris 全變 NaN 不可用。修法在三個 acos 引數前 clamp 到 [-1,1](well-conditioned 幾何路徑不變、只有邊界 round-off 收斂到 0 或 π);新增 apoapsis near-circular 與邊界 sweep 兩個測試、跨 -O0/-O2/-O3 一致 · +110/−43、2 檔 · 與 0/0 singularity(#660)分屬不同案 · target dev、maintainer asaezper 合併
prepareDevices 把 full-chip 數、allocatable 查找、container edits 套到整包 Results;但一個 ResourceClaim 可由多個 driver 一起滿足,claim 若同時含別 driver 的裝置,完整 TPU 配置反被拒、錯誤訊息還文不對題。改為只處理 result.Driver == DriverName 的 result(把官方 dra-example-driver 本就有的守衛補回)· +175/−1、2 檔 · kind/bug、Fixes #26、Prow 合併
prepareDevices 的 result 迴圈對每筆 result 都查自家 allocatable,別 driver 的裝置不在集合裡 → 混用兩 driver 的 claim 整包回 not allocatable、pod 起不來(config 路徑的 GetOpaqueDeviceConfigs 早就跳過別 driver、result 迴圈漏了同一步)。改為 result.Driver != DriverName 就跳過 · +81/−0、2 檔 · Fixes #322、maintainer prb112 合併
deviceClassMappings 是啟動時才讀的設定:改了要重啟 controller 才生效,線上熱改不會被撿起來(DRA autoscaling 相關)· +16/−0、1 檔 · kind/documentation、area/dra、Prow 合併
nostd::string_view::data() 指向 view 首字元、非 C string,凡讀到 NUL 才停的地方都會越界(4 處):最狠的是 HttpSslOptions 用 strncmp(url.data(),"https:",6) 把 5 字元的 https view 多讀一 byte 誤判成 https、擅自開 caller 沒要求的 TLS。改為在 view 長度內比較、header log 改用帶長度的 operator<< · +31/−5、6 檔 · [BUG] Stop reading past a non-NUL-terminated string_view(maintainer Marc Alff 合併)
kueue.x-k8s.io/priority-class label 指向不存在的 class 時,ExtractPriority 會回傳查找錯誤、且不 fallback 到 Pod PriorityClass 或預設優先權,錯誤在 client.Create 前就傳播 → Workload 根本沒被建立(update 亦然)。本 PR 把此行為與「省略 label 時的 fallback」差異寫進文件 · +8/−0、1 檔 · kind/documentation(不關閉 #3439,那筆追蹤加 Warning event)· maintainer 經 lgtm+approved 由 Prow 合併
rv32i-prebuilt.sh 把 count.txt 當可選、比對前又剝掉所有非數字字元,於是沒有該檔的 release 也能過、1x2 被讀成 12。改為要求 count.txt 恰為一個正十進位整數,缺失/格式錯/與 ELF 數不符即 exit 77,並加離線案例(fail-closed 中繼資料驗證) · +144/−12、3 檔 · sysprog21(Jserv)、maintainer jserv 合併
reservedcpus 也能設到 ReservedCPUs),但周邊兩處以精確名稱比對:rejectExcludedFields 讓折疊拼法把 schema 排除的欄位(如 bindaddress→BindAddress)偷渡進來;Load 的旗標優先權刪除也按精確名稱,使檔案的 reservedcpus 蓋過顯式 --reserved-cpus(與旗標語意相反)。改為拒絕拼法與 Config 正規 json tag 不符的設定鍵(不折疊比對、避免同鍵兩拼歧義,fail-closed)· +252/−3、3 檔 · kind/bug(先於 #272 落地;lgtm+approved 經 Prow 合併)
decode_word() 把所有 opcode 0x67 一律當 JALR、所有 0x73 一律當 SYSTEM:0x00009067(JALR funct3 為保留值)被當 direct jump 降階、0x00001073(CSR 指令)在 a7==93 時變成 SYS_EXIT。改為 JALR 要求 funct3==0、SYSTEM 只認精確 ECALL/EBREAK 指令字、其餘標 illegal,analyze_syscalls() 比對精確 ECALL 字,並加手工編碼回歸案例(decoder 正確性 bug、無自報 issue) · +58/−6、3 檔 · sysprog21(Jserv)、maintainer jserv 合併
apierrors.IsNotFound 區分真缺席與暫時失敗,後者回傳錯誤重新入列 · +330/−10 · CNCF Sandbox · Fixes #2764
misc-use-internal-linkage 警告 · +22/−8、6 檔
countConfiguredMDEVRamFBs 把「present 但 enabled 未設」的 vGPU ramFB 當關閉,但 SetDefaults_FeatureState 會把未設的 Enabled 補成 true → validator 與欄位預設值語意矛盾,VM/VMIRS 接受、VMI 卻被拒;改為未設即當 enabled · +114/−1 · kind/bug · release-note · Fixes #18541
batch_span_processor_test、tracer_test、tracer_provider_set_test、直方圖 exemplar reservoir 等)移進匿名 namespace 強制 internal linkage,收掉對應的 misc-use-internal-linkage 警告 · +27/−7、7 檔
spec.secondaryControlPlaneLoadBalancer 設為 null 移除時,AWSCluster 的 validating webhook 會 nil pointer dereference panic:ValidateUpdate 只在新舊值皆為 nil 時才跳過該組,於是 oldlb != nil、newlb == nil 走進既有 LB 分支並解參考 newlb;改為明確拒絕這種移除並回傳驗證錯誤 · +96/−14、2 檔 · kind/bug · release-note · Fixes #6129
ext/http 內嵌伺服器最後 5 個 misc-override-with-different-visibility 警告(#4215 當時延後處理的部分):HttpServer 以 private 繼承 SocketCallback,四個 onSocket* override 由 protected 對齊為 private;Reactor 以 protected 繼承 Thread,onThread 由 public 對齊為 protected。這些 override 只透過基底介面派發,故不影響相容性 · +8/−4、4 檔 · 完成 #4195
WritableMetricStorage* fixture 移進匿名 namespace 以強制 internal linkage(misc-use-internal-linkage),消掉 7 個 clang-tidy 警告、warning_limit 降至 156/166;這四個檔各自定義同名的 WritableMetricStorageTestFixture 且都連進同一個 //sdk/test/metrics:all_tests,逐 TU 匿名 namespace 同時解掉 gtest 套件名衝突 · +47/−20、6 檔 · Part of #4196
InitDriverPodConfig() 啟動時載入一次、以 sync.RWMutex 快取供併發安全讀取,回應 issue #12015)· +1139/−0、13 檔、size/XXL · 2025-11-07 開啟,歷經 8 個多月審查於 2026-07-23 合併
roundUpRange 的 min+step*n 對大 capacity 請求溢位成負 → 配置了一個其實無法滿足的 device;Fixes #140441;kind/bug · release-note;pohly 認定為 #140666 驗證層的「執行期防護」另一半)
Quantity.Sign()、算術卻用會截斷的 Quantity.Value(),2^64 因此通過守衛後除零;kind/bug · release-note,Fixes #140472,經 pohly 與 liggitt 核准)
validateVendorOrClassName 切 name[1:len(name)-1] 時未擋 len(name)==1,會算出 name[1:0] 而 slice-bounds panic;兄弟函式 ValidateDeviceName 本來就有這道守衛,Fixes #320,由 maintainer elezar 合併)
註:以上為 upstream merged PRs 時序總覽(預設顯示最近數筆,點上方按鈕展開全部);完整逐 repo 紀錄見下方各 Foundation 區塊。
Reference
給想知道「哪個 foundation 下哪個專案有幾個 PR」的人。每個 repo 名稱都連到該 repo 內我所有 PR 的過濾結果。
string_view::data() 被當 NUL 結尾 C string 讀過頭(4 處;含 HttpSslOptions 把 5 字元 https view 多讀一 byte 誤判成 https、擅自開 TLS)→ view 長度內比較(Marc Alff 合併)(2026-08-04);#4327 ext 標頭安裝從 *.h glob 改為明確清單(標頭列名才進套件、改名/刪除即當場報錯),移除 default_factory.h、curl client/operation 及內嵌 server 的 http_server.h/socket_tools.h 共 5 支實作/伺服器標頭出安裝面(貢獻 #1980、承 #4315 稽核)(2026-08-04);#4298 Elasticsearch exporter 的 waitForResponse() 在無述詞的 cv_.wait 上等待,通知早於 waiter parking 即遺失致永久阻塞(lost-wakeup;失敗路徑更未持鎖記狀態、spurious wakeup 又誤報失敗);改於鎖內記 CompletionState、以述詞等待(Fixes #4296,maintainer Marc Alff 合併)(2026-08-03);#4326 Windows CI 補跑 ext_http component 安裝測試(清單有 ext_http_curl 卻漏 ext_http,該測試在 Windows 從未 configure/build;由 #4315 稽核拆出、maintainer dbarker 合併)(2026-08-01);#4292 SocketAddr 字串解析兩平台記憶體安全(POSIX 讀未初始化位元組、Windows 越界寫;改用單一 inet_pton 解析器+valid/invalid 契約,Fixes #4290、#4291、屬 ext/http 稽核 #4287、maintainer Marc Alff 合併)(2026-08-01);#4289 HttpServer use-after-free(handleConnectionClosed() 以 map::erase 銷毀 Connection 後,processRequest() 未 return 仍寫 conn.response.*、對已關 socket sendMore,Fixes #4288)(2026-07-31);#4302 SDK common/logs 測試 helper 移入匿名 namespace(misc-use-internal-linkage 第二批,接續 #4301、Part of #4196)(2026-07-28)deviceClassMappings 變更需重啟 controller 才生效(area/dra)(2026-08-04);#13645 docs 釐清 kueue.x-k8s.io/priority-class label 指向不存在的 WorkloadPriorityClass 時,ExtractPriority 回查找錯誤、Workload 於 client.Create 前即被擋(不 fallback 到 Pod PriorityClass 或預設)(2026-08-04);#12897/#12909/#12945/#12954 DRA 配額會計 int64 溢位與 counter 夾值加固(含 count==1 進位測試)(2026-07-10)/var/lib/kubelet、搬過家的叢集跑不動:新增 --kubelet-root-dir、要求絕對路徑、空值 fail-closed 拒絕不 fallback;已合併的 #273 為其前置)(2026-08-04);#273 拒絕拼法與 schema 正規 json tag 不符的設定鍵(encoding/json 大小寫折疊讓 reservedcpus 偷渡到 ReservedCPUs、且蓋過顯式 --reserved-cpus,折疊的排除欄位如 bindaddress 亦繞過;改 fail-closed 拒收)(2026-08-03);#259 Load 收斂 flag 掃描範圍、不再對 --config、klog --v 等非 Config 欄位誤記 flagToJSONKey error(涵蓋性交回 TestFlagToJSONKey_CoversAllFlags 保證)(2026-07-30);#257 處理 SIGTERM 讓優雅關閉能執行清理(Fixes #253)(2026-07-27);#215 StopContainer claim-release test + lifetime invariant (2026-07-09)prepareDevices 對整包 Results 套 TPU 專屬檢查(full-chip 數/allocatable/container edits),claim 若同時含別 driver 裝置則完整 TPU 配置被拒;改為只處理 result.Driver == DriverName 的 result(把官方範本本就有的守衛補回,Fixes #26,kind/bug、Prow 合併)· Google 的 Kubernetes TPU DRA driver(2026-08-04)ramFB.enabled 當 enabled、對齊 SetDefaults_FeatureState(修 validator 與欄位預設值語意不一致致 VMI 被拒,Fixes #18541,kind/bug · release-note)· CNCF Incubating(2026-07-26)apierrors.IsNotFound 區分真缺席與暫時失敗、後者 requeue 而非刪掉既有 Release(Fixes #2764,由 maintainer LakshanSS 合併)· CNCF Sandbox(2026-01-06 接受)· Kubernetes 開發者平台(2026-07-27)WorkflowSpec/Template 層 resourceClaims 貫穿到 pod,實作自本人提案 #16576,+3343/−2、33 檔,lead maintainer Joibel 合併並排進 4.1-rc2)(2026-07-31);#16591 把該修正 cherry-pick 到 release-4.0(自動 pick 因 archiveWorkflow wrapper 衝突、手動解衝突,由 Joibel 合併,2026-07-31);#16577 controller archive 每個 workflow 只歸檔一次(修 archiveWorkflowAux 成功路徑雙重呼叫、雙寫 archive DB 且顛倒錯誤處理),並補上暫時性 DB 錯誤重試(納入 lead maintainer Joibel 邀請的 #15780,由 Joibel 合併)· CNCF Graduated · Argo 工作流引擎(2026-07-31)--k_mac 加入 3GPP kmac-r17 1–512 範圍驗證(關閉 #577)· !1047 驗證 ta_common + ta_common_offset 不超過 ASN.1 taCommon-r17 合法範圍(關閉 #579)· !1097 在 eci_to_orbital 的 acos 引數前 clamp 到 [-1,1],防合法幾何於 apoapsis 因浮點 round-off 使 cosine 微超 -1 → acos NaN 汙染整組軌道要素與 SIB19 ephemeris · O-RAN 5G CU/DU full-stack 實作,其中三筆為 NTN 協定正確性修正status: maintained · 2 merged · #110205 StickS3 板級支援,由 Zephyr TSC 主席 nashif 合併(2026-07-13)maps.Values 序、每次重啟順序不同、且影響 scheduler first-fit)+ #76 .gitignore 錨定 binary 樣式(原未錨定、連 cmd/ 原始碼目錄一起忽略) · AMD 官方 Kubernetes GPU DRA driver(ROCm)、maintainer bhatnitish 合併(2026-08-04)prepareDevices 的 result 迴圈對每筆 result 都查自家 allocatable(config 路徑的 GetOpaqueDeviceConfigs 早就跳過別 driver、result 迴圈漏了)→ 混用兩 driver 的 claim 回 not allocatable、pod 起不來;改為跳過別 driver 的裝置(Fixes #322,maintainer prb112 合併)· IBM Power 架構的 Kubernetes DRA driver(2026-08-04)jalr ra 的返回點(用共用 is_link_call() 統一 successors/compute_promotions/返回點收集,防走 jalr 返回路徑讀到歸零 promotion cell)+ #18 leader discovery 改為 reachability-aware(不可達的控制轉移不再把可達塊裡的指令誤標為 leader、切割 live block,避免誤拒合法 ecall;重算至定點)+ #13 不支援的 JALR/SYSTEM 解為 K_ILL 後令其終止基本塊與 CFG 遍歷(防常數傳播跨越不可達字而誤解後續 JALR,#12 的後續)+ #16 RV32I rolling-release 改用 SHA-256 內容 manifest(不再只比 ELF 數量、避免 stale release)+ #14 count.txt 嚴格驗證(fail-closed,畸形/缺失 exit 77)+ #12 RISC-V decoder 拒絕非法 JALR/SYSTEM 編碼(funct3≠0、精確 ECALL/EBREAK 指令字) · SUBLEQ+MUX 雙指令 VM、自舉 Forth、編 RISC-V(sysprog21/Jserv)(2026-08-04)In Progress
對這些專案已送出、正在上游審查的 PR。尚未合併,不計入上方 152;列在此是因為它們是往 vLLM、Prometheus、Magma 等專案的實質 pipeline。完整即時清單見 GitHub。
.shape(Closes #32127)(審查中)errors.Join(err, err) 打字錯誤吞掉 socket 清理失敗(Close() 回報成功卻留下 stale socket、下次啟動撞上)、converting client 的 v1beta2 UpdateStatus 誤用 v1beta1 client 觸發型別斷言 panic、device taint 的 copyTaintTimeAdded 逐 taint 重複 clone 整個 device 而丟失前一 taint 的 TimeAdded(審查中);另 #141170 為 SIG API Machinery 對 resource.Quantity int64 溢位的官方 burndown(#141166)撰寫 baseline accessor 測試矩陣——記錄 Value/MilliValue/ScaledValue 等各 accessor 現況、對錯誤值標 TODO,讓後續每個修正對已知基準做 diff(+663/−0、tests-only、審查中);#140674 對稱補上 resource.MaxMilliQuantity 常數並修正 Quantity 文件(同屬 #141166 burndown、#140135 gate 在其後,審查中)priority-class label 變更(修自報的 #13778):ensureOneWorkload 的 slicing 分支一判定「相容」就直接 return,而那個 return 落在唯一套用優先權轉換的 UpdateWorkloadPriority 之前 → 純 label 編輯帶著舊 priority 就回去了;相容性只講 pod set 形狀、不含優先權。改為相容路徑也套用 priority-class 變更(審查中)Kubernetes DRA
8 個 driver · 7 個組織 · 其中 4 家同一個「多-driver claim」缺陷(★)
Dynamic Resource Allocation(DRA,Kubernetes 1.34 GA)讓每個廠商用自己的 driver 把硬體交給排程器。我沿用缺陷變體分析法橫向稽核多家 driver,發現一個反覆出現的共通假設:「claim.Status.Allocation.Devices.Results 裡的每一筆都是我這個 driver 的」。但一個 ResourceClaim 可由多個 driver 一起滿足,於是這個假設在四家不同廠商的 driver 上各自爆開(★ 標記)。這與我在 Kubernetes 核心的 int64 溢位家族是同一種方法,換到裝置管理層。回報中/進行中項目不計入頁首數字;已 merged 的修正已列入上方合併清單。
prepareDevices 把整包 Results 都套 TPU 專屬檢查(full-chip 數、allocatable、container edits)→ 同一 claim 又要別 driver 的裝置時,完整 TPU 配置反被拒(錯誤訊息還文不對題)。改為只算本 driver 擁有的 result · 自報 #26 + 自修 #25
prepareDevices 逐一在本 driver 的 allocatable 查每個 result,別 driver 的裝置不在集合裡 → 整包回 not allocatable、混用兩 driver 的 pod 起不來(config 路徑 GetOpaqueDeviceConfigs 早就跳過別 driver,result loop 漏了)。改為 result.Driver != DriverName 就跳過 · 自報 #322 + 自修 #323
#59 prepareDevices 拿別 driver 的 result 去對 Spyre 裝置 map 解析、多-driver claim 整包失敗;#58 Unprepare 在 CDI spec 檔已消失時對 nil 取 ContainerEdits → nil 指標 panic
#136 status update 撞 conflict 重試時,把整個 status.devices 換成第一次嘗試前的快照 → 別 driver 在衝突視窗內寫的條目被蓋掉(同家族,這次落在 status-retry 路徑)· 自修 #137(+243/−4)審查中
上游參考實作:已合併 #215/#257/#259/#272/#273(設定鍵大小寫折疊繞過排除、kubelet-root 可設定且 fail-closed、SIGTERM graceful shutdown 等,詳見上方時序);#274/#282 為 kubelet-root 收尾(chart wiring + relocated-root e2e,修自報 #231)
已合併 #74/#76:ResourceSlice 裝置依 Go map 序發佈、每次重啟順序不同(影響 scheduler first-fit)→ 按名稱排序;.gitignore 未錨定連 cmd/ 原始碼一起忽略
shadow claim 身分與生命週期一叢(皆自報自修):名字漏帶 UID 致同名重建認領到舊 shadow(#66)、unprepareClaim 失敗前先丟 recovery state 致資源洩漏被 retry 掩蓋(#67)、prepareClaim 忽略啟動時還原的狀態(#68)、auto-pairing 讓兩個 composite 裝置共用同一實體裝置(#69)
#73 mutating webhook 的 addAnnotationSelectors 用 fmt.Sprintf 把原始 annotation 值直接拼進 CEL 字串字面值,沒 quote 也沒 trim。值裡帶引號或反斜線就長出 ["GPU-1""],API server 驗 CEL 時擋下、webhook Create 失敗、回滾前面容器已建的 claim、pod 被拒,還只回一個 CEL parse 錯誤看不出是 annotation 的問題;沒 trim 的安靜版是 GPU-1, GPU-2 變成含空格的 " GPU-2"、比不到任何裝置
O-RAN / NTN
11 個缺陷 · 分屬 5 種類別 · 同一 NTN SIB19 更新路徑
OCUDU(Open Centralized Unit Distributed Unit)是 srsRAN Project 的後繼專案,承襲其 5G CU/DU 程式碼、系統架構與開發脈絡。程式碼由 GitHub 移轉至 GitLab,主要授權亦由 srsRAN Project 的 AGPLv3 改為較寬鬆的 BSD-3-Clause-Open-MPI。OCUDU 的初始建置計畫於 2025 年公布,由美國 FutureG Office 透過 National Spectrum Consortium 提供經費,交由 DeepSig 與 Software Radio Systems(SRS)共同建置初始軟體。
Linux Foundation 於 2026 年 3 月 1 日在 MWC Barcelona 宣布成立 OCUDU Ecosystem Foundation,將技術專案置於中立、跨組織的開源治理架構之下。創始成員包括 AMD、AT&T、DeepSig、Ericsson、Nokia、NVIDIA、SoftBank、SRS 與 Verizon。SRS 是初始 CU/DU 程式碼的重要建置者及核心技術貢獻者之一。
OCUDU 並非在 2026 年 7 月才開始支援 NTN(Non-Terrestrial Network,非地面網路)。其前身 srsRAN Project 在 24.4 版已加入 GEO NTN 與 SIB19 支援,OCUDU 的初始 26.04 版本亦保留 GEO NTN 能力。2026 年 7 月期間 dev 分支密集合併 SIB19 廣播、TN/NTN 鄰區資訊、衛星切換、饋電鏈路 timing advance 與動態 SIB19 更新等擴充,是 NTN 實作快速演進與協定正確性加固的階段。
我沿用前述缺陷變體分析方法,對這條剛落地的 NTN SIB19 更新路徑(du_high、du_manager、MAC 排程與 ntn 數學)逐段稽核,辨識出 11 個缺陷、分屬五類:記憶體生命週期、環狀與規範時間邊界、數值退化與界限、錯誤處理與交易性、狀態失同步。這與我在 Kubernetes 上的 int64 溢位家族是同一種方法,換到 5G NTN 協定棧。
以下皆為回報中;其中 10 項已提出修正 MR(!1096、!1153、!1162、!1163)正在 SRS 審查,1 項(#660)尚未提交。均不計入頁首的 Merged PR 或 Found & Fixed,待 MR 合併再逐筆計入。
SIB19 更新把非持有 span 與區域 request 的 reference 交給延後 coroutine,呼叫端返回後即成 dangling
後續 DU update 與 MAC reconfiguration 讀已釋放記憶體 · 回報 #643 → 修正 !1153 審查中(詳見下方縱深一)
slot_point 在正好半個 hyperframe 處排序未定義,佇列中的 SIB19 更新可能早約 512 frames 套用
si-Periodicity rf512 恰為 1024-frame hyperframe 之半、踩在比較邊界 · 回報 #649 → 修正 !1096 審查中
epoch time 比 TS 38.331 定義的 SI-window end 晚一個 slot(15 kHz 為 1 ms)
epoch 是 serving-satellite ephemeris 與 Common TA 的時間參考,偏移使衛星位置參考失準 · 回報 #659 → 修正 !1096/!1163 審查中
赤道或圓形軌道(合法幾何)令 acos 分母歸零,NaN 灌進還原軌道要素、SIB19 與 ephemeris propagation
eci_to_orbital 的 0/0 → acos(NaN)=NaN · 回報 #660(尚無修正 MR,最乾淨的 Found & Fixed 素材)
sib_idx 從 unsigned 窄化為 uint8_t 無範圍檢查,>255 靜默截斷後才進 MAC
SI 緩衝的 tbs ≤ 2048 界限只有 debug assert,release build 無守衛 → OOB read
封裝把固定 2048-byte 緩衝以 grant tbs 長度的 span 交下層、無 runtime 檢查 · 回報 #652 → 修正 !1153 審查中
主控迴圈佇列(bounded 128)滿時,NTN 參數更新無 log、無 retry、無 error 靜默丟棄
更新無交易邊界,中途失敗留半套狀態;多 cell 時已提交的 cell 跳過 F1AP CU 通知
assistance info 在 SIB19 reconfig 可能失敗前就寫進 live cell config · 回報 #654 → 修正 !1153 審查中
忽略 update_ntn_assistance_info 的 false 回傳,更新失敗的 cell 仍走完流程並可回報成功
多 PDU 逐一 push,中途某次失敗即返回,已 push 的留在佇列不回滾 → 部分套用
encoder 向量每次 reconfig 縮放、content cache 只增;特定 remove-then-re-add 後未變內容的 SI 被廣播成全 0
SIB19 更新路徑將指向區域 std::vector<byte_buffer> 的 non-owning span,連同對區域 request 的 reference,交給延後執行的 coroutine。原始 handler 返回後,request 與 span 的 backing storage 均已失效,使後續 DU update procedure 與 MAC reconfiguration 讀取已釋放的記憶體。
修正 !1153 將 SI message buffers 改為由 request 持有,並以 value/move semantics 端到端傳遞至 coroutine 與 procedure。新增的端到端回歸測試經 ASan 驗證:修正前觸發錯誤、修正後通過;另以 mutation testing 分別還原 reference capture 與 non-owning span,確認測試能獨立捕捉兩條生命週期失效路徑。
#653、#654、#655 與 #657 不是四個孤立缺陷,而是同一條 NTN parameter update 程序端到端缺乏錯誤處理與交易性的四個面向:佇列滿時靜默丟棄、失敗留半套狀態且不 rollback、忽略失敗回傳報假成功、MAC 多 PDU 中途失敗不回滾。逐段稽核比逐個修 bug 高一階之處,正在於指出這種系統性的品質缺口,而非只撿到四個 bug。
#642 epoch_time 設定契約:serving-cell 的 epoch_time 文件化為 SIB19 EpochTime 的覆寫值,但 build_sib19_info 從未讀取;因同一 epoch 亦用於 ephemeris propagation,宜整體處理。目前等待維護者決定完整實作 override 或移除欄位並保留 epoch_sfn_offset。
#633 CI 供應鏈(非 NTN 協定):CodeChecker CI builder 釘 6.26.1,其 bundled ldlogger 受 CVE-2025-40843 影響(6.26.2 已修);現行 CI 使用 analyze/parse、未觸及受影響的 CodeChecker log,屬預防性升版與供應鏈衛生。
Peer Review · Issues · Cross-Platform
GitHub merged PR 之外的貢獻,分三類:A 學術同儕審查、B 自己回報又自己修好並合併的上游 bug(端到端,對應摘要的 26 Found & Fixed)、C 我回報但由他人修復或仍在審查中(誠實標注、不計入 merged)。
ResourceClaim 可由多個 driver 一起滿足,prepareDevices 卻對整包 Results 都跑 full-chip 數、allocatable 查找與 container edits → claim 同時含別 driver 裝置時,完整 TPU 配置反被拒、錯誤訊息還文不對題 · 自行修復 → PR #25 merged(只處理 result.Driver == DriverName 的 result,把官方 dra-example-driver 本就有的守衛補回,Fixes #26,kind/bug、Prow 合併)· Issue 以 completed 關閉
GetOpaqueDeviceConfigs 早就跳過別 driver,result 迴圈卻對每筆 result 都查自家 allocatable → 混用兩 driver 的 claim 整包 not allocatable、pod 起不來 · 自行修復 → PR #323 merged(result.Driver != DriverName 就跳過,Fixes #322,maintainer prb112 合併)· Issue 以 completed 關閉
map::erase 銷毀 Connection 後仍存取它(use-after-free):m_connections 是 std::map<Socket, Connection>,handler 回傳 -1 觸發 handleConnectionClosed() 的 erase 後,processRequest() 未 return 就續寫 conn.response.*、組 status line、對已關 socket sendMore · 自行修復 → PR #4289 merged(Fixes #4288)· Issue 以 completed 關閉
ResponseHandler::waitForResponse() 在無述詞的 cv_.wait(lk) 上等待;OnResponse 在釋放鎖後才 notify_all,通知早於 waiter parking 即遺失、匯出執行緒永久阻塞(OnEvent 失敗路徑更未持鎖、未記任何狀態,Destroyed 亦不通知不記錄),spurious wakeup 又把在途請求誤報失敗 · 自行修復 → PR #4298 merged(改於鎖內記錄明確 CompletionState、以述詞等待,Fixes #4296,maintainer Marc Alff 合併)· Issue 以 completed 關閉
char[16] 並於固定索引截斷,凡 host 短於 15 字元 inet_pton 即讀到不定值,髒堆疊上把 1.2.3.4:80 靜默解析成 0.0.0.0:80 · 自行修復 → PR #4292 merged(Fixes #4291,同 PR 一併修 #4290,屬 ext/http 稽核 #4287)· Issue 以 completed 關閉
sizeof(buf)(位元組數)為界卻索引 WCHAR[200] 陣列,逾 200 字元的位址最多寫穿 400 位元組 · 自行修復 → PR #4292 merged(兩平台改用單一 inet_pton 解析器+valid/invalid 契約,Fixes #4290、#4291、屬 ext/http 稽核 #4287、maintainer Marc Alff 合併)· Issue 以 completed 關閉
min+step*n 溢位成負,配額會計因此把一個實際上無法滿足的 device 判成可配置(sig/node · wg/device-management)· 自行修復 → PR #140442 merged 進 Kubernetes 核心(kind/bug · release-note)· Issue 以 completed 關閉
validRange.step 除零,在 step 為 2^64 的倍數時重新出現:那道守衛用的是精確的 Quantity.Sign(),但後續算術用的是超出 int64 就截斷的 Quantity.Value(),於是同一個值 Sign()==1 通過守衛、Value()==0 直接除零(sig/node · wg/device-management)· 自行修復 → PR #140666 merged 進 Kubernetes 核心(kind/bug · release-note)· Issue 以 completed 關閉
validateVendorOrClassName 對 name[1:len(name)-1] 沒有 len(name)==1 的守衛,於是算出低界大於高界的 name[1:0];報告中指出兄弟函式 ValidateDeviceName 本來就有同一道守衛,因此是疏漏而非刻意拒絕 · 自行修復 → PR #321 merged · Issue 以 completed 關閉
--k_mac 是唯一沒有 CLI 範圍檢查的參數(3GPP kmac-r17 定義為 INTEGER 1..512;其餘 NTN CLI 參數如 cell_specific_koffset、ta_common 皆有 CLI::Range)· 自行修復 → MR !1045 merged 進 dev(Fixes #577)· Work item 已結案
spec.secondaryControlPlaneLoadBalancer 設為 null 移除時,AWSCluster 的 validating webhook 以 nil pointer dereference panic(ValidateUpdate 只在新舊值皆為 nil 時跳過該組,oldlb != nil、newlb == nil 因而走進既有 LB 分支解參考 newlb)· 自行修復 → PR #6130 merged(kind/bug · release-note,改為明確拒絕移除並回傳驗證錯誤)· Issue 以 completed 關閉
int64 上加總使用者可控的 device count,溢位後把超額 Workload 判成可配置(與已 merged 的 kueue #12896 同一 int64 溢位家族)· 自行修復 → PR #5621 merged(新建 SaturatingAdd/Mul · CNCF Incubating)· Issue 以 completed 關閉
FindPosition 對 deep-space 軌道靜默回傳 err == nil 的錯誤結果(SGP4/SDP4 邊界未拒絕)· 自行修復 → PR #11 merged(拒絕 deep-space 靜默錯誤;另 #12 Vallado SGP4-VER 正典驗證)· Issue 以 completed 關閉
countConfiguredMDEVRamFBs 把「present 但 enabled 未設」的 ramFB 當成關閉,與 SetDefaults_FeatureState(未設補 true)矛盾,導致 VM/VMIRS 接受但 VMI 被拒 · 自行修復 → PR #18542 merged(kind/bug · release-note · CNCF Incubating)· Issue 以 completed 關閉
kueue.x-k8s.io/priority-class label 不會更新既有 Workload 的優先權——label 變更被接受卻無效,Workload 保留舊 priority 與舊 priorityClassRef;不限於指到不存在的 class,從一個合法 WorkloadPriorityClass 改成另一個合法的也照樣被吞,Job 與 Workload 對優先權各說各話、且無事件回報(正常路徑 ensureOneWorkload 會呼叫 UpdateWorkloadPriority 並發 UpdatedWorkload 事件)· 附可重現的 TestReconciler 案例 · 自行修復 → PR #13780 審查中(Closes #13778、尚未合併、不計入 merged)
UpdateWorkloadPriority → PrepareWorkloadPriority → ExtractPriority 每次都自己 Get 一遍,N 個 Workload 就 N 次讀取、彼此不共享結果。LeaderWorkerSet 最尖銳——parallelize.Until 把更新 fan-out 成 N 個 goroutine 併發各自 resolve,class 值若在 fan-out 途中變動,各 component 就被寫成同一 class 的不同值;一般路徑是同形狀的 sequential 版(#13780 的 scale-up 又多一處:quota-reserved slice 與待替換 replica 在同一 reconcile 一起更新)。且不會自癒:WorkloadPriorityClassReconciler 靠 class 名稱 list,發散後雖仍同名、卻得等下一次該 class 值更新才被一起拉回 · 承 #13778/#13780 同一子系統的更深一層 · 回報中、待修,不計入 merged
ensureOneWorkload 一判定 slice 相容就只同步優先權後 return,而一般路徑還會套用 AdmissionGatedBy annotation 與最大執行時間等更新 → elastic Job 改這些欄位都到不了既有 Workload(#13836)。根因是該路徑「邊決定邊寫」:count 與 priority 非原子寫入、chain 還被走訪兩次;提案讓 EnsureWorkloadSlices 回傳決策、由 caller 統一執行寫入(#13837,cleanup)· 回報中、待修,不計入 merged
reconcileWorkload,它同步 owner ref、queue name、AdmissionGatedBy 與 scale-to-zero hold,卻不呼叫 UpdateWorkloadPriority/PrepareWorkloadPriority(優先權只在無 Workload 時的 createPrebuiltWorkload 解析一次);webhook 的 ValidateUpdateForWorkloadPriorityClassName 只擋「對執行中 workload 加 label」與「移除 label」,把一個合法 class 名改成另一個是放行的 → label 進得去、存得住、kubectl get 看得到,Workload 卻保留原優先權 · 回報中、待修,不計入 merged(自報的 #13792 為誤開重複、已自行關閉 supersede 到此)
OtlpGrpcClient::ForceFlush 的 wait loop 對「任一通知」就 break(wait_for != timeout 在被喚醒時為真),而 loop 條件才是唯一讀 finished_request_counter 的地方、被這個 break 跳過 → 多個在途請求只要一個完成就結束等待、還回傳剩餘時長而非 predicate;兩個 client 又都以 exporter 的 export_timeout 為界、不理會 caller 傳入的截止時間(overrun)· 自修 → PR #4357(+78/−12)審查中(maintainer owent 已確認反向比較;改以 loop 條件決定、wait 以 caller 剩餘時間為界;屬部分修正、尚未 close #4339,不計入 merged)
ForceFlush 未等在途請求就回報成功(自報 #4336 → 自修 #4337,+967/−83)、bulk export 未依 HTTP 狀態與回應的 errors 旗標判定成敗(自報 #4295 → 自修 #4297)、exporter 的等待不會在 read/write error 時結束(maintainer lalitb 回報 #4330 → 自修 #4331)· 三支 PR 審查中,不計入 merged
SocketAddr(u_long, int) 對 port 做 uint16_t 轉換前未檢查範圍,負值或 >65535 會 wrap 成別的 port(addListeningPort 會用到)· 由社群貢獻者 noob339 依本報告撰寫 #4320 修正(SocketAddr/addListeningPort 加範圍驗證、拒收 -1/65536/99999)審查中(該 PR 為他人作品、不計入本站 merged)· 另有本人 #4307 追蹤同建構子的 misaligned 存取與截斷
roundUpRange int64 溢位+除零:min + step*n 以 int64 計算,near-max 容量請求相乘溢位為負 → 消耗量被低估、共享裝置被超額允收(負的 consumed 在 checkCapacity 反而「釋出」容量);另 added/step 與 violateValidRange 的 % step 未檢查 step==0 → 除零 panic。這些 helper 由 k8s.io/dynamic-resource-allocation 手抄(原碼註明「equivalent to upstream」),故上游同缺陷 · 由 maintainer ryan-mist triage/accepted 並請一併開上游 issue(延續我的 int64 溢位家族 kueue #12896/volcano #5620)· 回報中、待修,不計入 merged
.shape:set_data_3d 文件宣稱吃 array-like 並照收 list,draw 卻讀 _verts3d[0].shape,於無效座標的 mask 分支觸發 AttributeError(3.11 迴歸)· 自行修復 → PR #32128 審查中(Closes #32127,尚未合併、不計入 merged)· matplotlib(NumFOCUS)
val_in_range 以陣列呼叫既有 limit_range_for_scale(連 matplotlib 自身 LogScale 都寫成 scalar 版),丟出的 ValueError 被過寬的 except (TypeError, ValueError) 當成「無點在範圍內」→ 全部標無效換成 NaN、artist 靜默消失(相容性迴歸、無警告無例外)· 回報中,不計入 merged
map[string]DeviceAttribute),同一 request 內的多個 device 因此互相覆蓋(sig/node · wg/device-management)· 經上游貢獻者 GunaKKIBM 依本報告撰寫修復 → PR #140600 merged 進 Kubernetes 核心(2026-07-17;該 PR 為他人作品,不計入本站 merged 數)· Issue 以 completed 關閉
minMember 與 minResource 兩個運算元都直接取自 yunikorn.apache.org/task-groups pod annotation 且未設上界,因此乘積、跨 task group 的加總、乃至 Quantity 的 int64 accessor 本身都可能 wrap,最終把負的 PlaceholderAsk 送進 core(Bug · Major · shim - kubernetes)· 由 YuniKorn PMC 成員 Wilfred Spiegelenburg 分類並指派給我 · 修復 PR #1053 仍在審查中(尚未合併,不計入 merged 數)