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

為 Client-Go 引入特性門控:增強靈活性和控制力

Kubernetes 元件使用名為**特性門控(feature gates)** 的開關來管理新增新功能時所帶來的風險。特性門控機制能夠讓一項功能分階段地從 Alpha、Beta 演進到 GA 階段。

Kubernetes 元件,如 kube-controller-manager 和 kube-scheduler,使用 client-go 庫與 API 互動。同一個庫也被整個 Kubernetes 生態系統用來構建控制器、工具、Webhook 等。client-go 現在包含了它自己的特性門控機制,讓開發者和叢集管理員在如何採用客戶端特性方面擁有更多的控制權。

要了解更多關於 Kubernetes 中特性門控的資訊,請訪問特性門控

動機

在 client-go 沒有特性門控之前,每個新功能都以自己的方式(如果有的話)將功能的可用性與啟用分離開來。有些功能透過更新到更新版本的 client-go 來啟用。其他功能則需要在每個使用它們的程式中進行主動配置。還有少數功能可以在執行時使用環境變數進行配置。當消費由 kube-apiserver 暴露的受特性門控保護的功能時,有時需要一個客戶端回退機制,以保持與由於版本較舊或配置不同而不支援該功能的伺服器的相容性。在這些回退機制中發現問題的情況下,緩解措施需要更新到修復後的 client-go 版本或進行回滾。

這些方法都不能很好地支援在某些(但不是全部)消費 client-go 的程式中預設啟用某個特性。相比於最初只為單個元件啟用一個新特性,更改預設設定會立即影響所有 Kubernetes 元件的預設值,這會顯著擴大影響範圍。

client-go 中的特性門控

為了應對這些挑戰,重要的 client-go 特性將使用新的特性門控機制分階段引入。這將允許開發者和使用者以一種對於有 Kubernetes 元件特性門控經驗的人來說很熟悉的方式啟用或停用特性。

開箱即用,只需使用最新版本的 client-go,就能帶來以下幾個好處。

對於使用 client-go 構建的軟體的使用者

  • 早期採用者可以基於每個程序啟用預設關閉的 client-go 特性。
  • 出現問題的特性可以在不構建新二進位制檔案的情況下被停用。
  • 所有已知的 client-go 特性門控的狀態都會被記錄下來,允許使用者進行檢查。

對於使用 client-go 開發軟體的開發者

  • 預設情況下,client-go 特性門控的過載是從環境變數中讀取的。如果在 client-go 的某個特性中發現了一個 bug,使用者將能夠在不等待新版本釋出的情況下停用它。
  • 開發者可以在程式中替換預設的基於環境變數的過載機制,以更改預設值、從其他來源讀取過載配置,或者完全停用執行時過載。Kubernetes 元件利用這種可定製性將 client-go 特性門控與現有的 --feature-gates 命令列標誌、特性啟用指標和日誌記錄進行整合。

過載 client-go 特性門控

注意:這裡描述的是在執行時過載 client-go 特性門控的預設方法。特定程式的開發者可以停用或自定義此方法。在 Kubernetes 元件中,client-go 特性門控的過載由 --feature-gates 標誌控制。

client-go 的特性可以透過設定以 KUBE_FEATURE 為字首的環境變數來啟用或停用。例如,要啟用名為 MyFeature 的特性,可以如下設定環境變數

 KUBE_FEATURE_MyFeature=true

要停用該特性,請將環境變數設定為 false

 KUBE_FEATURE_MyFeature=false

注意:在某些作業系統上,環境變數是區分大小寫的。因此,KUBE_FEATURE_MyFeatureKUBE_FEATURE_MYFEATURE 將被視為兩個不同的變數。

自定義 client-go 特性門控

對於 Kubernetes 生態系統中的許多程式來說,預設的基於環境變數的特性門控過載機制可能已經足夠,並且不需要任何特殊的整合。需要不同行為的程式可以用它們自己的自定義特性門控提供程式來替換它。這使得程式可以做到諸如強制停用已知工作不佳的特性、直接從遠端配置服務讀取特性門控,或者透過命令列選項接受特性門控過載等操作。

Kubernetes 元件將 client-go 的預設特性門控提供程式替換為到現有 Kubernetes 特性門控提供程式的墊片。在所有實際應用中,client-go 特性門控與其他的 Kubernetes 特性門控一樣對待:它們被連線到 --feature-gates 命令列標誌,包含在特性啟用指標中,並在啟動時被記錄。

要替換預設的特性門控提供程式,請實現 Gates 介面並在包初始化時呼叫 ReplaceFeatureGates,如下面的簡單示例所示

import (
 k8s.io/client-go/features
)

type AlwaysEnabledGates struct{}

func (AlwaysEnabledGates) Enabled(features.Feature) bool {
 return true
}

func init() {
 features.ReplaceFeatureGates(AlwaysEnabledGates{})
}

需要已定義的 client-go 特性完整列表的實現可以透過實現 Registry 介面並呼叫 AddFeaturesToExistingFeatureGates 來獲取。有關完整的示例,請參閱在 Kubernetes 中的用法

總結

隨著 client-go v1.30 中特性門控的引入,推出新的 client-go 特性變得更加安全和容易。使用者和開發者可以控制自己採用 client-go 特性的節奏。Kubernetes 貢獻者的工作也因為有了一個通用的機制來演進跨越 Kubernetes API 邊界兩側的特性而得到了簡化。

特別感謝 @sttts@deads2k 在塑造此特性方面的幫助。