In-depth analysis of the API object type definition of kubernetes

table of Contents

 

1. Background

2. Analysis

2.1api

2.2metav1

2.2.1MetaType

2.2.3ListMeta

2.3runtime

2.3.1 schedule

2.3.2Object

3. Summary


1. Background

When I was learning kuberentes, the author, as a code farmer, was very curious about its code implementation. So I started to git clone the code. First of all, I was confused by the code warehouse of kuberentes. The kuberentes project has many warehouses, including kubernetes, client-go, api, apimachinery..., where should I start? Simply start with the definition of the API object of kubernetes. The api-related warehouse has two api and apimachinery. At the same time, there are two packages of api and apis in the apimachinery warehouse. It seems that they all have types.go and meta.go. , Interface.go. At this time, the author's mood is really unspeakable, but curiosity urges me to understand the principle, so I have this article with a similar summary. I hope this article can help readers get a preliminary understanding of kubernetes code and become a more basic introductory article.

2. Analysis

In the past, in the author's impression, APIs were all kinds of interfaces, and the most typical one was the API of the operating system. When it comes to APIs, the default is function definitions. Until REST APIs become popular, APIs are no longer functions in form, but the principles are the same, except that the server side of the interface has changed from local to remote. In fact, the author has always ignored another important point of the API, that is, the interface type, that is, the parameter type of the interface function, which is also a part of the API. The author believes that: the API of the operating system emphasizes methods, and most of the parameter types are designed for the method, while the Rest API emphasizes resources, and there are only a few methods. When understanding the Rest API of a system, we must first look at what resources are available, how these resources are defined, what operations are supported, and so on.

What kubernetes provides externally is the Rest API, but this part is packaged into a form similar to SDK by the client-go project. And apisever provides various operations based on API objects. The goal of this article is to explore how API objects are defined and implemented in kubernetes.

2.1api

There are a lot of API objects provided in kubernetes, which are defined in the k8s.io/api repository, which is why this chapter is named api. Pod should be one of the most basic objects. When I started learning kubernetes, I believe that most students have written code similar to the following:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']

A Pod object named myapp-pod is created in kubernetes through the command kubectl create -f xxx.yaml (namespace is ignored here).

Analyze the above process from a programming perspective: There needs to be a Pod type in kubernetes. Each time you execute kubectl create -f xxx.yaml to create a Pod object, you need to instantiate the Pod and assign the parameters in xxx.yaml to the Pod. Object.

Now let's take a look at how the Pod type is defined in kubernetes:

// 代码源自k8s.io/api/core/v1/types.go
// kubernetes的API对象是单独的git仓库(https://github.com/kubernetes/api.git),可见API对象
// 在kubernetes项目中的重要程度。
type Pod struct {
    // metav1是"k8s.io/apimachinery/pkg/apis/meta/v1"的重命名。额...,apimachinery又是
    // 什么鬼?apis包又是干啥的?起初笔者被这些名字搞得云里雾里,但所有的这些迷雾都会在本文揭开,此处
    // 读者只需要知道这个是类型的meta。那什么又是类型的meta呢?以普通类型int32为例,类型名称
    // “int32”、类型占用内存空间4字节就是类型的meta,简单的说就是类型属性的描述。而kubernetes的
    // API对象的类型meta是如何定义的,后面会有单独章节详细说明。
    metav1.TypeMeta `json:",inline"`
    // 同样是metav1包,这回是对象的meta。同样以int32为例,对象的地址就属于对象meta。在kubernetes
    // 中,API对象都有自己的属性,并且他们都有相同的属性,例如名字、命名空间、标签等等。kuberentes把
    // 这些公共的属性提取出来就是metav1.ObjectMeta,成为了API对象类型的父类。
    metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
    // 从名字上看还是比较好理解的,就是Pod规格,最为代表性的就是CPU、内存的资源使用。它和xxx.yaml中
    // spec是关联的。PodSpec不作为本文的说明重点,所以不再详细解释。
    Spec PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
    // Pod的状态,比如是运行还是挂起、Pod的IP、启动时间等等。
    Status PodStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}

