Kubernetes版本:v1.18.4

一、介绍

在kubernetes中,一切皆资源。

在kubernetes中,对资源进行了分组以及版本化,它们分为Group(资源组)、Version(资源版本)、Resource(资源)、Kind(种类)。其中:

  • Group:资源组,在Kubernetes API Server中也称为APIGroup
  • Version:资源版本,在Kubernetes API Server中也成为APIVersions
  • Resource:资源,在Kubernetes API Server中也成为APIResource
  • Kind:种类,描述Resource的种类

整体的数据结构关系如图所示:
image.png

Kubernetes系统支持多个Group,每个Group支持多个Version,每个Version支持多个Resource,其中部分资源同时会拥有自己的子资源(即SubResource)。

资源组、资源版本、资源、子资源的完整表现形式为///。以常用的Deployment资源为例,其完整表现形式为apps/v1/deployments/status。

每一个资源都拥有一定数量的资源操作方法(即Verbs),资源操作方法用于Etcd集群存储中对资源对象的增、删、改、查操作。目前Kubernetes系统支持8种资源操作方法,分别是create、delete、deletecollection、get、list、patch、update、watch操作方法。

每一个资源都至少有两个版本,分别是外部版本(External Version)和内部版本(Internal Version)。外部版本用于对外暴露给用户请求的接口所使用的资源对象。内部版本不对外暴露,仅在Kubernetes API Server内部使用。

Kubernetes资源也可分为两种,分别是Kubernetes Resource(Kubernetes内置资源)和Custom Resource(自定义资源)。开发者通过CRD(即CustomResource Definitions)可实现自定义资源,它允许用户将自己定义的资源添加到Kubernetes系统中,并像使用Kubernetes内置资源一样使用它们。

源码位置:staging\src\k8s.io\apimachinery\pkg\runtime\schema\group_version.go

  1. type GroupVersionResource struct {
  2. Group string
  3. Version string
  4. Resource string
  5. }

常用的资源数据结构都定义在这个文件中。

结构名称 说明
GroupVersionResource 定义资源组、资源版本、资源
GroupResource 定义资源组、资源
GroupKind 定义资源组、资源种类
GroupVersionKind 定义资源组、资源版本、资源种类
GroupVersion 定义资源组、资源版本
GroupVersions 定义多个资源版本

二、Group 资源组

Group叫做资源组,在Kubernetes API Server中也可称其为APIGroup。Kubernetes系统中定义了许多资源组,这些资源组按照不同功能将资源进行了划分,资源组特点如下。

  • 将众多资源按照功能划分成不同的资源组,并允许单独启用/禁用资源组。当然也可以单独启用/禁用资源组中的资源。
  • 支持不同资源组中拥有不同的资源版本。这方便组内的资源根据版本进行迭代升级。
  • 支持同名的资源种类(即Kind)存在于不同的资源组内。
  • 资源组与资源版本通过Kubernetes API Server对外暴露,允许开发者通过HTTP协议进行交互并通过动态客户端(即DynamicClient)进行资源发现。
  • 支持CRD自定义资源扩展。
  • 用户交互简单,例如在使用kubectl命令行工具时,可以不填写资源组名称。

其代码路径:staging\src\k8s.io\apimachinery\pkg\apis\meta\v1\types.go
定义如下:

  1. type APIGroup struct {
  2. TypeMeta `json:",inline"`
  3. Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
  4. Versions []GroupVersionForDiscovery `json:"versions" protobuf:"bytes,2,rep,name=versions"`
  5. PreferredVersion GroupVersionForDiscovery `json:"preferredVersion,omitempty" protobuf:"bytes,3,opt,name=preferredVersion"`
  6. ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs,omitempty" protobuf:"bytes,4,rep,name=serverAddressByClientCIDRs"`
  7. }

其中:

  • Name:资源组的名称
  • Versions:资源组的版本,一个资源组可以有多个版本
  • PreferredVersion:首选版本,如果有多个资源版本,则指定一个版本为首选版本
  • ServerAddressByClientCIDRs:客户端和服务端的映射,方便客户端找服务端地址

在当前的Kubernetes系统中,支持两类资源组,分别是拥有组名的资源组和没有组名的资源组。

  • 拥有组名://,例如apps/v1/deployments,通过http访问的路径为:http://localhost:6443/apis///
  • 没有组名:/,例如/v1/pods,通过http访问的路径为:http://localhost:6443/api//

    没有组名的资源组,表示资源组名称为空。用来表示核心资源组下的v1资源版本。

三、Version 版本

