核心数据结构
在整个 Kubernetes 体系架构中,资源是 Kubernetes 最重要的概念,可以说 Kubernetes 的生态系统都围绕着资源运作。Kubernetes 系统虽然有相当复杂和众多的功能,但它本质上是一个资源控制系统——注册、管理、调度资源并维护资源的状态。
1、GVR 概念
在 kubernetes 庞大的资源系统中,单用资源的概念远远不够,因此将资源再次分组和版本化,形成 Group(资源组)、Version(资源版本)、Resource(资源)等概念。
Group:被称为资源组,可称其为 APIGroup。
Version:被称为资源版本,也可称其为 APIVersions。
Resource:被称为资源,也可称其为APIResource。
Kind:资源种类,描述 Resource 的种类,与 Resource 为同一级别。

Kubernetes 的每个资源可使用 metav1.APIResource 结构进行描述,它描述资源的基本信息,例如资源名称(Name)、资源所属的命名空间(Namespaced)、资源种类(Kind)、资源可操作的方法列表(Verbs),资源版本通过 metav1.APIVersions 来描述。
2、Group
Kubernetes 系统中定义了许多资源组,这些资源组按照不同功能将资源进行了划分,资源组特点如下:
将众多资源按照功能划分成不同的资源组,并允许单独启用/禁用资源组;
支持资源组中拥有不同的资源版本,便于资源的版本升级;
支持同名的资源种类存在于不同的资源组内;
资源组与资源版本通过 API Server 对外暴露,允许开发者进行资源发现;
支持CRD自定义资源扩展;
其在代码中的定义表示为:
type APIGroup struct {
TypeMeta
Name string // 资源组名称
Versions []GroupVersionForDiscovery // 资源组支持版本
PreferredVersion GroupVersionForDiscovery // 资源组优先版本
ServerAddressByClientCIDRs []ServerAddressByClientCIDR
}在实际过程中会发现一些 没有组名的资源组,被称为 Core Groups(即核心资源组)或 Legacy Groups,也可被称为GroupLess(即无组)。其表现形式为 /<version>/<resource>,例如 /v1/pods 的资源路径。并且其和拥有组名的资源组在形成路径上面也略有不同,拥有组名的以 /apis 开始,而没有组名的以 /api 开始。
3、Version
Kubernetes 的资源版本控制可分为3种,分别是 Alpha、Beta、Stable,它们之间的迭代顺序为由前至后,其通常用来表示软件测试过程的三个阶段。
Alpha 是第1个阶段,一般用于内部测试,随时可能被官方进行废弃不再支持,例如 v1alpha2、v2alpha1;
Beta 是第2个阶段,该版本已经修复了大部分不完善之处,但仍有可能存在缺陷和漏洞,在迭代中会有稍微改动,例如 v1beta2、v2beta1;
Stable 是第3个阶段,此时基本形成了产品并达到了一定的成熟度,可稳定运行,例如 v1、v2。
4、Resource
Kubernetes 系统虽然有相当复杂和众多的功能,但它本质上是一个资源控制系统——管理、调度资源并维护资源的状态。
一个资源被实例化后会表达为一个资源对象,在系统中目前支持两种资源对象:
持久性资源:在资源对象被创建后,Kubernetes 会持久确保该资源对象存在。大部分资源对象属于持久性实体,例如 Deployment 资源对象;
短暂性资源:也可称其为非持久性资源,在资源对象被创建后,如果出现故障或调度失败,不会重新创建该资源对象,例如 Pod 资源对象。
type APIResource struct {
Name string // 资源名称
SingularName string // 资源的单数名称,它必须由小写字母组成,默认使用资源种类(Kind)的小写形式进行命名。例如,Pod资源的单数名称为pod,复数名称为pods
Namespaced bool // 资源是否拥有命名空间
Group string // 资源组名称
Version string // 资源组版本
Kind string // 资源类型
Verbs Verbs // 资源操作列表
ShortNames []string // 资源简称
Categories []string
StorageVersionHash string
}4.1 资源外部版本与内部版本
在 Kubernetes 系统中,同一资源对应着两个版本,分别是外部版本和内部版本。例如,Deployment 资源,它所属的外部版本表现形式为 apps/v1,内部版本(内部版本一般与资源组在同一级目录下)表现形式为 apps/__internal。
外部版本资源对象:也称为 Versioned Object。外部版本用于对外暴露给用户请求的接口所使用的资源对象,例如,用户在通过YAML或JSON格式的描述文件创建资源对象时,所使用的是外部版本的资源对象。
内部版本资源对象:内部版本不对外暴露,仅在内部使用。内部版本用于多资源版本的转换,例如将 v1beta1 版本转换为 v1 版本,其过程为 v1beta1→internal→v1。
资源版本与外部版本、内部版本概念不同。拥有资源版本的资源属于外部版本,拥有 runtime.APIVersionInternal 标识的资源属于内部版本。
资源的内部版本定义了所支持的资源类型(types.go)、资源验证方法(validation.go)、资源注册至资源注册表的方法(install/install.go)等。而资源的外部版本定义了资源的转换方法(conversion.go)、资源的默认值(defaults.go)等。
4.2 资源注册
在每一个 Kubernetes 资源组目录中,都拥有一个 install/install.go 代码文件,它负责将资源信息注册到资源注册表(Scheme)中。
func init() {
Install(legacyscheme.Scheme)
}
// Install registers the API group and adds types to a scheme
func Install(scheme *runtime.Scheme) {
utilruntime.Must(core.AddToScheme(scheme))
utilruntime.Must(v1.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion))
}legacyscheme.Scheme 是 kube-apiserver 组件的全局资源注册表,而 Kubernetes 的所有资源信息都交给资源注册表统一管理。
core.AddToScheme 函数注册 core 资源组内部版本的资源;
v1.AddToScheme 函数注册core资源组外部版本的资源;
scheme.SetVersionPriority 函数注册资源组的版本顺序,多个资源版本之间最前面的为资源首选版本。
4.3 资源首选版本
上面提到组可以拥有很多个版本,在明确指定了使用哪个版本的资源时则使用具体版本,否则会使用优选版本。
在 scheme.PreferredVersionAllGroups 方法中则是直接遍历版本,选择第一个版本。除此之外,还有其他两个方法用于版本获取,scheme.PrioritizedVersionsForGroup1 取指定资源组的资源版本,按照优先顺序返回;scheme.PrioritizedVersionsAllGroups 获取所有资源组的资源版本,按照优先顺序返回。
4.4 资源操作方法
Kubernetes 系统所支持的操作方法目前有 8 种操作,分别是 create、delete、deletecollection、get、list、patch、update、watch,符合 RESTFUL 接口的定义,可以划分为增删改查四类操作。
资源对象的操作方法与存储(Storage)相关联,增、删、改、查实际上都是针对存储的操作。通过查看与存储相关联的源码包 vendor/k8s.io/apiserver/pkg/registry/,每种操作方法对应一个操作方法接口(Interface)。以 get 操作为例,其是一个接口, 如果某个资源对象(pod)在存储上实现了 Get,就可以认为该资源对象拥有了 get 操作方法。
// Getter is an object that can retrieve a named RESTful resource.
type Getter interface {
// Get finds a resource in the storage by name and returns it.
// Although it can return an arbitrary error value, IsNotFound(err) is true for the
// returned error value err when the specified resource is not found.
Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error)
}
func (e *Store) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
obj := e.NewFunc()
key, err := e.KeyFunc(ctx, name)
if err != nil {
return nil, err
}
if err := e.Storage.Get(ctx, key, storage.GetOptions{ResourceVersion: options.ResourceVersion}, obj); err != nil {
return nil, storeerr.InterpretGetError(err, e.qualifiedResourceFromContext(ctx), name)
}
if e.Decorator != nil {
e.Decorator(obj)
}
return obj, nil
}4.5 命名空间
系统支持命名空间(Namespace),用来解决集群中资源对象过多导致管理复杂的问题,其中每个命名空间相当于一个"虚拟集群",不同命名空间之间可以进行隔离,也可以通过某种方式跨命名空间通信。
Kubernetes 系统中默认内置了4个命名空间:
default:所有未指定命名空间的资源对象都会被分配给该命名空间;
kube-system:所有由 Kubernetes 系统创建的资源对象都会被分配给该命名空间;
kube-public:此命名空间下的资源对象可以被所有人访问(包括未认证用户);
kube-node-lease:此命名空间下存放来自节点的心跳记录(节点租约信息)。
4.6 自定义资源
Kubernetes 系统附带了许多内置资源,但是仍有些需求需要使用自定义资源(custom resource)来扩展 Kubernetes 的功能。在系统早期,是通过 ThirdPartyResource(TPR)来实现扩展,但自 Kubernetes 1.7 版本后,取而代之的是CustomResourceDefinitions(自定义资源定义,CRD)。
通过 CRD 可以实现自定义资源,它允许用户将自己定义的资源添加到 Kubernetes 系统中,并像使用 Kubernetes 内置资源一样使用这些资源,而通过一个 operator 控制器来对自定义资源进行控制操作。
- 感谢你赐予我前进的力量