Kubernetes核心数据结构1.0


Group、Version、Resource核心数据结构

在整个 Kubernetes 体系架构中,资源是 Kubernetes 最重要的概念,它本质上是一个资源控制系统————注册、管理、调度资源并维护资源的状态。

Kubernetes 将资源进行分组和版本化,形成 Group、Version、Resource。具体机构图如下:

kubernetes核心数据结构图

  • 部分资源同时会拥有自己的子资源,例如,Deployment 资源拥有 Status 子资源。

  • 完整的表现形式为 ///

  • 外部版本用于对外暴露给用户请求的接口所使用的资源对象。

  • 内部版本不对外暴露,仅在 kubernetes api server 内部使用。

  • kubernetes 的每个资源可使用 metav1.APIResource 结构进行描述,它描述资源的基本信息,例如资源名称,资源所属 命名空间,资源种类,资源可操作的方法列表。

resourceList := []*metav1.APIResourceList{
    {
        GroupVersion: "v1",
        APIResources: []metav1.APIResource{
            {
                Name: "pods", # 资源不存在资源组时
                Namespaced: true,
                Kind: "Pod",
                Verbs: []string{"get", "list", "delete", "deletecollection", "create", "update", "patch", "watch"},
            },
            {
                Name: "services",
                Namespaced: true,
                Kind: "Service",
                Verbs: []string{"get", "list", "delete", "deletecollection", "create", "update", "patch", "watch"},
            },
        },
    },
    {
        GroupVersion: "apps/v1", # 同时存在资源组和版本
        APIResources: []metav1.APIResource{
            {
                Name: "deployments",
                Namespaced: true,
                Kind: "Deployment",
                Verbs: []string{"get", "list", "delete", "deletecollection", "create", "update", "patch", "watch"},
            },
        },
    }
}

可以通过 Group、Version、Resource 结构来明确标识一个资源的资源组名称,资源版本及资源名称。简称 GVR。
常见的资源结构如下: GVR, GV, GR, GVK, GV, GK, GVS。

Group

type APIGroup struct {
    Name string
    // 资源组名称
    Versions []GroupVersionForDiscovery
    // 资源组下所支持的资源组版本
    PreferredVersion GroupVersionForDiscovery
    // 首选版本
}
  • 拥有组名的资源组:其表现形式为 //

    拥有组名的资源组的 HTTP PATH 以 /apis 为前缀,其表现形式为 /apis///

  • 没有组名的资源组:被称为 Core Groups(即核心资源组)或 Legacy Groups,也可能被称为 GroupLess (即无组),其表现形式为 /

    没有组名的资源组的 HTTP PATH 以 /api 为前缀,其表现形式为 /api//

Version

分为三种版本,依次迭代顺序为 Alpha -> Beta -> Stable

type APIVersions struct {
    Versions []string
}
// Versions: 所支持的资源版本列表

Resource

一个资源被实例化后会表达为一个资源对象(即 Resource Object),所有资源对象都是 Entity(实体)。

Kubernetes 目前支持的两种实体:

  • 持久性实体(Persistent Entity):在资源对象被创建够, Kubernetes 会持久确保该资源对象存在。大部分对象属于持久性实体,例如 Deployment 资源对象。
  • 短暂性实体(Ephemeral Entity):在资源对象被创建后,如果出现故障或调度失败,不会重新创建该资源对象,例如 Pod 资源对象。
type APIResource struct {
    Name string
    // 资源名称
    SingularName string
    // 资源的单数名称,它必须由小写字母组成,默认使用资源种类的小写形式进行命名。
    Namespaced bool
    // 资源是否拥有所属命名空间
    Group string
    Version string
    Kind string
    Verbs Verbs
    ShortNames []string
    // 资源的简称
}

资源外部版本和内部版本

  • External Object: 外部版本用于对外暴露给用户请求的接口所使用的资源对象,用户通过 YAML/JSON 格式的描述文件创建资源对象时,所使用的是外部版本的资源对象,外部版本的资源对象通过资源版本(Alpha, Beta, Stable)进行标识。

  • Internal Object: 内部版本不对外暴露,仅在 kubernetes api server 内部使用,内部版本用于多资源版本的转换。内部版本资源对象通过 runtime.APIVersionInternal (即_internal)进行标识。

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

  • 资源的外部版本和内部版本是需要相互转换的,而用于转换的函数需要事先初始化到资源注册表(Scheme)中,多个外部版本之间的资源进行相互转换,都需要通过内部版本进行中转。这也是 Kubernetes 能实现多资源版本转换的关键

  • 资源的外部版本和内部版本的代码定义也不太一样,外部版本的资源需要对外暴露给用户请求的接口,所以资源代码定义了 JSON/Proto Tags,而内部版本的资源不对外暴露,所以没有任何 Tags 定义。

