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

使用更新的 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:放棄當前目錄的 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 補丁版本儘可能安全且無干擾,因此,在現有的 Kubernetes 釋出分支更新到新的 Go 小版本之前,該版本必須滿足幾個要求:

  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。