Kubernetes的资源版本控制可分为3种,分别是Alpha、Beta、Stable,它们之间的迭代顺序为Alpha→Beta→Stable,其通常用来表示软件测试过程中的3个阶段。Alpha是第1个阶段,一般用于内部测试;Beta是第2个阶段,该版本已经修复了大部分不完善之处,但仍有可能存在缺陷和漏洞,一般由特定的用户群来进行测试;Stable是第3个阶段,此时基本形成了产品并达到了一定的成熟度,可稳定运行。

代码路径:staging\src\k8s.io\apimachinery\pkg\apis\meta\v1\types.go

  1. type APIVersions struct {
  2. TypeMeta `json:",inline"`
  3. Versions []string `json:"versions" protobuf:"bytes,1,rep,name=versions"`
  4. ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs" protobuf:"bytes,2,rep,name=serverAddressByClientCIDRs"`
  5. }

其中:

  • Versions:资源版本列表,可以有多个版本
  • ServerAddressByClientCIDRs:客户端和服务端的映射关系,方便客户端查找服务端地址

四、Resource 资源

在Kubernetes中,一切皆资源,资源被实例化后称为资源对象,所有资源对象都是Entity(实体),Kubernetes使用Entity来表示当前的状态,用户可以使用Kubernetes API Server进行查询和更新资源对象。

在Kubernetes中Entity分为两类:

  • 持久性实体:kubernetes会确保该实体持久存在,比如deployment资源对象
  • 短暂性实体:该实体是一次性的,比如pod资源对象

资源数据结构代码路径:staging\src\k8s.io\apimachinery\pkg\apis\meta\v1\types.go

  1. type APIResource struct {
  2. Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
  3. SingularName string `json:"singularName" protobuf:"bytes,6,opt,name=singularName"`
  4. Namespaced bool `json:"namespaced" protobuf:"varint,2,opt,name=namespaced"`
  5. Group string `json:"group,omitempty" protobuf:"bytes,8,opt,name=group"`
  6. Version string `json:"version,omitempty" protobuf:"bytes,9,opt,name=version"`
  7. Kind string `json:"kind" protobuf:"bytes,3,opt,name=kind"`
  8. Verbs Verbs `json:"verbs" protobuf:"bytes,4,opt,name=verbs"`
  9. ShortNames []string `json:"shortNames,omitempty" protobuf:"bytes,5,rep,name=shortNames"`
  10. Categories []string `json:"categories,omitempty" protobuf:"bytes,7,rep,name=categories"`
  11. StorageVersionHash string `json:"storageVersionHash,omitempty" protobuf:"bytes,10,opt,name=storageVersionHash"`
  12. }

其中:

  • Name:资源名称
  • SingularName:资源的单数名称,它必须由小写字母组成,默认使用资源种类(Kind)的小写形式进行命名。例如,Pod资源的单数名称为pod,复数名称为pods。
  • Namespaced:资源是否有命名空间
  • Group:资源所属组
  • Version:资源所属的资源版本
  • Kind:资源种类
  • Verbs:资源的操作列表
  • ShortNames:资源简称,比如deployment简称为deploy
  • Categories:组资源的类别
  • StorageVersionHash:存储版本的hash值

4.1、资源版本

资源版本分为外部版本和内部版本。外部版本用于对外暴露给用户请求的接口所使用的资源对象,内部版本不对外暴露,仅在Kubernetes API Server内部使用。内部版本用于多资源版本的转换,例如将v1beta1版本转换为v1版本,其过程为v1beta1→internal→v1,即先将v1beta1转换为内部版本(internal),再由内部版本(internal)转换为v1版本。内部版本资源对象通过runtime.APIVersionInternal(即__internal)进行标识。

资源版本(如v1beta1、v1等)与外部版本/内部版本概念不同。拥有资源版本的资源属于外部版本,拥有runtime.APIVersionInternal标识的资源属于内部版本。

内部版本定义的代码路径为:pkg\apis\<GROUP>\types.go下,外部版本定义的代码路径为:pkg\apis\<GROUP>\<VERSION>\,例如,Deployment资源,它的外部版本定义在pkg/apis/apps/{v1,v1beta1,v1beta2}/目录下,它的内部版本定义在pkg/apis/apps/目录下(内部版本一般与资源组在同一级目录下)。

外部版本的资源类型定义在staging\src\k8s.io\api\<GROUP>\<VERSION>\types.go,内部版本的资源类型定义在pkg\apis\<GROUP>\types.go

资源的外部版本与内部版本的代码定义不太一样,外部版本的资源需要对外暴露给用户请求的接口,所以资源代码定义了JSON Tags和Proto Tags,用于请求的序列化和反序列化操作。内部版本的资源不对外暴露,所以没有任何的JSON Tags和Proto Tags定义。