From the definition of Pod, it inherits two types, metav1.TypeMeta and metav1.ObjectMeta, and defines two member variables, Spec and Status. In fact, most of the types of kubernetes API objects are of this structure, they all inherit metav1.TypeMeta and metav1.ObjectMeta, the former is used to define the attributes of the type, the latter is used to define the public attributes of the object; Spec is used to define the API object type The private properties of API objects are also the difference between API objects (for example, although Pod and Deployment both inherit two parent classes, the difference between them is achieved through Spec. It is like two children of the same parent, there are Where they are like, more or less, they have become two independent individuals, which is the charm of inheritance); Status is used to describe the state of each object, and the type of each object Closely related. Careful readers can easily find that metav1.TypeMeta and metav1.ObjectMeta correspond to the kind, apiVersion, and metadata fields in xxx.yaml, and Spec corresponds to the spec field in xxx.yaml. This can be confirmed in the code comment `json:...`, and another conclusion can be drawn here, that is, xxx.yaml is the serialization of Pod type yaml. Therefore, kubectl create -f xxx.yaml is equivalent to new(Pod).

Here I want to say a few words about metav1.TypeMeta and metav1.ObjectMeta. They can be regarded as the base classes of all API objects in kubernetes, similar to the Object class in java. Because the language has a compiler, things like metav1.TypeMeta are blocked from compilation, so all the classes that developers see inherit from Object. But in kubernetes, each API object needs the metav1.TypeMeta field to describe what type it is, so that the corresponding type of object can be constructed, so the metav1.TypeMeta field of all objects of the same type are the same. But metav1.ObjectMeta is different, it is a public property that defines an object, that is, a property that all objects should have. This part is related to the object itself, and has nothing to do with the type, so the metav1.ObjectMeta of all objects of the same type may be different.

In addition to the single object in the kubernetes API object, there is also an object list type, which is used to describe a group of objects, which is equivalent to slice in golang. The typical application scenario of the object list is enumeration, and the object list can express a group of objects. Some readers may ask why you don’t use slices of objects, such as []Pod. With the author’s explanation of the object list, readers will understand. Here we take PodList as an example for analysis:

// 代码源自k8s.io/api/core/v1/types.go
type PodList struct {
    // PodList同样需要继承metav1.TypeMeta,毕竟对象列表也好、单体对象也好都需要类型属性。
    // PodList比[]Pod类型在yaml或者json表达上多了类型描述,当需要根据yaml构建对象列表的时候,
    // 就可以根据类型描述反序列成为PodList。而[]Pod则不可以,他必须确保yaml就是[]Pod序列化的
    // 结果,否则就会报错。这就无法实现一个通用的对象序列化/反序列化。
    metav1.TypeMeta `json:",inline"`
    // 与Pod不同,PodList继承了metav1.ListMeta,metav1.ListMeta是所有对象类表类型的父类,
    // 他定义了所有列表类型公共属性。
    metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
    // Items就是PodList定义的本质了,其实就是Pod的slice。说白了PodList就是[]Pod基础上加了一些
    // 跟类型和类表相关的信息,这些信息的作用会在后面的章节做详细解释。
    Items []Pod `json:"items" protobuf:"bytes,2,rep,name=items"`
}

The definition of Pod has been explained before, but PodList will not explain much. Here is a summary:

  1. metav1.TypeMeta and metav1.ObjectMeta are the parent classes of all API monomer objects;
  2. metav1.TypeMeta and metav1.ListMeta are the parent classes of all API list objects;
  3. metav1.TypeMeta is the parent class of all API objects. This is also easy to understand. After all, all objects must explain what type they are;

2.2metav1

metav1 is the abbreviation of k8s.io/apimachinery/pkg/apis/meta/v1, and will be referred to as metav1 in the following.

2.2.1MetaType

As the parent class of all API objects, it's time to reveal its true colors:

