连云港网站备案在哪,网站策划的工作职责,建设工程合同包括哪些,最有效的宣传方式AddToScheme 函数
AddToScheme 就是为了对外暴露#xff0c;方便别人调用#xff0c;将当前Group组的信息注册到其 Scheme 中#xff0c;以便了解该 Group 组的数据结构#xff0c;用于后续处理
项目版本用途使用场景k8s.io/apiV1注册资源某一外部版本数据结构#xff0…AddToScheme 函数
AddToScheme 就是为了对外暴露方便别人调用将当前Group组的信息注册到其 Scheme 中以便了解该 Group 组的数据结构用于后续处理
项目版本用途使用场景k8s.io/apiV1注册资源某一外部版本数据结构只包含v1 版本的基础资源数据结构不包含版本转换函数适用于指定v1版本编写控制器k8s.io/kubernetesV1注册默认值填充函数和内外版本转换函数默认值填充函数v1和internal的转换函数 zz_generated.conversion.go不适用于单独编写控制器k8s.io/kubernetesinternal注册资源内部版本数据结构所有版本的中转者记录的资源数据结构相比于单一版本更丰富不包含版本转换函数适用于核心组件控制器可以适配多版本
api 项目中 v1 版本的 AddToScheme 函数
register.go 中的 AddToScheme 是专门设计为供外部调用的接口用于将当前 API 组的所有资源类型和相关逻辑如默认值和转换函数注册到全局 Scheme 中。它通过封装复杂的注册逻辑提供了一个统一、简单且易于使用的接口大大降低了集成的复杂性。 详细了解见下面附录
// mod/k8s.io/apiv0.29.0/apps/v1/register.go
package v1import (metav1 k8s.io/apimachinery/pkg/apis/meta/v1k8s.io/apimachinery/pkg/runtimek8s.io/apimachinery/pkg/runtime/schema
)// GroupName is the group name use in this package
const GroupName apps// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion schema.GroupVersion{Group: GroupName, Version: v1}// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {return SchemeGroupVersion.WithResource(resource).GroupResource()
}var (// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.SchemeBuilder runtime.NewSchemeBuilder(addKnownTypes)localSchemeBuilder SchemeBuilder// 就是此函数之后编写别的控制器需要此资源时可以用过调用该 package-name.AddToScheme 就能了解到该 apps/v1 组的所有资源和对应的数据结构用于逻辑处理AddToScheme localSchemeBuilder.AddToScheme
)// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {scheme.AddKnownTypes(SchemeGroupVersion,Deployment{},DeploymentList{},StatefulSet{},StatefulSetList{},DaemonSet{},DaemonSetList{},ReplicaSet{},ReplicaSetList{},ControllerRevision{},ControllerRevisionList{},)metav1.AddToGroupVersion(scheme, SchemeGroupVersion)return nil
}Kubernetes 项目中的 v1 版本的 AddToScheme 函数
// 路径 mod/k8s.io/kubernetesv1.29.0/pkg/apis/apps/v1/register.go
package v1import (appsv1 k8s.io/api/apps/v1k8s.io/apimachinery/pkg/runtime/schema
)// GroupName is the group name use in this package
const GroupName apps// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion schema.GroupVersion{Group: GroupName, Version: v1}// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {return SchemeGroupVersion.WithResource(resource).GroupResource()
}var (localSchemeBuilder appsv1.SchemeBuilderAddToScheme localSchemeBuilder.AddToScheme
)func init() {// We only register manually written functions here. The registration of the// generated functions takes place in the generated files. The separation// makes the code compile even when the generated files are missing.localSchemeBuilder.Register(addDefaultingFuncs)
}相比于 api 项目同级目录还存在个 zz_generated.conversion.go 函数
// 路径 mod/k8s.io/kubernetesv1.29.0/pkg/apis/apps/v1/zz_generated.conversion.go
func init() {localSchemeBuilder.Register(RegisterConversions)
}// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {if err : s.AddGeneratedConversionFunc((*v1.ControllerRevision)(nil), (*apps.ControllerRevision)(nil), func(a, b interface{}, scope conversion.Scope) error {return Convert_v1_ControllerRevision_To_apps_ControllerRevision(a.(*v1.ControllerRevision), b.(*apps.ControllerRevision), scope)}); err ! nil {return err}if err : s.AddGeneratedConversionFunc((*apps.ControllerRevision)(nil), (*v1.ControllerRevision)(nil), func(a, b interface{}, scope conversion.Scope) error {return Convert_apps_ControllerRevision_To_v1_ControllerRevision(a.(*apps.ControllerRevision), b.(*v1.ControllerRevision), scope)}); err ! nil {return err}// ... 省略若干 v1版本和内部版本的转换函数
}内部版本的 AddToScheme 函数
// 路径 mod/k8s.io/kubernetesv1.29.0/pkg/apis/apps/register.go
package appsimport (k8s.io/apimachinery/pkg/runtimek8s.io/apimachinery/pkg/runtime/schemak8s.io/kubernetes/pkg/apis/autoscaling
)var (// SchemeBuilder stores functions to add things to a scheme.SchemeBuilder runtime.NewSchemeBuilder(addKnownTypes)// AddToScheme applies all stored functions t oa scheme.AddToScheme SchemeBuilder.AddToScheme
)// GroupName is the group name use in this package
const GroupName apps// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {return SchemeGroupVersion.WithKind(kind).GroupKind()
}// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {return SchemeGroupVersion.WithResource(resource).GroupResource()
}// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {// TODO this will get cleaned up with the scheme types are fixedscheme.AddKnownTypes(SchemeGroupVersion,DaemonSet{},DaemonSetList{},Deployment{},DeploymentList{},DeploymentRollback{},autoscaling.Scale{},StatefulSet{},StatefulSetList{},ControllerRevision{},ControllerRevisionList{},ReplicaSet{},ReplicaSetList{},)return nil
}附录1 | 理解 AddToScheme
是的register.go 中的 AddToScheme 是专门供外部调用的接口。它的主要作用是将当前 API 组的所有资源类型、元数据、版本等注册到全局的 runtime.Scheme从而支持这些类型的序列化、反序列化、默认值设置和版本转换等操作。 AddToScheme 的特点
封装性 它封装了资源类型注册的细节调用者只需要知道 AddToScheme 能将特定 API 组的资源类型注册到 Scheme 中而无需了解具体的注册过程。 便于外部调用 通过导出 AddToScheme外部模块可以轻松将该 API 组集成到自己的项目中。 统一注册点 将所有相关类型如 Deployment、StatefulSet集中在一个函数中注册方便维护和使用。 调用场景
在 Kubernetes 源码中
AddToScheme 通常会被 Kubernetes 的核心组件或工具如 kubectl、API server调用用于支持资源的处理
import (example.com/project/pkg/apis/apps/v1k8s.io/apimachinery/pkg/runtime
)func main() {scheme : runtime.NewScheme()v1.AddToScheme(scheme) // 注册 apps/v1 的资源类型
}在 Controller 开发中
在开发 Kubernetes Controller 时必须将自定义资源类型注册到控制器的 Scheme 中
import (appsv1 example.com/project/pkg/apis/apps/v1ctrl sigs.k8s.io/controller-runtime
)func main() {scheme : ctrl.GetScheme()appsv1.AddToScheme(scheme) // 注册 apps/v1 类型到 controller-runtime 的 Scheme
}在测试代码中
测试代码中需要模拟某些资源的序列化或反序列化操作时也需要调用 AddToScheme
import (example.com/project/pkg/apis/apps/v1k8s.io/apimachinery/pkg/runtime
)func TestSomething(t *testing.T) {scheme : runtime.NewScheme()_ v1.AddToScheme(scheme) // 注册类型确保测试环境中可以处理这些资源
}设计目的
抽象和复用 将复杂的注册过程如 AddKnownTypes 和 AddToGroupVersion 的调用封装为一个简单的函数供外部使用。 统一接口 Kubernetes 中不同 API 组都会导出类似的 AddToScheme 函数外部调用者只需要知道这个约定即可注册所需的类型。 灵活性 通过 SchemeBuilder 的机制支持动态添加注册逻辑便于扩展。 总结
register.go 中的 AddToScheme 是专门设计为供外部调用的接口用于将当前 API 组的所有资源类型和相关逻辑如默认值和转换函数注册到全局 Scheme 中。它通过封装复杂的注册逻辑提供了一个统一、简单且易于使用的接口大大降低了集成的复杂性。
附录2 | api 和 kubernetes 项目同版本的 register.go 文件有什么不同
Kubernetes 的 api 项目和 kubernetes 项目中的 register.go 文件不一致主要是因为两者承担的职责不同它们分属不同的模块和依赖层级。以下是原因和区别的详细分析 1. 两者的职责和用途
k8s.io/api
功能 是一个独立的 API 定义项目主要用于定义 Kubernetes 的资源结构和常量。提供资源类型的核心定义如 Deployment、StatefulSet。这些定义是“纯粹的”不包含与 Kubernetes 内部运行时相关的逻辑。 特点 仅包含资源的结构定义和自动生成的代码如 deepcopy、openapi。用于支持外部项目如客户端工具client-go或自定义控制器。
kubernetes
功能 是 Kubernetes 主项目包含所有 Kubernetes 的核心逻辑包括控制器、调度器等。除了使用 k8s.io/api 提供的资源定义外还需要注册这些资源到 runtime.Scheme 中。 特点 包含具体的 Scheme 注册逻辑和运行时依赖。需要将资源绑定到 Kubernetes 的控制器和调度器逻辑。 2. 两者 register.go 的区别
k8s.io/api 中的 register.go
内容 提供 GroupName 和 SchemeGroupVersion 等常量用于定义 API 组和版本。仅导出 SchemeBuilder 和 AddToScheme用于资源类型注册。不包含 runtime.Scheme 的直接引用也不执行实际的资源注册。 目的 定义一个通用的接口允许其他模块或项目将这些资源类型注册到自己的 runtime.Scheme 中。不直接注册到运行时保持模块的轻量级和独立性。
var (SchemeBuilder runtime.NewSchemeBuilder(addKnownTypes)AddToScheme SchemeBuilder.AddToScheme
)kubernetes 中的 register.go
内容 从 k8s.io/api 导入资源类型和 SchemeBuilder。在主项目中结合 Kubernetes 内部逻辑扩展资源注册的功能。增加了 localSchemeBuilder 和其他运行时相关逻辑。 目的 扩展 API 定义并将其绑定到 Kubernetes 主项目的运行时环境。实现默认值填充addDefaultingFuncs、字段标签转换等额外功能。
localSchemeBuilder.Register(addDefaultingFuncs)3. 为什么有分工
模块化设计 Kubernetes 将 k8s.io/api 和 kubernetes 主项目分开是为了实现模块化和解耦。资源定义是基础层而运行时逻辑是上层依赖。 减少依赖复杂度 k8s.io/api 是许多外部项目如 client-go的直接依赖如果包含运行时逻辑会导致循环依赖。通过分离k8s.io/api 只关注定义避免了复杂的依赖链。 适配不同场景 k8s.io/api 可以被外部项目独立使用而不需要整个 Kubernetes 主项目。kubernetes 主项目需要额外的运行时逻辑处理更复杂的功能。 4. 实际工作流
在 k8s.io/api 中
提供了 SchemeBuilder 和 AddToScheme供外部调用。示例
import (appsv1 k8s.io/api/apps/v1k8s.io/apimachinery/pkg/runtime
)var scheme runtime.NewScheme()func main() {appsv1.AddToScheme(scheme) // 注册 API 定义到 Scheme
}在 kubernetes 中
除了注册类型还会添加其他自定义逻辑如默认值和字段标签转换。示例
import (k8s.io/kubernetes/pkg/apis/apps/v1
)func main() {v1.AddToScheme(scheme) // 注册到 Kubernetes 主项目的 Scheme
}5. 总结
特性k8s.io/apikubernetes主要职责定义 API 类型和常量运行时绑定和扩展逻辑是否包含运行时逻辑否是导出内容SchemeBuilder、AddToSchemeAddToScheme、localSchemeBuilder、扩展功能是否直接注册 Scheme否是使用场景提供轻量级定义供外部依赖Kubernetes 主项目内部使用
两者的设计目标不同k8s.io/api 是独立的资源定义库而 kubernetes 则是完整的实现与运行时逻辑结合。
附录3 | 以 apps 组说明同版本两个 register.go 的 AddToScheme 调用关系
以 apps 组为例Kubernetes 的 Scheme 是通过逐层调用 AddToScheme 函数来注册 API 类型的。这两个 AddToScheme 函数分别来自
k8s.io/api/apps/v1定义 API 类型如 Deployment, StatefulSet 等并提供注册方法。kubernetes/pkg/apis/apps/v1扩展 API 定义并添加运行时相关功能如默认值填充、字段标签转换等。
以下是详细的调用流程和逻辑分析 1. 两个 AddToScheme 的来源
k8s.io/api/apps/v1
定义 SchemeBuilder 和 AddToScheme注册资源的基本定义到 Scheme 中。核心功能是调用 runtime.Scheme.AddKnownTypes 注册类型。
kubernetes/pkg/apis/apps/v1 主要在 Kubernetes 主项目中使用扩展了 AddToScheme增加了 默认值函数defaulter。字段标签转换field label conversion functions。其他与运行时相关的功能。 2. 调用的层次和流程
在 Kubernetes 主项目中Scheme 的初始化流程会递归调用所有注册函数包括两个 AddToScheme 函数。以下是以 apps 组为例的调用流程
第一步调用 k8s.io/api/apps/v1 的 AddToScheme
Kubernetes 主项目会先调用 k8s.io/api/apps/v1 提供的 AddToScheme
import (appsv1 k8s.io/api/apps/v1
)var scheme runtime.NewScheme()func main() {// 注册 apps 组的资源类型appsv1.AddToScheme(scheme)
}此时的逻辑在 k8s.io/api/apps/v1/register.go 中
var SchemeBuilder runtime.NewSchemeBuilder(addKnownTypes)
var AddToScheme SchemeBuilder.AddToSchemefunc addKnownTypes(scheme *runtime.Scheme) error {scheme.AddKnownTypes(SchemeGroupVersion,Deployment{},DeploymentList{},StatefulSet{},StatefulSetList{},DaemonSet{},DaemonSetList{},ReplicaSet{},ReplicaSetList{},ControllerRevision{},ControllerRevisionList{},)metav1.AddToGroupVersion(scheme, SchemeGroupVersion) // 注册元数据return nil
}注册的内容主要是
资源类型如 Deployment, StatefulSet。元数据通过 metav1.AddToGroupVersion 注册通用的元信息类型。 第二步调用 kubernetes/pkg/apis/apps/v1 的 AddToScheme
在 Kubernetes 主项目中还需要进一步扩展 apps 的资源定义。这时会调用 kubernetes/pkg/apis/apps/v1 中的 AddToScheme
import (appsinternalv1 k8s.io/kubernetes/pkg/apis/apps/v1
)func main() {// 扩展 apps 组的功能appsinternalv1.AddToScheme(scheme)
}此时的逻辑在 kubernetes/pkg/apis/apps/v1/register.go 中
var localSchemeBuilder appsv1.SchemeBuilder // 直接复用 k8s.io/api/apps/v1 的 SchemeBuilder
var AddToScheme localSchemeBuilder.AddToSchemefunc init() {// 注册运行时相关的函数localSchemeBuilder.Register(addDefaultingFuncs)
}这里做了以下扩展
注册默认值函数addDefaultingFuncs。为 apps 资源添加额外的运行时功能。 3. 总结两者如何组合
在 Kubernetes 主项目中Scheme 会分别调用 k8s.io/api/apps/v1 和 kubernetes/pkg/apis/apps/v1 的 AddToScheme实现如下目标 基础类型注册 k8s.io/api/apps/v1 提供的 AddToScheme 确保 apps 组的资源类型被正确注册到 Scheme 中。这是所有调用的基础。 运行时扩展 kubernetes/pkg/apis/apps/v1提供的 AddToScheme在基础类型的注册之上添加运行时功能如 默认值填充Defaulting。字段标签转换Field Label Conversion。
调用顺序如下
首先调用 k8s.io/api/apps/v1 的 AddToScheme。其次调用 kubernetes/pkg/apis/apps/v1 的 AddToScheme 扩展功能。 4. 实际调用示例
完整流程可能如下
import (appsv1 k8s.io/api/apps/v1appsinternalv1 k8s.io/kubernetes/pkg/apis/apps/v1k8s.io/apimachinery/pkg/runtime
)func main() {scheme : runtime.NewScheme()// 注册基础类型if err : appsv1.AddToScheme(scheme); err ! nil {panic(err)}// 扩展运行时功能if err : appsinternalv1.AddToScheme(scheme); err ! nil {panic(err)}// 验证是否注册成功gvk : schema.GroupVersionKind{Group: apps, Version: v1, Kind: Deployment}obj, err : scheme.New(gvk)if err ! nil {panic(err)}fmt.Printf(Registered object: %T\n, obj)
}5. 注册的依赖关系
步骤来源功能appsv1.AddToSchemek8s.io/api/apps/v1注册基础资源类型和元信息appsinternalv1.AddToSchemekubernetes/pkg/apis/apps/v1扩展运行时功能添加默认值、字段转换等
通过这种分层调用Kubernetes 可以灵活地管理 API 类型的定义和运行时行为。
附录4 | 编写控制器时采用 api 项目的 AddToScheme 还是 kubernetes 项目 internal 版本的 AddToScheme
在编写 Kubernetes 控制器时通常需要根据具体的需求选择调用 api 项目中的 AddToScheme 或 kubernetes 项目中的 internal 版本的 AddToScheme。以下是两者的区别和使用场景分析 1. 两种 AddToScheme 的区别
api 项目中的 AddToScheme 来源k8s.io/api例如 k8s.io/api/apps/v1。 内容 提供公开的 API 类型定义。注册外部版本化资源类型如 apps/v1.Deployment。 特点 独立于 Kubernetes 核心实现可被任何第三方控制器、客户端使用。稳定性高版本化清晰。 使用场景 第三方控制器开发时优先使用。通过 Kubernetes API 与集群交互的场景。
kubernetes 项目中的 AddToScheme 来源k8s.io/kubernetes/pkg/apis例如 k8s.io/kubernetes/pkg/apis/apps/v1。 内容 包含内部资源类型internal type。提供额外的运行时功能如默认值设置defaulting、版本转换conversion等。 特点 依赖 Kubernetes 核心实现不能单独使用。包含内部类型internal需要版本转换才能与外部 API 交互。 使用场景 Kubernetes 核心组件如控制器管理器、调度器中使用。需要直接操作内部类型的场景。 2. 控制器开发中如何选择
一般情况使用 k8s.io/api 推荐做法在控制器开发中优先使用 k8s.io/api 中的 AddToScheme因为 提供的是外部版本的资源类型直接与 Kubernetes API 交互。更加通用易于维护适用于所有 Kubernetes 集群。 示例 import (k8s.io/api/apps/v1k8s.io/apimachinery/pkg/runtime
)var scheme runtime.NewScheme()func init() {// 注册外部版本的 apps 组资源if err : v1.AddToScheme(scheme); err ! nil {panic(err)}
}特殊情况使用 kubernetes 项目中的 internal 版本 适用场景 需要内部类型的性能优化如果控制器需要直接操作 Kubernetes 内部类型internal types例如在同一个进程内执行大量的内部操作可以使用 internal 版本。与 Kubernetes 核心组件的深度集成如自定义 ControllerManager在直接调用内部组件时可能需要使用 internal 版本的 AddToScheme。 注意事项 使用 internal 类型时需要手动处理版本转换将其转换为外部类型与 API Server 交互。kubernetes/pkg/apis 依赖于 Kubernetes 主项目控制器无法独立运行。 示例 import (k8s.io/kubernetes/pkg/apis/appsk8s.io/apimachinery/pkg/runtime
)var scheme runtime.NewScheme()func init() {// 注册内部版本的 apps 组资源if err : apps.AddToScheme(scheme); err ! nil {panic(err)}
}3. 推荐做法
优先使用 k8s.io/api 理由 更加通用独立性高不依赖 Kubernetes 源码。版本稳定减少与 Kubernetes 主项目版本变化的耦合。适用于第三方控制器开发和部署。
仅在必要时使用 kubernetes/pkg/apis 理由 使用 internal 版本需要处理更多的兼容性问题版本转换等。仅在需要直接操作 Kubernetes 内部类型或开发 Kubernetes 核心组件时才考虑使用。 4. 典型场景举例
使用 k8s.io/api推荐
开发一个管理 Deployment 的控制器直接与 Kubernetes API Server 交互
import (appsv1 k8s.io/api/apps/v1k8s.io/apimachinery/pkg/runtimek8s.io/client-go/kubernetes/scheme
)func main() {// 初始化 SchemelocalScheme : runtime.NewScheme()appsv1.AddToScheme(localScheme)// 与 API Server 交互// 例如监听 Deployment 资源的变化
}使用 kubernetes/pkg/apis仅在核心组件开发中
扩展 Kubernetes 核心控制器管理器自定义默认值或内部优化
import (appsinternal k8s.io/kubernetes/pkg/apis/appsk8s.io/apimachinery/pkg/runtime
)func main() {// 注册内部版本资源scheme : runtime.NewScheme()appsinternal.AddToScheme(scheme)// 使用内部版本操作internalDeployment : appsinternal.Deployment{}// 操作 internalDeployment 逻辑
}5. 总结
场景使用的 AddToScheme 来源理由第三方控制器开发k8s.io/api独立性高直接操作外部版本资源易于与 API Server 交互。Kubernetes 核心组件扩展kubernetes/pkg/apis内部类型性能更高适合深度定制和运行时扩展功能。操作需要运行时默认值或内部结构的资源kubernetes/pkg/apis需转换外部类型提供默认值填充、版本转换等运行时功能但需要处理额外的兼容性问题。
在实际开发中优先使用外部版本k8s.io/api仅在必要时才使用 internal 类型kubernetes/pkg/apis。