k8s概念之GVK与GVR
gvk vs gvr
理解
GVK 和 GVR 是什么?
- GVK 就是 group、verison、kind
- GVR 就是 group、version、resource
GVK
Kind 是 API “顶级”资源对象的类型,每个资源对象都需要 Kind 来区分它自身代表的资源类型。其中 kind 字段即代表该资源对象的类型。一般来说,在 kubernetes API 中有三种不同的 Kind:
- 单个资源对象的类型,最典型的就是刚才例子中提到的 Pod
- 资源对象的列表类型,例如 PodList 以及 NodeList 等
- 特殊类型以及非持久化操作的类型,很多这种类型的资源是 subresource, 例如用于绑定资源的 /binding、更新资源状态的 /status 以及读写资源实例数量的 /scale
GVR
Resource 则是通过 HTTP 协议以 JSON 格式发送或者读取的资源展现形式,可以以单个资源对象展现,例如 .../namespaces/default,也可以以列表的形式展现,例如 .../jobs。要正确的请求资源对象,API-Server 必须知道 apiVersion 与请求的资源,这样 API-Server 才能正确地解码请求信息,这些信息正是处于请求的资源路径中。一般来说,把 API Group、API Version 以及 Resource 组合成为 GVR 可以区分特定的资源请求路径,例如 /apis/batch/v1/jobs 就是请求所有的 jobs 信息。
GVK vs GVR
其实,理解了 GVK 之后再理解 GVR 就很容易了,这就是面向对象编程里面的类和对象的概念是一样的:
好理解吧,Kind 其实就是一个类,用于描述对象的;而 Resource 就是具体的 Kind,可以理解成类已经实例化成对象了。
为什么有 kind 和 resouce 两个相似概念
首先我们要明确几个概念:
在编码过程中,资源数据的存储都是以结构体存储(称为 Go type)。由于多版本version的存在(alpha1,beta1,v1等),不同版本中存储结构体的存在着差异,但是我们都会给其相同的 Kind 名字(比如 Deployment)。因此,我们编码中只用 Kind 名(如 Deployment),并不能准确获取到其使用哪个版本结构体
所以,采用 GVK 获取到一个具体的 存储结构体,也就是 GVK 的三个信息(group/verion/kind) 确定一个 Go type(结构体)。
如何获取呢? —— 通过 Scheme, Scheme 存储了 GVK 和 Go type 的映射关系
在创建资源过程中,我们编写 yaml,提交请求:
编写 yaml 过程中,我们会写 apiversion 和 kind,其实就是 GVK。
而客户端(也就是我们)与 apiserver 通信是 http 形式,就是将请求发送到某一 http path;
发送到哪个 http path 呢?这个 http path 其实就是 GVR。
/apis/batch/v1/namespaces/default/job 这个就是表示 default 命名空间的 job 资源
我们 kubectl get po 时 也是请求的路径 也可以称之为 GVR。
其实 GVR 是由 GVK 转化而来 —— 通过REST映射的RESTMappers实现
总结
- 同 Kind 由于多版本会存在 多个数据结构(Go type)
- GVK 可以确定一个具体的 Go Type(映射关系由 Scheme 维护)
- GVK 可以转换 http path 请求路径(也就是 GVR)(映射由RESTMappers实现)
- GVK和GVR是相关的。GVK在GVR标识的HTTP路径下提供服务。将GVK映射到GVR的过程称为REST映射。我们将在“ REST Mapping”中看到在Golang中实现REST映射的RESTMappers。
API-group
将整个 kubernetes API 资源分成各个组,可以带来很多好处:
- 各组可以单独打开或者关闭[7]
- 各组可以有独立的版本,在不影响其他组的情况下单独向前衍化
- 同一个资源可以同时存在于多个不同组中,这样就可以同时支持某个特定资源稳定版本与实验版本
API 分组也体现在访问资源的 RESTful API 路径上,core 组中的资源访问路径一般为 /api/$VERSION,其他命名组的资源访问路径则是 /apis/$GROUP_NAME/$VERSION,此外还有一些系统级别的资源,如集群指标信息 /metrics,以上这些就基本构成了 kubernetes API 的树结构:
API-version
为了支持独立的演进,kubernetes API 也支持不同的版本,不同的版本代表不同的成熟度。注意,这里说的是 API 而非资源支持多版本。因为多版本支持是针对 API 级别,而不是特定的资源或者资源的字段。一般来说,我们根据 API 分组、资源类型、namespace 以及 name 来区分不同的资源对象,对于同一个资源对象的不同版本,API-Server 负责不同版本之间的无损切换,这点对于客户端来说是完全透明的(无感知)。事实上,不同版本的同类型的资源在持久化层的数据可能是相同的。例如,对于同一种资源类型支持 v1 和 v1beta1 两个 API 版本,以 v1beta1 版本创建该资源的对象,后续可以以v1 或者 v1beta1 来更新或者删除该资源对象。
API 多版本支持一般通过将资源分组置于不同的版本中来实现,例如,batch 同时存在 v2alph1 与 v1 版本。一般来说,新的资源分组先出现 v1alpha1 版本,随着稳定性的提高被推进到 v1beta1 ,最后从 v1 版本毕业。
随着新的用户场景出现,kubernetes API 需要不断变化,可能是新增一个字段,也可能是删除旧的字段,甚至是改变资源的展现形式。为了保证兼容性,kubernetes 制定了一系列的策略[8]。总的来说,对于已经 GA 的 API,API,kubernetes 严格维护其兼容性,终端用户可以放心食用,beta 版本的 API 则尽量维护,保证不打破版本跨版本之间的交互,而对于 alpha 版本的 API 则很难保证兼容性,不太推荐生产环境使用。
核心资源
如果想看系统支持哪些 GVK,那么可以通过 kubectl 的命令查看:
这里可能你会发现一些特别的地方,就是对于 Pod 和 Service,它的 API GROUP 居然是空的,这又是什么意思?这其实就是 Kubernetes 核心资源的含义,也就是所谓的 Kubernetes 中的基础资源(Kubernetes Resource),他们不需要 Group,只有 Version 和 Kind,其实,我认为这是历史原因导致的,在 Kubernetes 的开始之初还不支持自定义类型的时候就没考虑过 Group。
源码相关
gvk和go type的映射
详见k8s scheme的资源注册!文章待写。。。
RESTMapper
RESTMapper作为GVK到GVR的映射,通过 GVK 信息则可以获取要读取的资源对象的 GVR,进而构建 RESTful API 请求获取对应的资源。Kubernetes 定义了 RESTMapper 接口并带默认带有实现 DefaultRESTMapper。
RESTMapper作为GVK到GVR的映射,其主要作用是在ListerWatcher时, 根据Schema定义的类型GVK解析出GVR, 向apiserver发起http请求获取资源, 然后watch。
什么是RESTMapper。RESTMapper是一个interface,定义在/pkg/api/meta/interfaces.go中。关于RESTMapper的注释非常重要,“RESTMapper allows clients to map resources to kind, and map kind and version to interfaces for manipulating those objects”。也就是说,RESTMapper映射是指GVR(GroupVersionResource)和GVK(GroupVersionKind)的关系,可以通过GVR找到合适的GVK,并可以通过GVK生成一个RESTMapping。
restmapping
当我们要定义一个 GVR 的时候,那么怎么知道这个 GVR 是属于哪个 GVK 的呢?也就是前面说的,kubectl 是如何从 YAML 描述文件中知道该请求的是哪个 GVR URL?这就是 REST Mapping 的功能,REST Mapping 可以指定一个 GVR(例如 daemonset 的这个例子),然后它返回对应的 GVK 以及支持的操作等。
参考
【k8s基础篇】k8s基础2之GVK与GVR_oceanweave的博客-CSDN博客
更多推荐
所有评论(0)