【k8s深入理解之 Scheme 补充-7】理解无版本资源、有版本资源、元数据信息等联系和区别

发布于:2024-11-29 ⋅ 阅读:(11) ⋅ 点赞:(0)

代码

  • 注意 无版本资源 —— 也是一种资源,可以理解为公共资源,用于记录或查询(如 Status 或 APIGroup 等)
    • 由于 k8s 发展原因,一般放置在 核心组v1 版本种(Group为空,版本为 v1),因此又可以说它”有版本“ —— 但是【很稳定,基本上不更新】,所以称之为【无版本资源】
    • 这些在k8s.io/kubernetes项目中
  • 但是 Metadata、ObjectMeta 等 —— 这些在k8s.io/api项目中
    • 这些不是【独立的API资源】,是资源数据结构体的一部分字段,因此称之为【元数据】,有时候也会被称之为”无版本资源“
// 路径 mod/k8s.io/apimachinery@v0.29.0/pkg/apis/meta/v1/register.go
// AddToGroupVersion registers common meta types into schemas.
func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion) {
	scheme.AddKnownTypeWithName(groupVersion.WithKind(WatchEventKind), &WatchEvent{})
	scheme.AddKnownTypeWithName(
		schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal}.WithKind(WatchEventKind),
		&InternalEvent{},
	)
	// Supports legacy code paths, most callers should use metav1.ParameterCodec for now
	scheme.AddKnownTypes(groupVersion, optionsTypes...)
	// Register Unversioned types under their own special group
	scheme.AddUnversionedTypes(Unversioned,
		&Status{},
		&APIVersions{},
		&APIGroupList{},
		&APIGroup{},
		&APIResourceList{},
	)

	// register manually. This usually goes through the SchemeBuilder, which we cannot use here.
	utilruntime.Must(RegisterConversions(scheme))
	utilruntime.Must(RegisterDefaults(scheme))
}

附录1 | 无版本资源(不需要考虑版本转换,为他人提供服务)

在 Kubernetes (K8s) 中,无版本资源(Unversioned Resources)指的是不依赖于版本控制的资源类型。这些资源通常不随 Kubernetes API 版本的变化而变化,或者它们没有与之对应的版本化机制。在 Kubernetes 中,版本通常用于管理和升级资源的不同版本,但是无版本资源在这个版本化体系之外,通常用于一些全局或基础性的信息。

无版本资源的典型例子

无版本资源常常用于以下类型的对象:

  1. Status
    • Status 是用于表示 API 请求的执行结果或状态的对象,它通常不会随版本变化而变化。它用于在处理某些操作(如资源创建、删除)时提供反馈和错误信息。
    • Status 通常是无版本的,因为它并不是一种具有长期持久性的资源,而是一个临时的反馈对象。
  2. APIGroupAPIGroupList
    • 这些对象表示 Kubernetes 中的 API 组及其版本信息,通常用于在 API 服务器启动时向客户端报告哪些 API 组和版本是可用的。
    • 这些对象与 Kubernetes 的版本控制无关,因此也可以被视为无版本资源。
  3. APIResourceList
    • APIResourceList 是一种用于描述 API 资源列表的对象,通常用于支持 Kubernetes 资源的发现。
    • 这种类型也没有特定的版本,因为它只是列出当前可用的资源,而与具体版本无关。

无版本资源的特点

  • 不参与版本转换:这些资源通常不会参与 Kubernetes 内部的版本转换过程。它们在不同的 API 版本之间保持不变,通常用于表示元数据或状态信息。
  • 简单的结构:它们通常具有简单的结构,不包含复杂的业务逻辑,因此无需随着 API 版本的变化进行更新。
  • 通常用于全局性的操作:例如,Kubernetes API 服务器在启动时会返回 APIGroupAPIGroupList 等资源,用来表示整个集群支持的 API 组和资源列表。

如何注册无版本资源