// 代码源自:k8s.io/apimachinery/pkg/apis/meta/v1/types.go
// 同样来自apimachinery仓库,ObjectMeta是xxx.yaml中metadata字段,平时我们填写的metadata
// 一般只有name、label,其实ObjectMeta字段还是有很多内容了,让笔者逐一介绍一下。
type ObjectMeta struct {
    // 对象的名字应该不用介绍了。
    Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
    // 如果Name为空,系统这为该对象生成一个唯一的名字。
    GenerateName string `json:"generateName,omitempty" protobuf:"bytes,2,opt,name=generateName"`
    // 命名空间,在平时学习、调试的时候很少用,但是在发布的时候会经常用。
    Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`
    // 对象的URL,由系统生成。
    SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,4,opt,name=selfLink"`
    // 对象的唯一ID,由系统生成。
    UID types.UID `json:"uid,omitempty" protobuf:"bytes,5,opt,name=uid,casttype=k8s.io/kubernetes/pkg/types.UID"`
    // 资源版本,这是一个非常有意思且变量,版本可以理解为对象在时间轴上的一个时间节点,代表着对象最后
    // 一次更新的时刻。如果说Name是在Namespace空间下唯一,那么ResourceVersion则是同名、同类型
    // 对象时间下唯一。因为同名对象在不同时间可能会更新、删除再添加,在比较两个对象谁比较新的情况
    // 非常有用,比如Watch。
    ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,6,opt,name=resourceVersion"`
    // 笔者很少关注这个值,所以也不太了解是干什么的,读者感兴趣可以自己了解一下。
    Generation int64 `json:"generation,omitempty" protobuf:"varint,7,opt,name=generation"`
    // 对象创建时间,由系统生成。
    CreationTimestamp Time `json:"creationTimestamp,omitempty" protobuf:"bytes,8,opt,name=creationTimestamp"`
    // 对象删除时间,指针类型说明是可选的,当指针不为空的时候说明对象被删除了,也是由系统生成
    DeletionTimestamp *Time `json:"deletionTimestamp,omitempty" protobuf:"bytes,9,opt,name=deletionTimestamp"`
    // 对象被删除前允许优雅结束的时间,单位为秒。
    DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty" protobuf:"varint,10,opt,name=deletionGracePeriodSeconds"`
    // 对象标签,这个是我们经常用的,不用多解释了
    Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"`
    // 批注,这个和标签很像,但是用法不同,比如可以用来做配置。
    Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"`
    // 该对象依赖的对象类表,如果这些依赖对象全部被删除了,那么该对象也会被回收。如果该对象对象被
    // 某一controller管理,那么类表中有一条就是指向这个controller的。例如Deployment对象的
    // OwnerReferences有一条就是指向DeploymentController的。
    OwnerReferences []OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid" protobuf:"bytes,13,rep,name=ownerReferences"`
    // 下面这几个变量笔者没有了解过,等笔者知道了再来更新文章吧。
    Finalizers []string `json:"finalizers,omitempty" patchStrategy:"merge" protobuf:"bytes,14,rep,name=finalizers"`
    ClusterName string `json:"clusterName,omitempty" protobuf:"bytes,15,opt,name=clusterName"`
    ManagedFields []ManagedFieldsEntry `json:"managedFields,omitempty" protobuf:"bytes,17,rep,name=managedFields"`
}

// 代码源自k8s.io/apimachinery/pkg/apis/meta/v1/meta.go,GetObjectMeta是MetaAccessor
// 的接口函数,这个函数说明了ObjectMeta实现了MetaAccessor。
func (obj *ObjectMeta) GetObjectMeta() Object { return obj }

