【k8s深入理解之 Scheme 补充-7】理解无版本资源、有版本资源、元数据信息等联系和区别
代码
- 注意 无版本资源 —— 也是一种资源,可以理解为公共资源,用于记录或查询(如 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 中,版本通常用于管理和升级资源的不同版本,但是无版本资源在这个版本化体系之外,通常用于一些全局或基础性的信息。
无版本资源的典型例子
无版本资源常常用于以下类型的对象:
Status
:Status
是用于表示 API 请求的执行结果或状态的对象,它通常不会随版本变化而变化。它用于在处理某些操作(如资源创建、删除)时提供反馈和错误信息。Status
通常是无版本的,因为它并不是一种具有长期持久性的资源,而是一个临时的反馈对象。
APIGroup
、APIGroupList
:- 这些对象表示 Kubernetes 中的 API 组及其版本信息,通常用于在 API 服务器启动时向客户端报告哪些 API 组和版本是可用的。
- 这些对象与 Kubernetes 的版本控制无关,因此也可以被视为无版本资源。
APIResourceList
:APIResourceList
是一种用于描述 API 资源列表的对象,通常用于支持 Kubernetes 资源的发现。- 这种类型也没有特定的版本,因为它只是列出当前可用的资源,而与具体版本无关。
无版本资源的特点
- 不参与版本转换:这些资源通常不会参与 Kubernetes 内部的版本转换过程。它们在不同的 API 版本之间保持不变,通常用于表示元数据或状态信息。
- 简单的结构:它们通常具有简单的结构,不包含复杂的业务逻辑,因此无需随着 API 版本的变化进行更新。
- 通常用于全局性的操作:例如,Kubernetes API 服务器在启动时会返回
APIGroup
、APIGroupList
等资源,用来表示整个集群支持的 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{},
)
}
在上面的代码中,Status
、APIVersions
、APIGroupList
、APIGroup
和 APIResourceList
都是无版本资源,它们被注册为无版本资源,不参与版本控制。
无版本资源的应用场景
- API 资源的发现:当用户或客户端查询 Kubernetes API 服务器时,可能会通过无版本资源(如
APIGroupList
)查询集群中的所有支持的 API 组和版本。 - 状态返回:像
Status
这样的资源用于返回操作的状态,例如在资源创建、删除或更新时返回的成功或错误消息。 - 兼容性支持:一些资源可能没有版本化机制,因为它们是为了确保系统的兼容性和稳定性,或者它们只是用于基础性操作,不需要随 Kubernetes 的版本变化而变化。
总结
无版本资源在 Kubernetes 中主要用于描述全局性的信息和状态,它们不参与版本控制,也不进行版本转换。常见的无版本资源包括 Status
、APIGroupList
和 APIResourceList
等。这些资源通常用于提供 API 资源的发现、反馈信息或元数据,而不是用于代表长期存在的 API 对象。
附录2 | ObjectMeta
和 TypeMeta
是结构体字段,不是独立资源
ObjectMeta
和 TypeMeta
被认为是 Kubernetes 中的“无版本资源”,因为它们不代表单独的 API 资源,而是作为其他版本化资源的元数据结构存在。尽管它们在资源定义中扮演着重要角色,但它们的设计方式与实际的 API 资源类型(如 Pod
、Deployment
等)有所不同,因此不需要单独注册到 Kubernetes 的 Scheme
中。
以下是详细的原因和解释:
1. ObjectMeta
和 TypeMeta
是结构体字段,而不是独立资源
TypeMeta
和ObjectMeta
并不是 Kubernetes 中的独立 API 资源类型,而是大多数 Kubernetes 资源的元数据字段。TypeMeta
包含字段如apiVersion
和kind
,用于标识资源类型。ObjectMeta
包含字段如name
、namespace
、labels
、annotations
,用于描述资源的标识信息。
它们只是 Kubernetes API 资源中的一部分,其他资源类型(如 Pod
、Deployment
、Service
等)会引用它们。因此,ObjectMeta
和 TypeMeta
没有独立的 API 版本,也不需要单独注册到 Scheme
中。
2. 版本化和 Scheme
注册
在 Kubernetes 中,资源类型(例如 Pod
、Deployment
、Service
)是需要注册到 Scheme
中的,这样 API server 和客户端才能处理这些资源的序列化和反序列化。注册过程确保了 API 资源的字段能够正确地被编码和解码,支持 API 的版本管理。
TypeMeta
和 ObjectMeta
的注册
-
TypeMeta
和ObjectMeta
是内嵌结构体,它们作为其他资源的字段存在。当你定义一个资源类型时,比如Pod
或Deployment
,你会在其定义中嵌入ObjectMeta
和TypeMeta
:type Pod struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // Pod 其他字段... }
TypeMeta
和ObjectMeta
是通过内嵌结构体的方式包含在这些资源中的,因此它们不需要单独注册到Scheme
。- 当你注册某个资源类型(如
Pod
)时,ObjectMeta
和TypeMeta
已经被隐式注册了,因为它们是资源定义的一部分。
单独注册和 Scheme
- 实际注册到
Scheme
中的是 API 资源类型(如Pod
、Deployment
、ReplicaSet
),这些资源是具有版本的。 - 例如,你注册一个 API 组和版本 (
v1.Pod
),而不是单独为ObjectMeta
或TypeMeta
注册。
3. 设计理念
TypeMeta
和ObjectMeta
是基础字段,设计上目的是给其他资源提供元数据支持。它们不是独立的功能模块或 API 资源类型。- Kubernetes 的 Scheme 主要处理的是 API 资源类型,这些类型包含版本和可能的自定义行为(如
Pod
、Service
、Deployment
等),而不是像TypeMeta
和ObjectMeta
这样的辅助字段。
4. 内嵌结构体的自动注册
- 内嵌结构体自动注册:在 Go 语言中,
TypeMeta
和ObjectMeta
作为内嵌结构体,自动成为包含它们的资源的一部分。因此,在 Kubernetes 中,注册Pod
等资源类型时,它们的ObjectMeta
和TypeMeta
已经在 Scheme 中注册了,无需额外处理。 - 只要你注册了
Pod
类型,Kubernetes 就知道如何处理ObjectMeta
和TypeMeta
,因为它们在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"`
}
TypeMeta
和ObjectMeta
作为内嵌字段出现在Pod
结构体中。- 当你注册
Pod
类型时,TypeMeta
和ObjectMeta
会自动被注册,并且能够正确序列化/反序列化。 - 因为它们只是字段,不需要单独注册。
6. 总结
ObjectMeta
和TypeMeta
是 Kubernetes API 资源的元数据部分,不是独立的 API 资源类型,因此它们不需要单独注册到Scheme
中。- 它们通过内嵌的方式包含在其他资源类型(如
Pod
、Deployment
)中,注册时自动处理。 Scheme
注册主要是针对具有版本和独立生命周期的资源类型,而TypeMeta
和ObjectMeta
是这些资源类型的一部分。
附录3 | 无版本资源和有版本资源的区别
感谢你的补充!你提到的资源(Status
、APIVersions
、APIGroupList
等)确实属于无版本资源,它们在 Kubernetes API 中是基础性、通用的部分,不与具体的 API 组或版本绑定。下面重新总结无版本资源和有版本资源的区别。
1. 无版本资源
定义
- 无版本资源(Unversioned Resources)是 Kubernetes API 中通用且稳定的资源或结构,它们不绑定具体的版本和 API 组,通常提供元数据支持或通用功能。
特点
- 通用性:
- 通常为所有 API 版本通用,不属于任何特定 API 组或版本。
- 用于支持元数据描述(如
ObjectMeta
)或通用功能(如Status
、APIGroupList
)。
- 稳定性:
- 设计上追求长期稳定,变更较少。
- 仅在必要时(如新功能或修复设计缺陷)才会修改。
- 注册到 Scheme 的需求:
- 是否注册到 Scheme 取决于是否需要被序列化/反序列化为独立的资源。
- 像
ObjectMeta
和TypeMeta
这样的结构体是嵌套字段,不需要注册。 - 像
Status
和APIGroupList
这样的资源是直接暴露给用户的,需要注册到 Scheme 中,以便序列化/反序列化。
- 用途:
- 作为 API 的通用组件(
ObjectMeta
、TypeMeta
)。 - 作为操作结果或元信息的独立资源(
Status
、APIVersions
、APIGroupList
)。
- 作为 API 的通用组件(
例子
ObjectMeta
:提供资源的元信息,例如name
、namespace
。TypeMeta
:标识资源的kind
和apiVersion
。Status
:用于描述 API 操作的结果。APIGroupList
和APIGroup
:列出可用的 API 组和版本。APIVersions
:列出支持的 API 版本。
2. 有版本资源
定义
- 有版本资源(Versioned Resources)是 Kubernetes 中版本化的资源类型,用户可以通过 API 操作这些资源。
- 它们绑定特定的 API 组(如
apps
、core
)和版本(如v1
、v1beta1
)。
特点
-
版本化支持:
- 资源类型随着 API 的演进可能有多个版本,例如
v1
、v1beta1
。 - 版本化使得新功能可以逐步引入,同时保持向后兼容。
- 资源类型随着 API 的演进可能有多个版本,例如
-
直接暴露给用户:
-
用户通过指定
apiVersion
和kind
来操作这些资源。 -
例如:
apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment
-
-
注册到 Scheme 的需求:
- 所有有版本资源都需要注册到 Scheme 中,以支持序列化/反序列化以及版本转换。
-
用途:
- 直接描述 Kubernetes 中的核心概念或应用场景,例如
Pod
、Service
、Deployment
。
- 直接描述 Kubernetes 中的核心概念或应用场景,例如
例子
Pod
(core/v1
):表示容器的基本运行单元。Deployment
(apps/v1
):表示应用的部署策略。Service
(core/v1
):提供网络访问的抽象。
3. 无版本资源和有版本资源的核心区别
特性 | 无版本资源 | 有版本资源 |
---|---|---|
是否版本化 | 不绑定具体版本 | 绑定特定版本(如 v1 、v1beta1 ) |
API 组绑定 | 不绑定具体 API 组 | 绑定具体的 API 组(如 apps 、batch ) |
是否暴露给用户 | 部分暴露(如 Status ),部分为辅助字段 | 直接暴露,用户通过 kubectl 和 API 使用 |
注册到 Scheme 的需求 | 辅助字段不需要,独立资源需要注册 | 需要注册到 Scheme 中 |
变化频率 | 稳定,设计上尽量减少变更 | 随 API 演进可能频繁更新 |
用途 | 提供元数据支持或通用功能 | 描述 Kubernetes 中的核心资源和概念 |
例子 | ObjectMeta 、TypeMeta 、Status | Pod 、Service 、Deployment |
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"}
),但它与有版本资源的版本化机制有本质区别:
- 特殊的 API 组和版本:
- 无版本资源的
Group
是空字符串""
,这表示它们属于 Kubernetes 核心 API,而不是某个特定的 API 组(如apps
或batch
)。 Version
通常是v1
,表示它们是稳定的基础类型,而不是 API 的演进版本。
- 无版本资源的
- 不参与版本迁移或转换:
- 有版本资源可能有多个版本(如
v1alpha1
、v1beta1
、v1
),需要提供版本转换逻辑。 - 无版本资源仅使用一个固定版本,不需要版本迁移或转换。
- 有版本资源可能有多个版本(如
- 设计意图:
- 这些资源是通用的,设计上不属于任何具体的功能模块,因此不需要 API 组或版本的分离管理。
2. 为什么无版本资源绑定了 GroupVersion
?
无版本资源需要 GroupVersion
的原因主要是为了在 API 中有一个统一的资源标识,同时支持序列化和反序列化。这是 Kubernetes 内部机制的一部分,但它的意义与有版本资源不同。
原因和目的:
- 支持通用接口:
- Kubernetes 的所有资源(无论是有版本还是无版本)都需要在 API 中有一个唯一标识。
GroupVersionKind
(GVK)是这个标识的基础结构,因此即使是无版本资源,也需要一个GroupVersion
。
- 统一处理机制:
- Scheme 需要对所有资源进行注册以支持序列化/反序列化。
- 无版本资源也需要通过
GroupVersion
注册到 Scheme 中,以便 API server 和客户端可以正常处理它们。
- 表明稳定性:
- 无版本资源通常标记为
v1
,这是 Kubernetes 对稳定性的一种声明。 - 它不意味着该资源会经历版本迭代,而是说明它是稳定的、基础的资源。
- 无版本资源通常标记为
3. 对比无版本资源与有版本资源的 GroupVersion
特性 | 无版本资源 | 有版本资源 |
---|---|---|
Group | 空字符串 "" (核心组,无特定功能模块) | 如 apps 、batch 、networking.k8s.io |
Version | 固定为 v1 ,表示稳定版本,不会迭代 | 可有多个版本,如 v1beta1 、v1 |
是否需要版本转换 | 不需要 | 需要支持版本迁移和兼容逻辑 |
用途 | 通用基础资源(如 Status ) | 特定功能资源(如 Pod 、Deployment ) |
4. 无版本资源绑定版本的影响
无版本资源绑定了 GroupVersion
(如 {Group: "", Version: "v1"}
),但它的版本定义更像是一个标记,而不是对资源版本化的承诺。这种绑定有以下影响:
- API 标识性:
- 即使无版本资源不属于某个具体的 API 组或版本,也需要通过
GroupVersion
提供统一的标识和处理方式。
- 即使无版本资源不属于某个具体的 API 组或版本,也需要通过
- 稳定性承诺:
- 使用
v1
是 Kubernetes 对无版本资源稳定性的声明。通常无版本资源不会经历版本升级,但如果未来有重大设计变更(极少数情况),也可能引入新版本。
- 使用
- 与有版本资源的区别:
- 无版本资源不属于某个 API 组,也不需要支持版本迁移或演进,因此不参与版本管理逻辑。
5. 总结:无版本资源与有版本资源的区别
维度 | 无版本资源 | 有版本资源 |
---|---|---|
API 组绑定 | Group 为 "" ,属于核心 API,无具体模块 | 绑定到特定 API 组(如 apps 、batch ) |
版本绑定 | 固定 v1 ,仅用于标识,设计上不需要迭代 | 支持多版本(如 v1beta1 、v1 ),有版本迁移 |
用途 | 提供通用功能或基础支持,如 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 版本、资源列表、组信息等)的查询接口。
主要存储位置
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 组的定义。
- 所有的无状态资源(如
k8s.io/apimachinery
包:- 一些基础 API 结构体(例如
Status
)和元数据类型(如TypeMeta
和ObjectMeta
)都在k8s.io/apimachinery
库中定义。这些类型在多个 API 组之间共享,属于 Kubernetes 核心的通用定义。
- 一些基础 API 结构体(例如
k8s.io/kubernetes/pkg/apis
:- 这里定义了 Kubernetes 的所有资源类型,包括用于 API 组、版本管理的资源。例如,
APIGroupList
,APIGroup
,APIVersions
这些结构体会在该部分进行定义和使用。
- 这里定义了 Kubernetes 的所有资源类型,包括用于 API 组、版本管理的资源。例如,
具体代码示例
例如,APIVersions
和 APIGroupList
这些类型通常是从 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"`
}
APIGroupList
和 APIGroup
定义:
位于 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"`
}
无状态资源的用途
这些无状态资源通常用于以下目的:
- API 版本和组查询:
- 通过
APIVersions
和APIGroupList
等资源,用户可以查询 Kubernetes 集群支持的所有 API 版本和 API 组。它们提供集群的元数据,帮助客户端了解哪些资源是可用的。
- 通过
- 集群信息:
- 通过查询
APIGroup
,APIResourceList
,用户可以获取集群中某个 API 组的资源类型列表,以及这些资源的详细信息。
- 通过查询
- 操作状态:
Status
类型通常用于表示请求的执行状态,特别是在资源操作(如创建、删除等)完成后,API 会返回Status
来指示操作结果。
总结
这些无状态资源(如 &Status{}
, &APIVersions{}
, &APIGroupList{}
, &APIGroup{}
, &APIResourceList{}
等)并不是存储在某个特定的 “项目” 中,而是定义在 Kubernetes 的源代码库中,作为 Kubernetes API Server 的一部分。它们通常存储和返回集群的元数据、资源列表、版本信息等,主要通过 Kubernetes API Server 提供的端点来访问。