本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

透過更新的 Go 版本保持 Kubernetes 安全

問題

自 v1.19 版本(於 2020 年發布)以來,Kubernetes 專案為每個次要版本提供 12-14 個月的修補程式版本。這讓使用者能夠在年度升級週期中驗證和採用 Kubernetes 版本,並在一年內收到安全性修正。

Go 專案每年發布兩次新的次要版本,並為最後兩個次要版本提供安全性修正,因此每個 Go 版本約有一年的支援期。即使每個新的 Kubernetes 次要版本在首次發布時都是使用受支援的 Go 版本建置的,但該 Go 版本會在 Kubernetes 次要版本之前停止支援,而自 v1.19 以來延長的 Kubernetes 修補程式支援只會擴大這種差距。

在撰寫本文時,所有 Go 修補程式版本中,剛好超過一半 (88/171) 包含可能具有安全性意涵的問題修正。即使其中許多問題與 Kubernetes 無關,但有些問題是相關的,因此使用收到這些修正的受支援 Go 版本仍然很重要。

一個顯而易見的解決方案是直接將 Kubernetes 發行分支更新為新的 Go 次要版本。但是,Kubernetes 避免在修補程式版本中進行破壞穩定的變更,而且從歷史上看,這阻止了將現有的發行分支更新為新的 Go 次要版本,原因是這些變更被認為過於複雜、有風險或會造成中斷,而無法包含在修補程式版本中。範例包括

  • Go 1.6:預設啟用 http/2
  • Go 1.14:EINTR 處理問題
  • Go 1.17:捨棄 x509 CN 支援、ParseIP 變更
  • Go 1.18:預設停用 x509 SHA-1 憑證支援
  • Go 1.19:捨棄 current-dir LookPath 行為

其中一些變更可以在 Kubernetes 程式碼中輕鬆緩解,有些只能透過使用者指定的 GODEBUG 環境變數選擇退出,而其他變更則需要侵入性程式碼變更或根本無法避免。由於這種不一致性,Kubernetes 發行分支通常會停留在單一 Go 次要版本上,並且可能無法在每個 Kubernetes 次要版本的支援生命週期的最後幾個月取得相關的 Go 安全性修正。

當相關的 Go 安全性修正僅在較新的 Kubernetes 次要版本中可用時,使用者將不得不在其 12-14 個月的支援期間結束之前升級離開較舊的 Kubernetes 次要版本,只是為了取得這些修正。如果使用者沒有準備好進行升級,可能會導致 Kubernetes 叢集容易受到攻擊。即使使用者可以適應意外的升級,不確定性也使 Kubernetes 的年度支援對於規劃而言變得不太可靠。

解決方案

我們很高興宣布,截至 2023 年 1 月,受支援的 Kubernetes 版本和受支援的 Go 版本之間的差距已獲得解決。

在過去一年中,我們與 Go 團隊密切合作,以解決採用新 Go 版本的困難。這促成了討論提案在 GopherCon 的演講,以及設計,以改善 Go 中的回溯相容性,確保新的 Go 版本可以為至少兩年(四個 Go 版本)保持與先前 Go 版本相容的執行階段行為。這讓像 Kubernetes 這樣的專案能夠將發行分支更新為受支援的 Go 版本,而不會讓使用者接觸到行為變更。

提議的改進措施有望納入 Go 1.21,而 Go 團隊已在 2022 年底的 Go 1.19 修補程式版本中交付有針對性的相容性改進。這些變更使 Kubernetes 1.23+ 能夠在 2023 年 1 月更新至 Go 1.19,同時避免任何使用者面向的組態或行為變更。所有受支援的 Kubernetes 發行分支現在都使用受支援的 Go 版本,並且可以取得包含可用安全性修正的新 Go 修補程式版本。

展望未來,Kubernetes 維護人員仍然致力於使 Kubernetes 修補程式版本盡可能安全且非破壞性,因此新的 Go 次要版本必須滿足以下幾項要求,現有的 Kubernetes 發行分支才會更新以使用它

  1. 新的 Go 版本必須至少發布 3 個月。這讓 Go 社群有時間採用,並有時間回報問題或回歸。
  2. 新的 Go 版本必須在新 Kubernetes 次要版本中使用至少 1 個月。這可確保所有 Kubernetes 發行封鎖測試都在新的 Go 版本上通過,並讓 Kubernetes 社群有時間針對候選版本和新次要版本的早期採用提供意見反應。
  3. 不得有已知會影響 Kubernetes 的先前 Go 版本的回歸。
  4. 執行階段行為必須預設保留,而無需 Kubernetes 使用者/管理員採取任何動作。
  5. k8s.io/client-go 這樣的 Kubernetes 程式庫必須保持與每個次要版本使用的原始 Go 版本相容,因此消費者不必更新 Go 版本即可取得程式庫修補程式版本(儘管鼓勵他們使用受支援的 Go 版本進行建置,這在 Go 1.21 中計劃的相容性改進中變得更加容易)。

所有這些工作的目標是低調地使 Kubernetes 修補程式版本更安全、更可靠,並使 Kubernetes 次要版本在其整個支援生命週期內安全使用。

非常感謝 Go 團隊,特別是 Russ Cox,感謝他們協助推動這些改進,使其造福所有 Go 使用者,而不僅僅是 Kubernetes。