// 下面所有的函数是接口Object的ObjectMeta实现,可以看出来基本就是setter/getter方法。纳尼?
// 又一个Object(这个Object是metav1.Object,本章节简写为Object)?Object是API对象公共属性
// (meta信息)的抽象,下面的函数是Object所有函数的实现,因为功能比较简单,笔者就不一一注释了。
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 }
func (meta *ObjectMeta) GetResourceVersion() string          { return meta.ResourceVersion }
func (meta *ObjectMeta) SetResourceVersion(version string)   { meta.ResourceVersion = version }
func (meta *ObjectMeta) GetGeneration() int64                { return meta.Generation }
func (meta *ObjectMeta) SetGeneration(generation int64)      { meta.Generation = generation }
func (meta *ObjectMeta) GetSelfLink() string                 { return meta.SelfLink }
func (meta *ObjectMeta) SetSelfLink(selfLink string)         { meta.SelfLink = selfLink }
func (meta *ObjectMeta) GetCreationTimestamp() Time          { return meta.CreationTimestamp }
func (meta *ObjectMeta) SetCreationTimestamp(creationTimestamp Time) {
    meta.CreationTimestamp = creationTimestamp
}
func (meta *ObjectMeta) GetDeletionTimestamp() *Time { return meta.DeletionTimestamp }
func (meta *ObjectMeta) SetDeletionTimestamp(deletionTimestamp *Time) {
    meta.DeletionTimestamp = deletionTimestamp
}
func (meta *ObjectMeta) GetDeletionGracePeriodSeconds() *int64 { return meta.DeletionGracePeriodSeconds }
func (meta *ObjectMeta) SetDeletionGracePeriodSeconds(deletionGracePeriodSeconds *int64) {
    meta.DeletionGracePeriodSeconds = deletionGracePeriodSeconds
}
func (meta *ObjectMeta) GetLabels() map[string]string                 { return meta.Labels }
func (meta *ObjectMeta) SetLabels(labels map[string]string)           { meta.Labels = labels }
func (meta *ObjectMeta) GetAnnotations() map[string]string            { return meta.Annotations }
func (meta *ObjectMeta) SetAnnotations(annotations map[string]string) { meta.Annotations = annotations }
func (meta *ObjectMeta) GetFinalizers() []string                      { return meta.Finalizers }
func (meta *ObjectMeta) SetFinalizers(finalizers []string)            { meta.Finalizers = finalizers }
func (meta *ObjectMeta) GetOwnerReferences() []OwnerReference         { return meta.OwnerReferences }
func (meta *ObjectMeta) SetOwnerReferences(references []OwnerReference) {
    meta.OwnerReferences = references
}
func (meta *ObjectMeta) GetClusterName() string                 { return meta.ClusterName }
func (meta *ObjectMeta) SetClusterName(clusterName string)      { meta.ClusterName = clusterName }
func (meta *ObjectMeta) GetManagedFields() []ManagedFieldsEntry { return meta.ManagedFields }
func (meta *ObjectMeta) SetManagedFields(managedFields []ManagedFieldsEntry) {
    meta.ManagedFields = managedFields
}

The purpose of each member variable of ObjectMeta is not helpful for understanding this article. Readers only need to know that these properties are common properties of all API objects. Therefore, the author's comments on each member variable only remain at the surface definition, and did not give an in-depth explanation.

At this point, you can draw a conclusion: ObjectMeta implements the two interfaces of Object and MetaAccessor, and all the monolithic objects of kubernetes inherit ObjectMeta, then all API objects implement Object and MetaAccessor. There are many places in kubernetes to access the meta information of API objects and do not distinguish between object types. Object is a good choice.

2.2.3ListMeta

Similar to the ObjectMeta function, ListMeta defines the common properties of all list objects:

// 代码源自:k8s.io/apimachinery/pkg/apis/meta/v1/types.go
type ListMeta struct {
    // 下面这两个变量在ObjectMeta相同,不多解释
    SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,1,opt,name=selfLink"`
    ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,2,opt,name=resourceVersion"`
    // 在列举对象的时候可能会有非常多的对象,kubernetes支持分页获取,类似于SQL的limit,当对象总量
    // 多于单页的总量的时候,这个变量就会被设置。它用来告知用户需要继续获取,并且它包含了下次获取的
    // 起始位置。
    Continue string `json:"continue,omitempty" protobuf:"bytes,3,opt,name=continue"`
    // 从字面意思也能理解,就是还剩多少个对象,这个和Continue是配合使用的,当Continue被设置了
    // 这个变量就不会为空,用来告诉用户还有多少对象没有获取。
    RemainingItemCount *int64 `json:"remainingItemCount,omitempty" protobuf:"bytes,4,opt,name=remainingItemCount"`
}

// 代码源自k8s.io/apimachinery/pkg/apis/meta/v1/meta.go
// 下面所有的函数是接口ListInterface的ListMeta实现,ListInterface是API对象列表公共属性(meta)
// 的抽象。
func (meta *ListMeta) GetResourceVersion() string        { return meta.ResourceVersion }
func (meta *ListMeta) SetResourceVersion(version string) { meta.ResourceVersion = version }
func (meta *ListMeta) GetSelfLink() string               { return meta.SelfLink }
func (meta *ListMeta) SetSelfLink(selfLink string)       { meta.SelfLink = selfLink }
func (meta *ListMeta) GetContinue() string               { return meta.Continue }
func (meta *ListMeta) SetContinue(c string)              { meta.Continue = c }
func (meta *ListMeta) GetRemainingItemCount() *int64     { return meta.RemainingItemCount }
func (meta *ListMeta) SetRemainingItemCount(c *int64)    { meta.RemainingItemCount = c }