在 Kubernetes 中,无版本资源通常是通过 Scheme 来注册的。通过 AddUnversionedTypes 方法,将这些资源类型添加到 Scheme 中,以便 Kubernetes 能够正确地识别并处理它们。示例如下:

func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion) {
	// Register Unversioned types under their own special group
	scheme.AddUnversionedTypes(Unversioned,
		&Status{},
		&APIVersions{},
		&APIGroupList{},
		&APIGroup{},
		&APIResourceList{},
	)
}

在上面的代码中,StatusAPIVersionsAPIGroupListAPIGroupAPIResourceList 都是无版本资源,它们被注册为无版本资源,不参与版本控制。

无版本资源的应用场景

  • API 资源的发现:当用户或客户端查询 Kubernetes API 服务器时,可能会通过无版本资源(如 APIGroupList)查询集群中的所有支持的 API 组和版本。
  • 状态返回:像 Status 这样的资源用于返回操作的状态,例如在资源创建、删除或更新时返回的成功或错误消息。
  • 兼容性支持:一些资源可能没有版本化机制,因为它们是为了确保系统的兼容性和稳定性,或者它们只是用于基础性操作,不需要随 Kubernetes 的版本变化而变化。

总结

无版本资源在 Kubernetes 中主要用于描述全局性的信息和状态,它们不参与版本控制,也不进行版本转换。常见的无版本资源包括 StatusAPIGroupListAPIResourceList 等。这些资源通常用于提供 API 资源的发现、反馈信息或元数据,而不是用于代表长期存在的 API 对象。

附录2 | ObjectMetaTypeMeta 是结构体字段,不是独立资源

ObjectMetaTypeMeta 被认为是 Kubernetes 中的“无版本资源”,因为它们不代表单独的 API 资源,而是作为其他版本化资源的元数据结构存在。尽管它们在资源定义中扮演着重要角色,但它们的设计方式与实际的 API 资源类型(如 PodDeployment 等)有所不同,因此不需要单独注册到 Kubernetes 的 Scheme 中。

以下是详细的原因和解释:


1. ObjectMetaTypeMeta 是结构体字段,而不是独立资源

  • TypeMetaObjectMeta并不是 Kubernetes 中的独立 API 资源类型,而是大多数 Kubernetes 资源的元数据字段。
    • TypeMeta 包含字段如 apiVersionkind,用于标识资源类型。
    • ObjectMeta 包含字段如 namenamespacelabelsannotations,用于描述资源的标识信息。

它们只是 Kubernetes API 资源中的一部分,其他资源类型(如 PodDeploymentService 等)会引用它们。因此,ObjectMetaTypeMeta 没有独立的 API 版本,也不需要单独注册到 Scheme 中。


2. 版本化和 Scheme 注册

在 Kubernetes 中,资源类型(例如 PodDeploymentService)是需要注册到 Scheme 中的,这样 API server 和客户端才能处理这些资源的序列化和反序列化。注册过程确保了 API 资源的字段能够正确地被编码和解码,支持 API 的版本管理。

TypeMetaObjectMeta 的注册
  • TypeMetaObjectMeta 是内嵌结构体,它们作为其他资源的字段存在。当你定义一个资源类型时,比如 PodDeployment,你会在其定义中嵌入 ObjectMetaTypeMeta

    type Pod struct {
        metav1.TypeMeta   `json:",inline"`
        metav1.ObjectMeta `json:"metadata,omitempty"`
        // Pod 其他字段...
    }
    
    • TypeMetaObjectMeta 是通过内嵌结构体的方式包含在这些资源中的,因此它们不需要单独注册到 Scheme
    • 当你注册某个资源类型(如 Pod)时,ObjectMetaTypeMeta 已经被隐式注册了,因为它们是资源定义的一部分。
