本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
为 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_MyFeature
和 KUBE_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 边界两侧的特性而得到了简化。