以Deployment为例。
外部版本:staging\src\k8s.io\api\apps\v1\types.go

  1. type Deployment struct {
  2. metav1.TypeMeta `json:",inline"`
  3. // Standard object metadata.
  4. // +optional
  5. metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
  6. // Specification of the desired behavior of the Deployment.
  7. // +optional
  8. Spec DeploymentSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
  9. // Most recently observed status of the Deployment.
  10. // +optional
  11. Status DeploymentStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
  12. }

内部版本:pkg\apis\apps\types.go

  1. type DeploymentList struct {
  2. metav1.TypeMeta
  3. // +optional
  4. metav1.ListMeta
  5. // Items is the list of deployments.
  6. Items []Deployment
  7. }

4.2、资源代码定义

Kubernetes资源代码定义在pkg/apis目录下,同一资源对应着内部版本和外部版本,内部版本和外部版本的资源代码结构并不相同。

以Deployment为例,其目录结构如下:
image.png
文件说明:

  • fuzzer:api组
  • install:把资源组下的所有资源注册到注册表中
  • v1/v1beta1/v1beta2:资源的外部版本
  • validation:定义资源的验证方法
  • doc.go:GoDoc文件,定义了当前包的注释信息
  • register.go:定义了资源组、资源版本及资源的注册信息
  • type.go:定义了在当前资源组、资源版本下所支持的资源类型
  • zz_generated.deepcopy.go:定义了资源的深复制操作,该文件由代码生成器自动生成

每一个Kubernetes资源目录,都通过register.go代码文件定义所属的资源组和资源版本,内部版本资源对象通过runtime.APIVersionInternal(即__internal)标识,代码示例如下:

代码路径:pkg\apis\apps\register.go

  1. // GroupName is the group name use in this package
  2. const GroupName = "apps"
  3. // SchemeGroupVersion is group version used to register these objects
  4. var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}

外部版本直接通过版本号标识,代码如下:
代码路径:pkg\apis\apps\v1\register.go

  1. // GroupName is the group name use in this package
  2. const GroupName = "apps"
  3. // SchemeGroupVersion is group version used to register these objects
  4. var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}

组下面的资源定义在pkg\apis\apps\types.go目录下。它的外部版本定义在pkg/apis/apps/{v1,v1beta1,v1beta2}目录下。

4.3、资源注册

资源是需要注册导注册表中的,其代码目录为pkg\apis\\install\install.go,里面的代码并不多,如下:

  1. func init() {
  2. Install(legacyscheme.Scheme)
  3. }
  4. // Install registers the API group and adds types to a scheme
  5. func Install(scheme *runtime.Scheme) {
  6. utilruntime.Must(apps.AddToScheme(scheme))
  7. utilruntime.Must(v1beta1.AddToScheme(scheme))
  8. utilruntime.Must(v1beta2.AddToScheme(scheme))
  9. utilruntime.Must(v1.AddToScheme(scheme))
  10. utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta2.SchemeGroupVersion, v1beta1.SchemeGroupVersion))
  11. }

legacyscheme.Scheme是kube-apiserver组件的全局资源注册表,Kubernetes的所有资源信息都交给资源注册表统一管理。apps.AddToScheme是注册apps组下面的内部版本,{v1beta1,v1beta2,v1}.AddToScheme注册外部版本,scheme.SetVersionPriority设置版本优先级,最前面的优先级最高。优先级最高的版本就是首选版本,即在我们没有指定版本的时候就使用首选版本。

4.4、资源操作方法

在Kubernetes系统中,针对每一个资源都有一定的操作方法(即Verbs),例如,对于Pod资源对象,可以通过kubectl命令行工具对其执行create、delete、get等操作。Kubernetes系统所支持的操作方法目前有8种操作,分别是create、delete、deletecollection、get、list、patch、update、watch。这些操作方法可分为四大类,分别属于增、删、改、查,对资源进行创建、删除、更新和查询。

资源操作方法的数据结构定义在:staging\src\k8s.io\apimachinery\pkg\apis\meta\v1\types.go

  1. // Verbs masks the value so protobuf can generate
  2. //
  3. // +protobuf.nullable=true
  4. // +protobuf.options.(gogoproto.goproto_stringer)=false
  5. type Verbs []string
  6. func (vs Verbs) String() string {
  7. return fmt.Sprintf("%v", []string(vs))
  8. }

操作方法的接口定义在:staging\src\k8s.io\apiserver\pkg\registry\rest\rest.go,资源对象以及操作接口对象说明如下:

操作方法 操作方法接口 说明
create rest.Creater 创建接口
delete rest.GracefulDeleter 删除接口(单个资源)
deletecollection rest.CollectionDeleter 删除接口(多个资源)
update rest.Updater 更新接口(完整资源)
patch rest.Patcher 补丁接口(局部资源)
get rest.Getter 获取接口(单个资源)
list rest.Lister 获取接口(多个资源)
watch rest.Watcher 监听接口