Here is a brief summary. In the metav1 package, the public properties (meta) of the API single object and the object list are abstracted, which are metav1.Object and metav1.ListInterface respectively. At the same time, the metav1 package implements these two abstractions. They are metav1.ObjectMeta and metav.listMeta. API object types can be abstracted by inheriting these classes. Is there a bit of "type" and "basic" as defined by apimachinery "Facilities" mean?

2.3runtime

2.3.1 schedule

As mentioned above, metav1.TypeMeta implements schema.ObjectKind (ObjectKind for short in this section), and metav1.TypeMeta has been very intuitive to correspond to the corresponding fields of xxx.yaml, so what does ObjectKind do?

// 代码源自k8s.io/apimachinery/pkg/runtime/schema/interfaces.go
// ObjectKind是接口,两个接口函数是GroupVersionKind类型的setter和getter
type ObjectKind interface {
    SetGroupVersionKind(kind GroupVersionKind)
    GroupVersionKind() GroupVersionKind
}
// GroupVersionKind才是kubernetes的API对象类型真身,他包括Kind、Version和Group。其中Kind和
// Version还比较好理解,Group又是什么?其实Group/Version才是xxx.yaml的apiVersion字段。
// 在kuberentes中API对象是分组的,像Pod、Service、ConfigMap都属于core分组,而core分组的对象
// 无需在apiVersion字段明文写出来,系统会默认将这类的对象归为core分组,正如文章开始那个Pod的例子。
// 详情可以看下面的代码实现。
type GroupVersionKind struct {
    Group   string
    Version string
    Kind    string
}
// 这个函数在metav1.TypeMeta实现GroupVersionKind()接口的时候调用了,该函数调用了ParseGroupVersion
// 实现从apiVersion解析Group和Version。
func FromAPIVersionAndKind(apiVersion, kind string) GroupVersionKind {
    if gv, err := ParseGroupVersion(apiVersion); err == nil {
        return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
    }
    return GroupVersionKind{Kind: kind}
}
// 从apiVersion解析Group和Version。
func ParseGroupVersion(gv string) (GroupVersion, error) {
    // 这种不报错是什么道理?什么情况下会有对象没有Group和Version?
    if (len(gv) == 0) || (gv == "/") {
        return GroupVersion{}, nil
    }
    // 数apiVersion中有几个‘/’
    switch strings.Count(gv, "/") {
    // 没有'/',就像文章开始的Pod的例子,那么Group就是空字符串,系统默认会把空字符串归为core
    case 0:
        return GroupVersion{"", gv}, nil
    // 有一个'/',那么就以'/'分割apiVersion,左边为Group,右边为Version。
    case 1:
        i := strings.Index(gv, "/")
        return GroupVersion{gv[:i], gv[i+1:]}, nil
    // 其他则为格式错误。
    default:
        return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv)
    }
}

That's why the apiVersion of Deployment is apps/v1 or extension/v1beta1. So far, it can be summarized as follows:

  1. schema.ObjecKind is an abstraction of all API object types meta;
  2. metav1.TypeMeta is an implementation of schema.ObjecKind. The API object type implements schema.ObjecKind by inheriting metav1.TypeMeta;

2.3.2Object

If schema.ObjecKind is the abstraction of all API object types, with metav1.Object as the abstraction of the common properties of all API monomer objects, it seems that the root of all API objects has been found. But do you feel weird? If you want to point to any API monomer object through a base class pointer, schema.ObjecKind and metav1.Object feel inappropriate, because the domain they can access is limited. If there is a function that needs to access the type and public properties of any API object, then two pointers to the same object (schema.ObjecKind and metav1.Object) must be passed in, which is too unacceptable. Is there a type as a unified base class for API monomer objects? This is what this section will discuss: runtime.Object (referred to as Object in this section).

