将特性门引入 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
标志控制。
通过设置以 KUBE_FEATURE
为前缀的环境变量,可以启用或禁用 client-go 的特性。例如,要启用名为 MyFeature
的特性,请按如下方式设置环境变量
KUBE_FEATURE_MyFeature=true
要禁用该特性,请将环境变量设置为 false
KUBE_FEATURE_MyFeature=false
注意:环境变量在某些操作系统上区分大小写。因此,KUBE_FEATURE_MyFeature
和 KUBE_FEATURE_MYFEATURE
将被视为两个不同的变量。
定制 client-go 特性门控
默认的基于环境变量的特性门控覆盖机制对于 Kubernetes 生态系统中的许多程序来说已经足够,并且不需要特殊的集成。需要不同行为的程序可以用自己的自定义特性门控提供者来替换它。这允许程序执行诸如强制禁用已知运行不佳的特性、直接从远程配置服务读取特性门控或通过命令行选项接受特性门控覆盖等操作。
Kubernetes 组件用一个 shim 来替换 client-go 的默认特性门控提供者,该 shim 连接到现有的 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 API 边界两侧都有一个共同的特性升级机制,Kubernetes 贡献者的工作流程也得到了简化。