资源代码定义

Kubernetes 内部版本和外部版本的资源代码结构并不相同。

  • 资源的内部版本定义了所支持的资源类型(types.go)、资源验证方法(validation.go)、资源注册至资源注册表的方法(install/install.go)等。
  • 资源的外部版本定义了资源的转换方法(conversion.go)、资源的默认值(defaults.go)等。
  • 外部版本与内部版本资源类型相同,都通过 register.go 代码文件定义所属的资源组和资源版本,外部版本资源对象通过资源版本(Alpha、Beta、Stable)标识。

将资源注册到资源注册表中

在每一个 Kubernetes 资源组目录中,都拥有一个 install/install.go 代码文件,它负责将资源信息注册到资源注册表(Scheme)中。

  • legancyschema.Scheme 是 kube-apiserver 组件的全局资源注册表,kubernetes 的所有资源信息都交给资源注册表统一管理。

  • core.AddToScheme: 函数注册 core 资源组内部版本的资源。

  • v1.AddToScheme: 函数注册 core 资源组外部版本的资源。

  • scheme.SetVersionPriority: 函数注册资源组的版本顺序,如有多个资源版本,排在最前面的为资源首选版本。

资源操作方法

在 kubernetes 系统中,针对每一个资源都有一定的操作方法(即 Verbs)。

  • 目前支持8中操作:create, delete, deletecollection, get, list, patch, update, watch,这些操作可以分为四大类,分别属于对资源进行创建、删除、更新和查询。

  • 要了解一个资源对象拥有哪些可操作的方法,需要查看与存储相关联的源码包 registry。

资源与命名空间

kubernetes 系统中默认内置了4个命名空间,分别如下:

  • default: 默认的命名空间
  • kube-system: 所有由 kubernetes 系统创建的资源对象都会被分配给该命名空间
  • kube-public: 此命名空间下的资源对象可以被所有人访问
  • kube-node-lease: 此命名空间下存放来自节点的心跳记录
  • 决定资源对象属于哪个命名空间,可通过资源对象的 ObjectMeta.Namespace 描述。

自定义资源

开发者通过 CustomResourceDefinitions(CRD)可以实现自定义资源,并将之添加到 Kubernetes 系统中。

kubernetes 资源可分为内置资源和自定义资源,它们都通过资源对象描述文件(Manifest File)进行定义。一个资源对象需要用5个字段来描述,这些字段定义在 YAML 或 JSON 文件中。

  • apiVersion: 指定创建资源对象的资源组和资源版本
  • kind: 指定创建资源对象的种类
  • metadata: 描述创建资源对象的元数据信息,例如名称、命名空间等。
  • spec: 包含有关资源对象的核心信息,包括资源状态、副本数量、环境变量、卷等信息。
  • status: 包含有关正在运行的资源对象的信息。

runtime.Object 类型基石

kubernetes 上的所有资源对象实际上就是一种 Go 语言的 Struct 类型,相当于一种数据结构,它们都有一个共同的结构叫 runtime.Object。runtime.Object 被设计为 Interface 接口类型,作为资源对象的通用资源对象。

例如: Pod 资源对象可以转换为 runtime.Object 通用资源对象,runtime.Object 通用资源对象也可以转换为 Pod 资源对象。

  • runtime.object 提供了两个方法,分别是 GetObjectKind 和 DeepCopyObject。
  1. GetObjectKind: 设置并返回 GroupVersionKind
  2. DeepCopyObject: 用于深复制当前资源对象并返回
  • Kubernetes 的每一个资源对象都嵌入了 metav1.TypeMeta 类型,该类型实现了 GetObjectKind 方法

    func main(){
      pod := &core.Pod{
          TypeMeta: metav1.TypeMeta{
              Kind: "Pod",
          },
          ObjectMeta: metav1.ObjectMeta{
              Labels: map[string]string{"name": "foo"}
          },
      }
      // 首先实例化 pod 资源
    
       obj := runtime.Object(pod)
       // 通过 runtime.Object 将 Pod 资源对象转换成通用资源对象
    
       pod2, ok := obj.(*core.Pod)
       // 通过断言的方式,将 obj 通用资源转换成 Pod 资源对象
       if !ok {
           panic("unexpected")
       }
    
       if !reflect.DeepEqual(pod, pod2) {
           panic("unexpected")
       }
       // 最终通过反射来验证转换前和转换后的资源对象是否相等
    }

文章作者: MJ-CJM
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 MJ-CJM !
评论
  目录