Kubernetes v1.37 前瞻:kube-proxy IPVS 模式進入淘汰倒數,cgroup v1 支援持續收斂
Kubernetes 官方部落格 · 2026-07-31
Kubernetes 官方部落格於 2026 年 7 月 31 日發布 v1.37 Sneak Peek,提前公開這個版本的幾項棄用與行為變更。內容涵蓋 kubectl run 的參數精簡、Static Pod 存取 API 資源的限制收緊,以及 kube-proxy IPVS 模式正式進入棄用時程。文章也重申 cgroup v1 支援將持續往 cgroup v2 收斂的既定方向。
核心改動
kubectl run --filename(簡寫 -f)參數在 v1.37 被標記為棄用。官方認為這個參數與指令定位不符,因為 kubectl run 產生的 Pod 一律只依據 NAME、--image 等 CLI 參數組成,並非讀取檔案定義,相關討論見 kubernetes/kubernetes#138671。同一版本也移除了 PreventStaticPodAPIReferences feature gate,並將限制永久生效:Static Pod 的定義中不得再透過 configMapRef、secretRef 之類欄位讀取 Secret 或 ConfigMap。這項限制源自 Static Pod 本來就不經過 API Server 建立,先前允許讀取屬於歷史遺留的錯誤行為(kubernetes/kubernetes#140226)。
篇幅最重的變更是 kube-proxy IPVS 模式的棄用計畫,對應的是 KEP-5495。棄用的直接原因是 sig-network 已缺乏熟悉 IPVS 後端程式碼的維護者,而社群多年來也一直建議回報 IPVS 問題的使用者改用 nftables 模式。IPVS 模式在 v1.8 引入,原本是為了解決 iptables 模式的效能瓶頸,但 KEP-3866 早已指出 IPVS 底層仍然依賴 iptables 規則,無法完整實作 Service 語意,這也是後續改推 nftables 模式取代兩者的背景(KEP-3866)。
值得注意的是,kube-proxy 目前預設仍是 iptables 模式,IPVS 一直只是可選的替代後端,因此這次棄用影響的是「曾經主動切換到 IPVS 模式」的叢集,而非所有 Kubernetes 使用者。棄用時程橫跨多個版本,叢集維運者可依此規劃遷移窗口:
| 版本 | IPVS 模式狀態 |
|---|---|
| v1.35 | 啟動時顯示棄用警告訊息,文件同步更新 |
| v1.37(本次) | 導入可關閉的 feature gate,預設仍啟用 |
| v1.40 | feature gate 預設關閉,需手動覆寫才能繼續使用 |
| v1.43 | feature gate 鎖定為預設值,IPVS 程式碼自倉庫移除 |
要確認叢集目前使用哪種模式,可以直接讀取 kube-proxy 的 ConfigMap:
kubectl -n kube-system get configmap kube-proxy \
-o jsonpath='{.data.config\.conf}' | grep 'mode:'影響範圍
cgroup v1 的淘汰是另一條持續進行中的主線,並非 v1.37 新增,而是延續自 v1.35 的既定路徑。自 v1.35 起 failCgroupV1 預設為 true,若節點只支援 cgroup v1 且未手動覆寫,kubelet 將直接初始化失敗。需要暫時繞過的環境可在 KubeletConfiguration 中明確覆寫,但官方明確提醒這只能作為短期權宜之計。
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failCgroupV1: false # 僅作為過渡期暫時覆寫會被 cgroup v1 殘留環境卡住的並不只是相容性問題,In-Place Pod Resizing 與 Tiered Memory Protection 等資源管理特性都直接依賴 cgroup v2 才能運作。換句話說,IPVS 與 cgroup v1 這兩條淘汰路線都指向同一件事:叢集管理者若還在使用舊有的網路或資源管理堆疊,應該把升級規劃提前排入 v1.37 到 v1.43 之間的視窗,而不是等到 feature gate 被鎖死才被迫應變。這兩項變更都不是單一版本的臨時決定,而是官方過去數個版本就已公開的既定路線圖,v1.37 只是把時程再往前推進一步。
原始來源:Kubernetes v1.37 Sneak Peek、KEP-5495: Deprecate ipvs mode in kube-proxy
GitHub 揭露原始碼比對加速術:拿掉「提前中止」分支,讓大小寫摺疊跑滿記憶體頻寬
GitHub Engineering Blog · 2026-07-31
GitHub 工程團隊發表 Don't stop early,說明其程式碼搜尋引擎 Blackbird 如何重寫「大小寫摺疊」(case-folding)這個看似基礎的步驟。文章的反直覺結論是:把「遇到非 ASCII 就提早跳出」的分支整個拿掉,反而讓吞吐量從 3.1 GiB/s 跳升到超過 45 GiB/s。這個優化最終以開源 Rust crate casefold 的形式釋出。
背景
Case-folding 是把字串正規化成同一種大小寫形式的過程,用途是讓搜尋能做到不分大小寫比對,例如讓 café 能比對到 CAFÉ。這件事聽起來單純,但 Blackbird 要處理的規模是 超過 1.8 億個儲存庫、逾 480TB 原始碼,任何每位元組的多餘開銷都會被規模放大成真實的延遲與硬體成本。傳統作法是逐位元組掃描,一旦偵測到非 ASCII 位元組就轉入較慢的 Unicode 處理路徑,這個「提早分支」正是效能瓶頸的根源。
核心改動
團隊的做法是把 ASCII 快速路徑改寫成完全無分支(branchless)的迴圈。用 OR 累加器偵測整段緩衝區是否含有非 ASCII 位元組,而不是逐位元組判斷後跳出,判斷是否為大寫字母也改用純算術的 b.wrapping_sub(b'A') < 26,轉小寫則用 *b |= u8::from(is_upper) << 5 這種位元運算取代條件式寫入。少了分支之後,LLVM 編譯器得以把整段迴圈向量化,最終產生 41 條向量指令,一次處理一整個 16-byte 向量寫入。文章特別強調一個反直覺的實驗結果:只把寫入改成無分支、但迴圈仍未被向量化時,效能反而從 3.1 GiB/s 掉到 2.6 GiB/s,因為每一輪都被迫做無條件寫回;無分支寫法要等到迴圈真正被向量化,才會由「每輪都寫」變成「整批寫一次」而真正受益。
對於真正落在 Unicode 摺疊範圍內的字元,團隊設計了一張僅 1,776 位元組的緊湊查表結構,取代原本查詢成本高昂的 HashMap。這張表由四個部分組成:248 位元組的分頁點陣圖(bitmap)、32 位元組的累積 popcount 索引、每筆 238 位元組的壓縮區段紀錄,以及 952 位元組的位元組差量表(byte-delta table)。分頁點陣圖的關鍵在於稀疏性:約 1,960 個可能的 Unicode 分頁中,只有 59 頁真正包含摺疊規則,其餘分頁可以直接靠點陣圖位元跳過,對 CJK、假名等不需要摺疊的字元幾乎零額外開銷。差量表則讓摺疊可以「以小端位元組相加」直接完成,不必經過 UTF-8 解碼、轉換、再編碼的來回。
影響範圍
三種輸入情境的實測數字清楚呈現了策略的取捨:
| 工作負載 | simple_fold | simd_normalizer | HashMap |
|---|---|---|---|
| 純 ASCII(5.7 KB) | >45 GiB/s | 1.21 GiB/s | 213 MiB/s |
| CJK / 無摺疊(8.1 KB) | 2.95 GiB/s | 1.97 GiB/s | 558 MiB/s |
| 最壞情況:全部需摺疊(8.8 KB) | 869 MiB/s | 922 MiB/s | 334 MiB/s |
可以看到 新方法在純 ASCII 情境下領先既有 SIMD normalizer 近 40 倍,在真實世界的原始碼中(絕大多數是 ASCII、偶爾夾雜少量 Unicode 註解或字串)這個情境正是最常出現的一種。即使在全部需要摺疊的最壞情況下,新方法也沒有明顯輸給既有的 SIMD 實作,顯示分頁點陣圖與差量表的額外開銷被控制得相當克制。這套實作已經以 casefold 為名開源釋出,程式碼放在 github/rust-gems 專案下,並發布到 crates.io,對外提供 simple_fold、simple_fold_char 等函式,任何需要處理大規模文字正規化的系統都可以直接引用。
原始來源:Don't stop early: Case-folding source code at memory speed、github/rust-gems: casefold crate
Docker 開放 GitHub Actions 使用 OIDC 免長效憑證登入,Docker Orgs 可逐步汰換 PAT
Docker 官方部落格 · 2026-07-31
Docker 官方部落格宣布,OIDC connections for GitHub Actions 正式對 Docker Orgs 開放。這項功能讓 GitHub Actions 工作流程能以短效、單次執行有效的 Token 登入 Docker Hub,取代過去必須存放在 GitHub Secrets 裡的長效 Personal Access Token(PAT)或 Organization Access Token(OAT)。適用對象是採用 Docker Team、Docker Business、Docker Hardened Images(DHI)或 Docker Sponsored Open Source(DSOS)方案的組織。
背景
長效憑證存放在 CI Secrets 裡,一直是安全稽核的常見缺失項目:Token 一旦外洩就可能被長期濫用,而且大多數團隊不會定期主動輪替它們。隨著一個組織底下的 pipeline 數量增加,需要手動管理的憑證也跟著線性增加,進一步放大外洩與過期風險。OIDC(OpenID Connect)提供的解法是讓 CI 平台簽發的身分憑證直接與目標服務做即時信任交換,不需要事先在雙方各自保存一份共用密鑰。這個模式並非 Docker 首創,GitHub Actions 早已支援以同樣方式對接 AWS、Azure 等雲端服務,這次是把同一套信任交換機制延伸到 Docker Hub 的登入場景。
運作機制
Docker 這次導入的流程本質上是一次 OIDC Token 交換,分成幾個步驟依序發生:
- GitHub Actions 在工作流程執行時簽發一個 JWT,內含 repository、branch、environment、workflow 等中繼資料;
- 工作流程呼叫
docker/login-action,把這個 JWT 一併帶給 Docker; - Docker 依照 GitHub 公開金鑰驗證 JWT 簽章,再比對組織端預先設定好的 ruleset;
- 驗證通過後,Docker 核發一個效期僅數分鐘、且只涵蓋 ruleset 允許範圍的短效 Token;
docker/login-action用這個短效 Token 完成登入,後續的docker pull、docker push、docker build皆維持原本用法不變。
整套機制的信任錨點是 GitHub 簽發的 JWT 與 Docker 端設定的 ruleset,而不是任何雙方事先共享的密鑰,這也是為什麼外洩風險被壓縮到「Token 有效的那幾分鐘」而非無限期。
影響範圍
設定分為四個步驟。第一步是在 Docker Home 建立 OIDC connection,最多可設定 5 組 ruleset,透過 OIDC subject claim 依 repository、branch、workflow 控制存取範圍,例如 repo:my-org/my-repo:ref:refs/heads/main 只允許 main 分支,或 repo:my-org/* 開放整個組織(官方特別註明不建議這樣設)。第二步是把既有的登入步驟改成以下寫法:
permissions:
contents: read
id-token: write
steps:
- name: Docker login
uses: docker/login-action@v4 # v4.5.0+
with:
username:
env:
DOCKERHUB_OIDC_CONNECTIONID: 其中 id-token: write 權限是讓工作流程能夠向 GitHub 請求 OIDC Token 的關鍵設定,contents: read 則是維持原本讀取程式碼所需的權限。第三步是實際跑一次工作流程確認能成功登入,若失敗可在 Docker 後台的 Failures 頁籤查看診斷訊息;確認無誤後,第四步就是把 GitHub Secrets 裡原本的 PAT 或 OAT 移除。既有的 PAT、OAT 仍可繼續運作,官方將這次更新定位為漸進式遷移,image、registry、既有 build 流程都不受影響;本地開發與非 GitHub 平台的 CI 目前仍須沿用 PAT/OAT,官方表示會陸續支援其他 CI 供應商。對已經在用 PAT 串接大量 workflow 的組織來說,這意味著遷移可以一個 repository、一個 workflow 逐步進行,不必一次性同步替換所有既有的 CI 憑證設定。
原始來源:Docker OIDC connections for GitHub Actions available for Docker Orgs、Docker Docs: OIDC connections