Kubernetes 核心数据结构(1)
参考书籍:《Kubernetes源码剖析-郑旭东著》
K8s 是一个完全以资源为中心的系统
Group、Version、Resource 核心数据结构
Kuberetes 系统虽然有相当复杂和众多的 功能,但它本质 上是一个资源控制系统——注册、管理、调度资源 并维护资源的状态。
Kuberetes 将资源再次分组和版本化,形成 Group(资源组)、Version(资源版本)、Resource(资源)
- Group: 被称为资源组,在Kubernetes API Server 中也可称其为 APIGroup。
- Version: 被称为资源版本,在Kubernetes API Server 中也可称其为 APIVersions。
- Resource: 被称为资源,在Kubernetes API Server 中也可称其为 APIResource。
- Kind: 资源种类,描述 Resource 的种类,与 Resource 为同一级别。
Kubernetes 系统支持多个Group,每个Group 支持多个Version,每个Version 支 持多个Resource,其中部分资源同时会拥有自己的子资源(即SubResource )。例如, Deployment资源拥有Status 子资源。
资源组、资源版本、资源、子资源的完整表现形式<group>/<version>/<resource>/ <subresource>
。以常用的 Deployment 资源为例,其完整表现形式为apps/v1/deployments/status
另外资源对象(Resource Object )在本书中也是 一个常用概念,由“ 资源组+ 资源版本+资源种类” 组成,并在实例化后表达一个资源对象,例如 Deployment 资源实例化后拥有资源组、资源版本及资源种类,其表现形式为<group>/<version>, Kind=<kind>
,例如apps/v1, Kind=Deployment
.
每一个资源都拥有一定数量的资源操作方法(即 Verbs ),资源操作方法用于 Etcd 集群存储中对资源对象的增、删、改、查操作。目前 Kubemetes 系统支持8 种资源操作方法,分别是 create、delete、delete、collection、get、list、patch、update、watch 操作方法。
每一个资源都至少有两个版本,分别是外部版本(External Version)和内部版本 ( Internal Version )。外部版本用于对外暴露给用户请求的接又所使用的资源对象。内部版本不对外暴露,仅在Kubernetes API Server 内部使用。
Kubernetes 资源也可分为两种, 分别是Kubernetes Resource (Kubermetes 内罝资源 ) 和 Custom Resource( 自 定 义 资 源 )。 开 发 者 通 过 C R D ( 即 Custom Resource Definitions )可实现自定义资源,它允许用户将自己定义的资源添加到 Kubernetes 系统中,并像使用 Kubernetes 内置资源 一样使用它们。
ResourceList
Kubernetes Group、 Version、Resource 等核心数据结构存放在staging/src/k8s.io/apimachinery/pkg/apis/meta/v1
目录中。它包含了Kubernetes
集群中所有组件使用的通 用核心数据结构,例如APIGroup、APIVersions、APIResource 等。其
中,我们可以 通过 APIResourceList 数据结构描述所有Group、Version、Resource 的结构。
|
|
Kubernetes的每个资源可使用metav1.APIResource
结构进行描述,它描述资源的基本信息,例如资源名称 (即 Name 字段)、资源所属的命名空间(即 Namespaced 字段)、资源种类(即 Kind 字段)、资源可操作的方法列表(即 Verbs 字段)。
每一个资源都属于一个或多个资源版本, 资源所属的版本通过 metavl.APIVersions
结构描述,一个或多个资源版本通过Versions []string
字符串数组进行存储。
Group
Group ( 资源组),在Kubernetes API Server 中也可称其为 APIGroup。Kubernetes 系统中定义了许多资源组,这些资源组按照不同功能将资源进行了划分,资源组特点如下。
- 将众多资源按照功能划分成不同的资源组,并允许单独启用/ 禁用资源组。 当然也可以单独启用/禁用资源组中的资源。
- 支持不同资源组中拥有不同的资源版本。这方便组内的资源根据版本进行迭代升级。
- 支持同名的资源种类 (即 Kind ) 存在于不同的资源组内 。
- 资源组与资源版本通过 Kubernetes API Server 对外暴露,允许开发者通过 HTTP 协议进行交互并通过动态客户端( 即 DynamicClient )进行资源发现。
- 支持CRD 自定 义资源扩展。
- 用户交互简单,例如在使用kubectl 命令行工具时,可以不填写资源组名称
|
|
在当前的Kubernetes 系统中,支持两类资源组,分别是拥有组名的资源组和没有组名的资源组。
拥有组名的资源组: 其表现形式为
<group>/<version>/<resource>
,例如apps/v1/deployments
没有组名的资源组: 被称为 Core Groups ( 即核心资源组)或 Legacy Groups , 也可被称为 Group Less ( 即无组 )。 其表现形式为
/<version>/<resource>
, 例 如/v1/pods
两类资源组表现形式不同, 形成的 HTTP PATH 路径也不同。 拥有组名的资源组的 HTTP PATH 以
/apis
为前缀,其表现形式为/apis/<group>/<version>/<resource>
,例如http://localhost:8080/apis/apps/v1/deployments
。没有组名的资源组的 HTTP PATH 以api
为前缀,其表现形式为/api/<version>/<resource>
,例如http://localhost:8080/api/vl/pods
.
Version
Kubernetes 的资源版本控制可分为了种,分别是 Alpha、Beta、Stable,它们之间的迭代顺序为Alpha -> Beta -> Stable
,其通常用来表示软件测试过程中的 了个阶段。 Alpha是第1个阶段,一般用于内部测试; Beta 是第2 个阶段,该版本已经修复了大 部分不完善之处,但仍有可能存在缺陷和漏洞, 一般由特定的用户群来进行测试; Stable 是第了个阶段,此时基本形成了产品并达到了一定的成熟度,可稳定运行。 Kubernetes 资源版本控制详情如下:
- Alpha 版本
Alpha 版本为内部测试版本,用于Kubernetes 开发者内部测试,该版本是不稳定的,可能存在很多缺陷和漏洞,官方随时可能会放弃支持该版本。在默认的情况下, 处于Alpha 版本的功能会被禁用。Alpha 版本名称一般为 vlalphal、vlalpha2、v2alphal 等。
- Beta 版本
Beta 版本为相对稳定的版本, Beta 版本经过官方和社区很多次测试 , 当功能迭代时,该版本会有较小的改变,但不会被删除。在默认的情况下,处于Beta 版本的功能是开启状态的。Beta 版本命名一般为 v1betal、v1beta2、v2betal。
- Stable 版本
Stable 版本为正式发布的版本, Stable 版本基本形成了产品 ,该版本不会被删除。 在默认的情况下 ,处于 stable 版本的功能全部处于开启状态 。Stable 版本命名一般为 v1、v2、 v3。
|
|
CIDR(Classless Inter-Domain Routing)是一个用于给用户分配IP地址以及在互联网上有效地路由IP数据包的对IP地址进行归类的方法。与传统的A类、B类和C类寻址模式相比,CIDR在IP地址分配方面更为高效。CIDR采用斜线记法,表示为:IP地址/网络ID的位数。
示例一:CIDR格式换算为IP地址网段
例如10.0.0.0/8,换算为32位二进制地址:00001010.00000000.00000000.00000000。其中/8表示8位网络ID,即32位二进制地址中前8位是固定不变的,对应网段为:00001010.00000000.00000000.00000000
00001010.11111111.11111111.11111111。则换算为十进制后,10.0.0.0/8表示:子网掩码为255.0.0.0,对应网段为10.0.0.010.255.255.255。示例二:IP地址网段换算为CIDR格式
例如192.168.0.0
192.168.31.255,后两段IP换算为二进制地址:00000000.0000000000011111.11111111,可以得出前19位(8*2+3)是固定不变的,则换算为CIDR格式后,表示为:192.168.0.0/19
Resource
一 个资源被实例化后会表达为一 个资源对象(即Resource Object )。在 Kuberetes 系统中定义并运行着各式各样的资源对象,Kubernetes 资源对象如图所示。所有资源对象都是 Entity 。 Entity 翻译成中 文为 “ 实 体” ,Kubernetes 使用这些 Entity 来表示当前状态。可以通过 Kubernetes API Server 进行查询和更新每一个资源对象。 Kubernetes 目前支持两种 Entity,分别介绍如下
持久性实体(Persistent Entity): 在资源对象被创建后,Kubernetes 会持久确保该资源对象存在。大部分资源对象属于持久性实体,例如 Deployment 资源对象
短暂性实体(Ephemeral Entity): 也可称其为非持久性实体(Non-Persistent Entity ) 。 在资源对象被创建后,如果出现故障或调度失败 ,不会重新创建该资源对象,例如 Pod 资源对象
|
|
资源外部版本与内部版本
Kubernetes 资源代码定义在 pkg/apis
目录下, 在详解资源代码定义之前, 先来了解一下资源的外部版本(ExternalVersion )与内部版本(Internal Version )。在 Kubernetes 系统中,同 一资源对应着两个版本,分别是外部版本和内部版本。例如,Deployment 资源,它所属的外部版本表现形式为apps/ v1
,内部版本表现形式为apps/_internal
'
ExternalObject: 外部版本资源对象,也称为 Versioned Object ( 即拥有资源版本的资源对象)。外部版本用于对外暴露给用户请求的接又所使用的资源对象,例如,用户在通过 YAML 或 JSON 格式的描述文件创建资源对象时,所使用的是外部版本的资源对象。外部版本的资源对象通过资源版本( Alpha 、Beta 、Stable )进行标识
Internal Object: 内部版本资源对象。内部版本不对外暴露,仅在 Kubernetes API Server 内部使用。内部版本用于多资源版本的转换,例如将 v1betal 版本转换为 v1 版本,其过程为
v1betal--internal - v1
,即先将 v1betal 转换为内部版本(internal ),再由内部版本(internal)转换为V1版本。内部版本资源对象通过runtime. APIVersionlnternal
(即 internal )进行标识。资源的外部版本代码定义在
pkg/apis/<group>/<version>/
目录下,资源的内部版本代码定义在pkg/apis/<group>/
日 录 下。 例 如 , Deployment 资源 ,它的外部版本定义在pkg/apis/apps/{v1,V1betal, v1beta2}/
目录下, 它的内部版本定义在pkg/apis/apps/
目录下(内部版本一般与资源组在同一级目录下)。资源的外部版本与内部版本如图所示。
资源的外部版本和内部版本是需要相互转换的,而用于转换的函数需要事先初始化到资源注册表 (Scheme) 中 。 多个外部版本 ( External Version ) 之间的资源进行相互转换,都需要通过内部版本 (Internal Version )进行中转。这也是Kubernetes 能实现多资源版本转换的关键.
资源的外部版本与内部版本的代码定义也不太一样,外部版本的资源需要对外暴露给用户请求的接又,所以资源代码定义了 JSONTags
和 Proto Tags
,用于请求的序列化和反序列化操作。内部版本的资源不对外暴露,所以没有任何的 JSON Tags 和ProtoTags定义。以Pod 资源代码定义为例,代码示例如下
|
|
|
|
资源代码定义
Kubernetes资源代码定义在pkg/apis
目录下,同一资源对应着内部版本和外部版本,内部版本和外部版本的资源代码结构并不相同。
资源的内部版本定义了所支持的资源类型 ( types.go)、资源验证方法( validation.go )、资源注册至资源注册表的方法 ( install/install.go) 等 。 而资源的外部版本定义了资源的转换方法 (conversion.go )、资源的默认值 (defaults.go) 等。
以 Deployment 资源为例,它的内部版本定义在 pkg/apis/apps/
目录下,其资源代码结构为
|
|
- doc.go: GoDoc 文件,定义了当前包的注释信息。在 Kubernetes 资源包中, 它还担当了代码生成器的全局 Tags 描述文件
- register. go : 定义了资源组、资源版本及资源的注册信息 。
- types.go: 定义了在当前资源组、资源版本下所支持的资源类型。
- v1、v1betal 、v1beta2 : 定义了资源组下拥有的资源版本的资源 (即外部版本)。
- install : 把当前资源组下的所有资源注册到资源注册表中。
- validation: 定义了资源的验证方法。
- zz_generated.deepcopy-go: 定义了资源的深复制操作,该文件由代码生成器自动生成
每一个 Kubernetes 资源目录,都通过 register.go 代码文件定义所属的资源组和资源版本,内部版本资源对象通过runtime.APIVersionInternal
(即 _internal ) 标识 ,代码示例如下:
|
|
以 Deployment 资源为例,它的外部版本定义在 pkg/apis/apps/{vl,v1betal, v1beta2 }
目录下,其资源代码结构如下:
|
|
conversion.go
: 定义了资源的转换函数 (默认转换函数 ),并将默认转换函数注册到资源注册表中。zz_generated.conversion.go
: 定义了资源的转换西数(自动生成的转换函 数),并将生成的转换两数注册到资源注册表中。该文件由代码生成器自 动生成。defaults.go
: 定义了资源的默认值函 数 ,并将默认值函数注册到资源注册表中zz_generated.defaults.go
: 定义了资源的默认值函数(自动生成的默认值函数 ),并将生成的默认值两数注册到资源注册表中。该文件由代码生成器自动生成
外部版本与内部版本资源类型相同,都通过 register.go
代码文件定义所属的资源组和资源版本,外部版本资源对象通过资源版本( Alpha、Beta、Stable)标识,代码
示例如下
|
|
将资源注册到资源注册表中
在每一个Kubernetes资源组目录中,都拥有一个instal/install.go
代码文件,它负责将资源信息注册到资源注册表(Scheme)中。以 core 核心资源组为例,代码示例如下:
|
|
legacyscheme.Scheme
是kube-apiserver
组件的全局资源注册表,Kubernetes 的所有资源信息都交给资源注册表统一管理。core. AddToScheme
函数注册core
资源组内部版本的资源。v1.AddToScheme
函数注册 core
资源组外部版本的资源。 scheme.SetVersionPriority
两数注册资源组的版本顺序,如有多个资源版本,排在最前面的为资源首选版本。
资源首选版本
首选版本( Preferred Version ),也称优选版本( Priority Version),一个资源组下拥有多个资源版本,例如,apps资源组拥有v1、v1betal、v1beta2 等资源版本。当我们使用 apps 资源组下的Deployment 资源时,在一些场景下,如不指定资源版本,则使用该资源的首选版本。
以apps 资源组为例,注册资源时会注册多个资源版本,分别是v1、v1beta2、 v1betal ,代码示例如下:
|
|
scheme.SetVersionPriority
注册版本顺序很重要,apps 资源组的注册版本顺序为 v1 、v1beta2 、v1betal ,那么在资源注册表的 version Priority
结构中 ,资源的首选版本
|
|
资源操作方法
在 Kubernetes 系统中 ,针对每一个资源都有一定的操作方法 ( 即 Verbs ),例如 ,对于 Pod 资源对象,可以通过kubectl 命令行工具对其执行 create、delete、get 等操 作。Kubernetes 系统所支持的操作方法目前有8 种操作,分别是 create、delete、 deletecollection、get、list、patch、update、watch。这些操作方法可分为四大类,分别属于增、删、改、查,对资源进行创建、删除、更新和查询。资源操作方法如图
资源操作方法可以通过metav1.Verbs
数据结构进行描述,代码示例如下:
|
|
不同资源拥有不同的操作方法,例如,针对 Pod 资源对象与 pod logs 子资源对象,Pod 资源对象拥有create、delete、deletecollection、get、list、patch、update、watch 等操作方法,pod/logs 子资源对象只拥有get操作方法,因为日志只需要执行查看操作。Pod 资源对象与pod/ logs 子资源对象的操作方法分别通过 metav1. Verbs 进行描述。
资源对象的操作方法与存储 (Storage )相关联,增、删、改、查实际上都是针对存储的操作。如何解 一个资源对象拥有哪些可操作的方法呢 ?
需要查看与存储相关联的源码包 registry
,其定义在 vendor/k8s.io/apiserver/pkg/registry/
目录下。 每种操作方法对应一个操作方法接又 (Interface),资源对象操作方法接口说明:
资源与命名空间
Kubernetes 系统支持命名空间(Namespace),其用来解決Kubernetes 集群中资源对象过多导致管理复杂的问题 。 每个命名空间相当于一个 “ 虚 拟 集 群 ” ,不同命名空间之间可以进行隔离,当然也可以通过某种方式跨命名空间通信。
Kubernetes 系统中默认内置了4个命名空间 ,分别介绍如下。
default: 所有未指定命名空间的资源对象都会被分配给该命名空间
kube-system: 所有由 Kubernetes 系统创建的资源对象都会被分配给该命名空间
kube-public: 此命名空间下的资源对象可以被所有人访问 (包括未认证用户)
kube-node-lease: 此命名空间下存放来自节点的心跳记录(节点租约信息)
通过运行
kubectl get namespace
命令查看Kubernetes
系统上所有的命名空间信息 。另外,在Kubernetes 系统中,大部分资源对象都存在于某些命名空间中(例如Pod 资源对象)。但并不是所有的资源对象都存在于某个命名空间中(例如 Node 资源对象)。决定资源对象属于哪个命名空间,可通过资源对象的ObjectMeta.Namespace
描述
自定义资源
Kubenetes 系统拥有强大的高扩展功能 ,其中自定义资源 (CustomResource ) 就是一种常见的扩展方式,即可将自己定义的资源添加到 Kubemetes 系统中。Kubernetes 系统附带了许多内置资源,但是仍有些需求需要使用自定义资源来扩展 Kubernetes 的功能。
开发者通过 CRD 可以实现自定义资源,它允许用户将自己定义的资源添加到 Kubernetes 系统中,并像使用 Kubernetes 内置资源一样使用 这些资源,例如,在 YAML/JSON 文件中带有 Spec 的资源定义都是对 Kubernetes 中的资源对象的定义,所有的自定义资源都可以与 Kubernetes 系统中的内置资源一样使用 kubectl 或 client- go 进行操作
资源对象描述文件定义
Kubernetes 资源可分为内置资源(Kubernetes Resources )和自定义资源(Custom Resources),它们都通过资源对象描述文件(Manifest File)进行定义,资源对象描述文件如图
一个资源对象需要用5 个字段来描述它分别是Group/Version、KindMetaData、 Spec、Status。这些字段定义在YAML或JSON 文件中。Kubernetes系统中的所有的 资源对象都可以采用YAML或JSON格式的描述文件来定义,下面是某个Pod 文件的资源对象描述文件 。 YAML Manifest File Example 代码示例如下:
|
|
- apiversion: 指定创建资源对象的资源组和资源版本, 其表现形式为
<group>/<version>
, 若是core
资源组 (即核心资源组 ) 下的资源对象 ,其表现形式为<version>
- kind: 指定创建资源对象的种类
- metadata: 描述创建资源对象的元数据信息,例如名称、命名空间等
- spee: 包含有关Deployment 资源对象的核心信息,告诉Kubernetes 期望的资源状态、副本数量、环境变量、 卷等信息
- status: 包含有关正在运行的 Deployment 资源对象的信息
每一个Kubernetes 资源对象都包含两个嵌套字段,即 spec 字段和 status 字段。 其中spec 字段是必需的,它描述了资源对象的“期望状态”(DesiredState),而status 字段用于描述资源对象的“ 实际状态” (Actual State) ,它是由Kubernetes 系统提供 和更新的。在任何时刻,Kubernetes控制器一直努力地管理着对象的实际状态以与期望状态相匹配。