// 代码源自k8s.io/apimachinery/pkg/runtime/interfaces.go
type Object interface {
    // 有了这个函数,就可以访问对象的类型域
    GetObjectKind() schema.ObjectKind
    // deepcopy是golang深度复制对象的方法,至于什么是深度复制本文就不解释了。这是个不错的函数,
    // 可以通过这个接口复制任何API对象而无需类型依赖。
    DeepCopyObject() Object
    // 就这么两个函数了么?那如果需要访问对象的公共属性域怎么办?不应该有一个类似GetObjectMeta()
    // 的接口么?这一点,kubernetes是通过另一个方式实现的,见下面的代码。
}

// 代码源自k8s.io/apimachinery/pkg/api/meta/meta.go,注意是api包,不是apis
// Accessor()函数可以把obj安全的转换为metav1.Object,这样也就避免了每个API对象类型都需要实现
// 类似GetObjectMeta()的接口了。有的读者肯定会问:所有的API对象都继承了metav1.ObjectMeta,
// 这个类型不是实现了GetObjectMeta()么?笔者就要在这里做出说明:笔者提到是类似GetObjectMeta(),
// 如果接口名字是ObjectMeta(),那岂不是继承metav1.ObjectMeta就没用了?一个顶层的类型抽象定义不
// 应该依赖于相对底层类型的实现。
func Accessor(obj interface{}) (metav1.Object, error) {
    // 使用了golang的switch type语法
    switch t := obj.(type) {
    // 因为API对象类型都继承了metav1.ObjectMeta,也就自然实现了metav1.Object。
    case metav1.Object:
        return t, nil
    // 在ObjectMeta章节笔者提到了,metav1.ObjectMeta实现了metav1.ObjectMetaAccessor,
    // 所以API对象也自然实现了metav1.ObjectMetaAccessor。但是API对象会在上一个case就返回
    // 了,这个case是给谁用的呢?笔者也比较疑惑,笔者感觉是那些没有直接继承metav1.ObjectMeta
    // 却实现了metav1.ObjectMetaAccessor的类型,笔者暂时还没找到相关类型定义。
    case metav1.ObjectMetaAccessor:
        if m := t.GetObjectMeta(); m != nil {
            return m, nil
        }
        return nil, errNotObject
    default:
        return nil, errNotObject
    }
}

Wait, why don't you see that the API object implements runtime.Object.DeepCopyObject()? That's because deep copy needs to be implemented for specific API object types, and there is type dependency, which cannot be implemented as the parent class of API object types. Here we take Pod as an example to see how Pod implements DeepCopyObject().

// +genclient
// +genclient:method=GetEphemeralContainers,verb=get,subresource=ephemeralcontainers,result=EphemeralContainers
// +genclient:method=UpdateEphemeralContainers,verb=update,subresource=ephemeralcontainers,input=EphemeralContainers,result=EphemeralContainers
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// 上面+k8s:deepcopy-gen:....就是告诉代码生成工具为下面的类型生成runtime.Object接口的
// DeepCopyObject()函数实现。因为所有的API对象类型都要实现DeepCopyObject()函数,这是一个相当
// 大量的重复工作,所以kubernetes用代码生成工具来实现。至于如何实现的不作为本文讨论重点,只要读者
// 知道deep copy的目的就可以了。
type Pod struct {
    ......
}

3. Summary

At this point, the summary of the previous chapters can be forgotten, because those summaries are based on the knowledge background at the time, and may lack the overall consideration to make wrong conclusions, so here is a comprehensive summary, as shown in the figure below. Show:

 

  1. runtime.Object is the root class (interface) of all API monomer objects;
  2. schema.ObjectKind is an abstraction of API object types (interface);
  3. metav1.Object is an abstraction (interface) of the public properties of API objects;
  4. metav1.ListInterface is an abstraction (interface) of the public properties of the API object list;
  5. metav1.TypeMeta is an implementation of schema.ObjectKind, and the API object type inherits it;
  6. metav1.ObjectMeta is an implementation of metav1.Object, and the API object type inherits it;
  7. metav1.ListMeta is an implementation of metav1.ListInterface, and the API object list inherits it;

 

Guess you like

Origin blog.csdn.net/weixin_42663840/article/details/102558455