参考

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.Objectschema.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 语言之中面向对象的概念, 例如接口, 继承, 组合等等。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