参考
Resource Model
在上一篇文章中我们主要介绍了 kubernetes 世界中的各种 resource 的 version,其中包括了资源的内部 internal version 和外部非 internal version,以及引入 internal version 来方便各种 resource 持续渐进演化的设计初衷。另外也从源码的角度分析了其中各个资源 group 的对外 version 和 internal version 都定义在哪些源文件之中,在这里我们主要介绍 kubernetes 中各种 resource 的基本定义 model。
我们可以用如下图例来表示 kubernetes 中 resource 的基本定义 model:
-
所有 resource 的基本定义 model,总结起来就是所有的 resource 都会通过继承的方式来继承 type meta 和 object meta 类型,通过组合成员变量的方式来组合了属于 resource 自己特定的 spec 和 status。这种模型的设计理念也比较常见,类似于在 java 的世界中,多数的设计模式也都是通过继承和组合的概念来完成变化的。
-
可以理解为,就是一个资源创建的基本框架
-
本节也就等同于之前的k8s类型定义介绍
根据以前文章,在 kubernetes 世界之中所有 resource 的基本定义里(例如我们常用的 YAML 文件),一定都有 type meta 和 object meta 这两个部分。在上一篇文章里我们以 deployment 资源为例, 也看同时到了 type meta 和 object meta 在源文件中的对应。
type Deployment struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Spec DeploymentSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
Status DeploymentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
-
我们看到在 deployment 的定义中 type meta 和 object meta 类型并没有名称的定义,而是直接写的类型。在 go 语言中,这种特性就相当于是继承 (类比 java 语言的继承) 。
-
DeploymentSpec 和 DeploymentStatus 这两种类型在资源 deployment 的定义中是有名称 Spec 和 Status 的, 在 go 语言中,这种方式就相当于是组合(类比 java 语言的成员变量)。
-
所以综上进行总结,在 kubernetes 世界里所有的 resource 定义之中,通过继承的方式来继承了 type meta 和 object meta 两种类型,通过组合成员变量的方式组合了属于自己特定的 spec 和 status。
从源码的角度来看 kubernetes resource 的 group version kind (即 GVK) 的属性被定义在 staging/src/k8s.io/apimachinery/pkg/runtime/schema/group\_version.go
中
type GroupVersionKind struct {
Group string
Version string
Kind string
}
对于 TypeMeta 这个类型定义来说,它实现了 runtime.Object
和 schema.ObjectKind
接口 (即实现了接口里定义的方法)
// staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go
type Object interface {
GetObjectKind() schema.ObjectKind
DeepCopyObject() Object
}
// staging/src/k8s.io/apimachinery/pkg/runtime/schema/interfaces.go
type ObjectKind interface {
SetGroupVersionKind(kind GroupVersionKind)
GroupVersionKind() GroupVersionKind
}
// staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/meta.go
func (obj *TypeMeta) GetObjectKind() schema.ObjectKind {
return obj
}
func (obj *TypeMeta) SetGroupVersionKind(gvk schema.GroupVersionKind) {
obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
}
对于 ObjectMeta,它实现了 meta.Object
接口
// staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/meta.go
type Object interface {
GetNamespace() string
SetNamespace(namespace string)
GetName() string
SetName(name string)
GetGenerateName() string
SetGenerateName(name string)
GetUID() types.UID
SetUID(uid types.UID)
.........
}
func (meta *ObjectMeta) GetNamespace() string { return meta.Namespace }
func (meta *ObjectMeta) SetNamespace(namespace string) { meta.Namespace = namespace }
func (meta *ObjectMeta) GetName() string { return meta.Name }
func (meta *ObjectMeta) SetName(name string) { meta.Name = name }
func (meta *ObjectMeta) GetGenerateName() string { return meta.GenerateName }
func (meta *ObjectMeta) SetGenerateName(generateName string) { meta.GenerateName = generateName }
func (meta *ObjectMeta) GetUID() types.UID { return meta.UID }
func (meta *ObjectMeta) SetUID(uid types.UID) { meta.UID = uid }
.........
由上述源码分析可以总结:
-
TypeMeta 和 ObjectMeta 两种结构体分别定义了 kubernetes 各种资源的类型属性和实例属性。
-
两种结构体又分别各自实现了不同的接口, TypeMeta 来实现了 runtime.Object 这个接口以及 schema.ObjectKind 等主要接口。 而 ObjectMeta 结构体则是实现了 meta.Object 等主要接口。
-
对于kubernetes 中的各种不同资源(例如 deployment 等), 通过继承的方式来继承了 TypeMeta 和 ObjectMeta 两种结构体类型, 从而定义了资源 common 的属性和方法。通过组合的方式定义了属于各自不同的 spec 和 status。
-
虽然以上的定义和设计都是 go 语言的特性,但是不难发现其中也处处蕴含着类似我们熟悉的 java 语言之中面向对象的概念, 例如接口, 继承, 组合等等。