单独注册和 Scheme
  • 实际注册到 Scheme 中的是 API 资源类型(如 PodDeploymentReplicaSet,这些资源是具有版本的。
  • 例如,你注册一个 API 组和版本 (v1.Pod),而不是单独为 ObjectMetaTypeMeta 注册。

3. 设计理念

  • TypeMetaObjectMeta 是基础字段,设计上目的是给其他资源提供元数据支持。它们不是独立的功能模块或 API 资源类型。
  • Kubernetes 的 Scheme 主要处理的是 API 资源类型,这些类型包含版本和可能的自定义行为(如 PodServiceDeployment 等),而不是像 TypeMetaObjectMeta 这样的辅助字段。

4. 内嵌结构体的自动注册

  • 内嵌结构体自动注册:在 Go 语言中,TypeMetaObjectMeta 作为内嵌结构体,自动成为包含它们的资源的一部分。因此,在 Kubernetes 中,注册 Pod 等资源类型时,它们的 ObjectMetaTypeMeta 已经在 Scheme 中注册了,无需额外处理。
  • 只要你注册了 Pod 类型,Kubernetes 就知道如何处理 ObjectMetaTypeMeta,因为它们在 Pod 中作为字段存在,注册过程是递归的。

5. 示例

考虑以下 Pod 的定义:

type Pod struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`
    Spec              PodSpec   `json:"spec,omitempty"`
    Status            PodStatus `json:"status,omitempty"`
}
  • TypeMetaObjectMeta 作为内嵌字段出现在 Pod 结构体中。
  • 当你注册 Pod 类型时,TypeMetaObjectMeta 会自动被注册,并且能够正确序列化/反序列化。
  • 因为它们只是字段,不需要单独注册

6. 总结

  • ObjectMetaTypeMeta 是 Kubernetes API 资源的元数据部分,不是独立的 API 资源类型,因此它们不需要单独注册到 Scheme 中。
  • 它们通过内嵌的方式包含在其他资源类型(如 PodDeployment)中,注册时自动处理。
  • Scheme 注册主要是针对具有版本和独立生命周期的资源类型,而 TypeMetaObjectMeta 是这些资源类型的一部分。

附录3 | 无版本资源和有版本资源的区别

感谢你的补充!你提到的资源(StatusAPIVersionsAPIGroupList 等)确实属于无版本资源,它们在 Kubernetes API 中是基础性、通用的部分,不与具体的 API 组或版本绑定。下面重新总结无版本资源和有版本资源的区别。


1. 无版本资源

定义
  • 无版本资源(Unversioned Resources)是 Kubernetes API 中通用且稳定的资源或结构,它们不绑定具体的版本和 API 组,通常提供元数据支持或通用功能。
特点
  1. 通用性
    • 通常为所有 API 版本通用,不属于任何特定 API 组或版本。
    • 用于支持元数据描述(如 ObjectMeta)或通用功能(如 StatusAPIGroupList)。
  2. 稳定性
    • 设计上追求长期稳定,变更较少。
    • 仅在必要时(如新功能或修复设计缺陷)才会修改。
  3. 注册到 Scheme 的需求
    • 是否注册到 Scheme 取决于是否需要被序列化/反序列化为独立的资源。
    • ObjectMetaTypeMeta 这样的结构体是嵌套字段,不需要注册。
    • StatusAPIGroupList 这样的资源是直接暴露给用户的,需要注册到 Scheme 中,以便序列化/反序列化。
  4. 用途
    • 作为 API 的通用组件(ObjectMetaTypeMeta)。
    • 作为操作结果或元信息的独立资源(StatusAPIVersionsAPIGroupList)。
例子
  • ObjectMeta:提供资源的元信息,例如 namenamespace
  • TypeMeta:标识资源的 kindapiVersion
  • Status:用于描述 API 操作的结果。
  • APIGroupListAPIGroup:列出可用的 API 组和版本。
  • APIVersions:列出支持的 API 版本。

2. 有版本资源

定义
  • 有版本资源(Versioned Resources)是 Kubernetes 中版本化的资源类型,用户可以通过 API 操作这些资源。
  • 它们绑定特定的 API 组(如 appscore)和版本(如 v1v1beta1)。
特点
  1. 版本化支持

    • 资源类型随着 API 的演进可能有多个版本,例如 v1v1beta1
    • 版本化使得新功能可以逐步引入,同时保持向后兼容。
  2. 直接暴露给用户

    • 用户通过指定 apiVersionkind 来操作这些资源。

    • 例如:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: my-deployment
      
  3. 注册到 Scheme 的需求

    • 所有有版本资源都需要注册到 Scheme 中,以支持序列化/反序列化以及版本转换。
  4. 用途

    • 直接描述 Kubernetes 中的核心概念或应用场景,例如 PodServiceDeployment
例子
  • Podcore/v1):表示容器的基本运行单元。
  • Deploymentapps/v1):表示应用的部署策略。
  • Servicecore/v1):提供网络访问的抽象。

3. 无版本资源和有版本资源的核心区别

特性 无版本资源 有版本资源
是否版本化 不绑定具体版本 绑定特定版本(如 v1v1beta1
API 组绑定 不绑定具体 API 组 绑定具体的 API 组(如 appsbatch
是否暴露给用户 部分暴露(如 Status),部分为辅助字段 直接暴露,用户通过 kubectl 和 API 使用
注册到 Scheme 的需求 辅助字段不需要,独立资源需要注册 需要注册到 Scheme 中
变化频率 稳定,设计上尽量减少变更 随 API 演进可能频繁更新
用途 提供元数据支持或通用功能 描述 Kubernetes 中的核心资源和概念
例子 ObjectMetaTypeMetaStatus PodServiceDeployment

4. 总结

无版本资源
  • 用于提供通用功能或元信息支持,设计上追求长期稳定,不绑定具体版本和 API 组。
  • 是否注册到 Scheme 取决于是否作为独立资源暴露(例如 Status 需要,ObjectMeta 不需要)。
有版本资源
  • 直接暴露给用户,随着 Kubernetes 功能演进不断更新,绑定特定的 API 组和版本。
  • 必须注册到 Scheme 中以支持序列化、反序列化和版本转换。

两者的关键区别在于用途和设计目标:无版本资源注重通用性和稳定性,而有版本资源注重功能和版本演进的灵活性。

附录4 | 无版本资源不需要绑定版本,为什么注册 Scheme 还要指定 v1 版本

  • 简言之,无版本 —— 指的是没有版本迭代 —— 稳定

  • 那为什么注册 Scheme 时,绑定到 核心组v1版本

  • 因为业务逻辑处理时,总得需要找到该无版本资源对应的 go Struct 结构体,也就是该 go Struct 结构体需要有个存储位置

  • 最初 k8s 设计时,就将此部分代码放置在 核心组v1版本

  • 因此业务逻辑处理时,为了便于找到该无版本资源对应的 go Struct 结构体,就需要这样的 GVK(核心组v1版本) 和 go Struct 的映射

// 路径 k8s.io/apimachinery/pkg/apis/meta/v1/register.go
// Unversioned is group version for unversioned API objects
// TODO: this should be v1 probably
var Unversioned = schema.GroupVersion{Group: "", Version: "v1"}

// AddToGroupVersion registers common meta types into schemas.
func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion) {
	// ...
  
	// Register Unversioned types under their own special group
	scheme.AddUnversionedTypes(Unversioned,
		&Status{},
		&APIVersions{},
		&APIGroupList{},
		&APIGroup{},
		&APIResourceList{},
	)
  
	// ...
}

你提到的 Unversioned 注册确实看起来绑定了一个版本 v1,但它的语义和有版本资源的版本化机制不一样。关键在于理解 无版本资源中 “绑定版本” 的不同语义 以及 Kubernetes 对其的特殊处理。


1. 无版本资源的 “绑定版本” 语义

在 Kubernetes 中,虽然无版本资源在 Scheme 中注册时指定了一个 GroupVersion(如 {Group: "", Version: "v1"}),但它与有版本资源的版本化机制有本质区别:

  1. 特殊的 API 组和版本:
    • 无版本资源的 Group 是空字符串 "",这表示它们属于 Kubernetes 核心 API,而不是某个特定的 API 组(如 appsbatch)。
    • Version 通常是 v1,表示它们是稳定的基础类型,而不是 API 的演进版本。
  2. 不参与版本迁移或转换:
    • 有版本资源可能有多个版本(如 v1alpha1v1beta1v1),需要提供版本转换逻辑。
    • 无版本资源仅使用一个固定版本,不需要版本迁移或转换。
  3. 设计意图:
    • 这些资源是通用的,设计上不属于任何具体的功能模块,因此不需要 API 组或版本的分离管理。

2. 为什么无版本资源绑定了 GroupVersion

无版本资源需要 GroupVersion 的原因主要是为了在 API 中有一个统一的资源标识,同时支持序列化和反序列化。这是 Kubernetes 内部机制的一部分,但它的意义与有版本资源不同。

原因和目的:
  1. 支持通用接口:
    • Kubernetes 的所有资源(无论是有版本还是无版本)都需要在 API 中有一个唯一标识。
    • GroupVersionKind(GVK)是这个标识的基础结构,因此即使是无版本资源,也需要一个 GroupVersion
  2. 统一处理机制:
    • Scheme 需要对所有资源进行注册以支持序列化/反序列化。
    • 无版本资源也需要通过 GroupVersion 注册到 Scheme 中,以便 API server 和客户端可以正常处理它们。
  3. 表明稳定性:
    • 无版本资源通常标记为 v1,这是 Kubernetes 对稳定性的一种声明。
    • 它不意味着该资源会经历版本迭代,而是说明它是稳定的、基础的资源。

3. 对比无版本资源与有版本资源的 GroupVersion

特性 无版本资源 有版本资源
Group 空字符串 ""(核心组,无特定功能模块) appsbatchnetworking.k8s.io
Version 固定为 v1,表示稳定版本,不会迭代 可有多个版本,如 v1beta1v1
是否需要版本转换 不需要 需要支持版本迁移和兼容逻辑
用途 通用基础资源(如 Status 特定功能资源(如 PodDeployment

4. 无版本资源绑定版本的影响

无版本资源绑定了 GroupVersion(如 {Group: "", Version: "v1"}),但它的版本定义更像是一个标记,而不是对资源版本化的承诺。这种绑定有以下影响:

  1. API 标识性:
    • 即使无版本资源不属于某个具体的 API 组或版本,也需要通过 GroupVersion 提供统一的标识和处理方式。
  2. 稳定性承诺:
    • 使用 v1 是 Kubernetes 对无版本资源稳定性的声明。通常无版本资源不会经历版本升级,但如果未来有重大设计变更(极少数情况),也可能引入新版本。
  3. 与有版本资源的区别:
    • 无版本资源不属于某个 API 组,也不需要支持版本迁移或演进,因此不参与版本管理逻辑。

5. 总结:无版本资源与有版本资源的区别

维度 无版本资源 有版本资源
API 组绑定 Group 为 "",属于核心 API,无具体模块 绑定到特定 API 组(如 appsbatch
版本绑定 固定 v1,仅用于标识,设计上不需要迭代 支持多版本(如 v1beta1v1),有版本迁移
用途 提供通用功能或基础支持,如 Status 描述 Kubernetes 的核心功能资源
注册到 Scheme 需要注册,但注册逻辑简单 必须注册,并且支持版本转换
版本迁移支持 不需要 需要支持版本迁移和演进逻辑
设计目标 通用性、长期稳定 灵活性、功能迭代

所以,无版本资源的 GroupVersion 注册是为了符合 Kubernetes 的统一处理机制,但它的语义是固定的,不会参与版本化迭代。而有版本资源则设计为支持功能扩展和版本管理,这是两者的根本区别。

附录5 | 无版本资源存放位置

你提到的 &Status{}, &APIVersions{}, &APIGroupList{}, &APIGroup{}, 和 &APIResourceList{} 等无状态资源通常属于 Kubernetes API 中的基础组件,这些资源是 无状态的(stateless),用于描述 Kubernetes 集群和 API 版本、组、资源等信息。它们通常并不直接存储在某个具体的项目中,而是由 Kubernetes API Server 提供并管理。

这些无状态资源存储和管理的位置

这些资源类型通常是定义在 Kubernetes 项目的 k8s.io/kubernetes 源代码库中的一些基础组件中,特别是在 API 定义部分。这些类型和结构体是在 Kubernetes 的 API 组 中定义和注册的。

它们属于 Kubernetes API Server 的一部分,API Server 通过这些资源提供对集群的元数据(如 API 版本、资源列表、组信息等)的查询接口。

主要存储位置

  1. k8s.io/kubernetes 项目:
    • 所有的无状态资源(如 Status, APIVersions, APIGroupList, APIGroup, APIResourceList 等)定义在 Kubernetes 的核心代码库中,特别是与 API 组相关的部分。
    • 它们通常位于以下目录中:
      • staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/ — 这里包含了许多 Kubernetes API 相关的结构体和接口定义。
      • staging/src/k8s.io/api/core/v1/ — 包含 Kubernetes 核心资源定义(如 Pod、Service、Deployment 等)以及元数据部分。
      • staging/src/k8s.io/kubernetes/pkg/apis/... — 这里包含了其他 API 组的定义。
  2. k8s.io/apimachinery 包:
    • 一些基础 API 结构体(例如 Status)和元数据类型(如 TypeMetaObjectMeta)都在 k8s.io/apimachinery 库中定义。这些类型在多个 API 组之间共享,属于 Kubernetes 核心的通用定义。
  3. k8s.io/kubernetes/pkg/apis
    • 这里定义了 Kubernetes 的所有资源类型,包括用于 API 组、版本管理的资源。例如,APIGroupList, APIGroup, APIVersions 这些结构体会在该部分进行定义和使用。

具体代码示例

例如,APIVersionsAPIGroupList 这些类型通常是从 Kubernetes 的 API 服务器组件中获取的,它们的定义如下:

APIVersions 定义:

位于 k8s.io/apimachinery/pkg/apis/meta/v1/types.go 中:

// APIVersions represents a list of supported API versions.
type APIVersions struct {
    metav1.TypeMeta `json:",inline"`
    Versions        []string `json:"versions"`
}
APIGroupListAPIGroup 定义:

位于 k8s.io/kubernetes/pkg/apis/core/v1/types.go 中:

// APIGroup represents a single API group in the Kubernetes API server.
type APIGroup struct {
    Name              string            `json:"name"`
    Versions         []APIGroupVersion `json:"versions"`
    Kind              string            `json:"kind"`
    PreferredVersion APIGroupVersion   `json:"preferredVersion"`
}

// APIGroupList represents a list of API groups.
type APIGroupList struct {
    metav1.TypeMeta `json:",inline"`
    Groups          []APIGroup `json:"groups"`
}

无状态资源的用途

这些无状态资源通常用于以下目的:

  1. API 版本和组查询:
    • 通过 APIVersionsAPIGroupList 等资源,用户可以查询 Kubernetes 集群支持的所有 API 版本和 API 组。它们提供集群的元数据,帮助客户端了解哪些资源是可用的。
  2. 集群信息:
    • 通过查询 APIGroup, APIResourceList,用户可以获取集群中某个 API 组的资源类型列表,以及这些资源的详细信息。
  3. 操作状态:
    • Status 类型通常用于表示请求的执行状态,特别是在资源操作(如创建、删除等)完成后,API 会返回 Status 来指示操作结果。

总结

这些无状态资源(如 &Status{}, &APIVersions{}, &APIGroupList{}, &APIGroup{}, &APIResourceList{} 等)并不是存储在某个特定的 “项目” 中,而是定义在 Kubernetes 的源代码库中,作为 Kubernetes API Server 的一部分。它们通常存储和返回集群的元数据、资源列表、版本信息等,主要通过 Kubernetes API Server 提供的端点来访问。