参考
详解
1 | 什么是Scheme
k8s系统拥有众多资源,每一种资源就是一个资源类型,这些资源类型需要有统一的注册、存储、查询、管理等机制。目前k8s系统中的所有资源类型都已注册到Scheme资源注册表中,其是一个内存型的资源注册表,拥有如下特点:
-
支持注册多种资源类型,包括内部版本和外部版本。
-
支持多种版本转换机制。
-
支持不同资源的序列化/反序列化机制。
Scheme资源注册表支持两种资源类型(Type)的注册,分别是UnversionedType和KnownType资源类型,分别介绍如下:
**UnversionedType:无版本资源类型,这是一个早期Kubernetes系统中的概念,它主要应用于某些没有版本的资源类型,该类型的资源对象并不需要进行转换。**在目前的Kubernetes发行版本中,无版本类型已被弱化,几乎所有的资源对象都拥有版本,但在metav1元数据中还有部分类型,它们既属于http://meta.k8s.io/v1又属于UnversionedType无版本资源类型,例如:metav1.Status、 metav1.APIVersions、metav1.APIGroupList、metav1.APIGroup、metav1.APIResourceList
KnownType:是目前Kubernetes最常用的资源类型,也可称其为“拥有版本的资源类型”。在scheme资源注册表中,UnversionedType资源类型的对象通过scheme.AddUnversionedTypes方法进行注册,KnownType资源类型的对象通过scheme.AddKnownTypes方法进行注册。
1.1 | Scheme结构体定义
// staging/src/[http://k8s.io/apimachinery/pkg/runtime/scheme.go
type Scheme struct {
gvkToType map[schema.GroupVersionKind]reflect.Type
typeToGVK map[reflect.Type][]schema.GroupVersionKind
unversionedTypes map[reflect.Type]schema.GroupVersionKind
unversionedKinds map[string]reflect.Type
...
}
Scheme资源注册表结构字段说明如下:
- gvkToType:存储GVK与Type的映射关系。
- typeToGVK:存储Type与GVK的映射关系,一个Type会对应一个或多个GVK。
- unversionedTypes:存储UnversionedType与GVK的映射关系。
- unversionedKinds:存储Kind(资源种类)名称与UnversionedType的映射关系。
Scheme资源注册表通过Go语言的map结构实现映射关系,这些映射关系可以实现高效的正向和反向检索,从Scheme资源注册表中检索某个GVK的Type,它的时间复杂度为O(1)。资源注册表映射关系如下图:
2 | 如何使用Scheme
定义注册方法AddToScheme
通过runtime.NewScheme实例化一个新的Scheme资源注册表。注册资源类型到Scheme资源注册表有两种方式:
- 通过scheme.AddKnownTypes方法注册KnownType类型的对象。
- 通过scheme.AddUnversionedTypes方法注册UnversionedType类型的对象。
3 | crd 注册到 Scheme
3.1 | 正常注册
- https://blog.csdn.net/sinat_24092079/article/details/121368895
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
AddToScheme = localSchemeBuilder.AddToScheme
)
// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
// SchemeGroupVersion 声明 group 和 version
// 后面哪些结构体 go type,就相当于 kind
scheme.AddKnownTypes(SchemeGroupVersion,
&Deployment{},
&DeploymentList{},
&StatefulSet{},
&StatefulSetList{},
&DaemonSet{},
&DaemonSetList{},
&ReplicaSet{},
&ReplicaSetList{},
&ControllerRevision{},
&ControllerRevisionList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
3.2 | kubebuilder 注册
// 注册 go type(kind),并没有指定 group 和 verison
func init() {
SchemeBuilder.Register(&EtcdPeer{}, &EtcdPeerList{})
}
// 其实 register 进行了封装,封装了 scheme.AddKnownTypes 和 metav1.AddToGroupVersion 方法
func (bld *Builder) Register(object ...runtime.Object) *Builder {
bld.SchemeBuilder.Register(func(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(bld.GroupVersion, object...)
metav1.AddToGroupVersion(scheme, bld.GroupVersion)
return nil
})
return bld
}
type Builder struct {
GroupVersion schema.GroupVersion
runtime.SchemeBuilder
}