在上一篇文章中我们主要介绍了 kubernetes 世界中的各种 resource 的 version,其中包括了资源的内部 internal version 和外部非 internal version,以及引入 internal version 来方便各种 resource 持续渐进演化的设计初衷。另外也从源码的角度分析了其中各个资源 group 的对外 version 和 internal version 都定义在哪些源文件之中,在这里我们主要介绍 kubernetes 中各种 resource 的基本定义 model。
我们可以用如下图例来表示 kubernetes 中 resource 的基本定义 model:
根据以前文章,在 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 语言之中面向对象的概念, 例如接口, 继承, 组合等等。
目前先我们写到这里,在下一篇文章中我们来介绍 kubernates resource 的 meta 序列化。