k8s概念之GVK与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博客

Kubernetes CRD 系列:Api Server 和 GVK(R)

https://blog.csdn.net/qq_24433609/category_11359650.html

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 controller-runtime 库中,可以使用 Client 接口的 List 方法来列出指定类型的资源。以下是一个具体的示例: ```go package main import ( "context" "fmt" "os" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" ) func main() { // 获取 Kubernetes 配置 kubeconfig := config.GetConfigOrDie() // 通过 Kubernetes 配置创建 clientset clientset, err := kubernetes.NewForConfig(kubeconfig) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create clientset: %v\n", err) os.Exit(1) } // 通过 Kubernetes 配置创建 client client, err := client.New(kubeconfig, client.Options{}) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create client: %v\n", err) os.Exit(1) } // 定义要列出的资源类型和命名空间 namespace := "default" gvk := schema.GroupVersionKind{Version: "v1", Kind: "Pod"} // 创建一个对象列表来存储结果 objectList := &corev1.PodList{} // 使用 client 的 List 方法列出指定类型的资源 err = client.List(context.Background(), objectList, &client.ListOptions{ Namespace: namespace, Raw: &metav1.ListOptions{}, ResourceVersion: "", }) if err != nil { if errors.IsNotFound(err) { fmt.Fprintf(os.Stderr, "Resource not found: %v\n", err) os.Exit(1) } else { fmt.Fprintf(os.Stderr, "Failed to list resources: %v\n", err) os.Exit(1) } } // 输出结果 fmt.Printf("Found %d pods in namespace %s:\n", len(objectList.Items), namespace) for _, obj := range objectList.Items { fmt.Printf(" %s\n", obj.Name) } } ``` 这个示例演示了如何使用 controller-runtime 库中的 Client 接口来列出指定命名空间中的 Pod 资源。你可以根据自己的需求修改示例代码中的参数来获取不同类型的资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值