Kubernetes系统使用client-go作为Go语言的官方编程式交互客户端库,提供对Kubernetes API Server服务的交互访问。Kubernetes的源码中已经集成了client-go的源码,无须单独下载。client-go源码路径为vendor/k8s.io/client-go。
开发者常使用client-go基于Kubernetes做二次开发,所以client-go是开发者应熟练掌握的必会技能。
client-go的代码库已经集成到Kubernetes源码中了,无须考虑版本兼容性问题,源码结构示例如下。
vendor/k8s.io/client-go
client-go源码目录结构说明:
client-go支持4种Client客户端对象与Kubernetes API Server交互的方式,Client交互对象如图所示。
RESTClient
是最基础的客户端。RESTClient对HTTP Request进行了封装,实现了RESTful风格的API。ClientSet、DynamicClient及DiscoveryClient客户端都是基于RESTClient实现的。
ClientSet
在RESTClient的基础上封装了对Resource和Version的管理方法。每一个Resource可以理解为一个客户端,而ClientSet则是多个客户端的集合,每一个Resource和Version都以函数的方式暴露给开发者。ClientSet只能够处理Kubernetes内置资源,它是通过client-gen代码生成器自动生成的。
DynamicClient
与ClientSet最大的不同之处是,ClientSet仅能访问Kubernetes自带的资源(即Client集合内的资源),不能直接访问CRD自定义资源。DynamicClient能够处理Kubernetes中的所有资源对象,包括Kubernetes内置资源与CRD自定义资源。
DiscoveryClient
发现客户端,用于发现kube-apiserver所支持的资源组、资源版本、资源信息(即Group、Versions、Resources)。
以上4种客户端:RESTClient、ClientSet、DynamicClient、DiscoveryClient都可以通过kubeconfig配置信息连接到指定的Kubernetes API Server,后面将详解它们的实现。
RESTClient是最基础的客户端。其他的ClientSet、DynamicClient及DiscoveryClient都是基于RESTClient实现的。RESTClient对HTTP Request进行了封装,实现了RESTful风格的API。它具有很高的灵活性,数据不依赖于方法和资源,因此RESTClient能够处理多种类型的调用,返回不同的数据格式。
类似于kubectl命令,通过RESTClient列出所有运行的Pod资源对象,RESTClient Example代码示例如下:
PS:完整代码可关注公众号,后台回复云原生,领取云原生实战大礼包,代码在其中(本文后续代码皆如此,只截图部分作为讲解)。
运行以上代码,列出default命名空间下的所有Pod资源对象的相关信息。首先加载kubeconfig配置信息,并设置config.APIPath请求的HTTP路径。然后设置config.GroupVersion请求的资源组/资源版本。最后设置config.NegotiatedSerializer数据的编解码器。
rest.RESTClientFor函数通过kubeconfig配置信息实例化RESTClient对象,RESTClient对象构建HTTP请求参数,例如Get函数设置请求方法为get操作,它还支持Post、Put、Delete、Patch等请求方法。Namespace函数设置请求的命名空间。Resource函数设置请求的资源名称。VersionedParams函数将一些查询选项(如limit、TimeoutSeconds等)添加到请求参数中。通过Do函数执行该请求,并将kube-apiserver返回的结果(Result对象)解析到corev1.PodList对象中。最终格式化输出结果。
RESTClient发送请求的过程对Go语言标准库net/http进行了封装,由Do→request函数实现。
RESTClient是一种最基础的客户端,使用时需要指定Resource和Version等信息,编写代码时需要提前知道Resource所在的Group和对应的Version信息。相比RESTClient,ClientSet使用起来更加便捷,一般情况下,开发者对Kubernetes进行二次开发时通常使用ClientSet。
ClientSet在RESTClient的基础上封装了对Resource和Version的管理方法。每一个Resource可以理解为一个客户端,而ClientSet则是多个客户端的集合,每一个Resource和Version都以函数的方式暴露给开发者,例如,ClientSet提供的RbacV1、CoreV1、NetworkingV1等接口函数,多ClientSet多资源集合如图所示。
注意:ClientSet仅能访问Kubernetes自身内置的资源(即客户端集合内的资源),不能直接访问CRD自定义资源。
类似于kubectl命令,通过ClientSet列出所有运行中的Pod资源对象,ClientSet Example代码示例如下:
运行以上代码,列出default命名空间下的所有Pod资源对象的相关信息。首先加载kubeconfig配置信息,kubernetes.NewForConfig通过kubeconfig配置信息实例化clientset对象,该对象用于管理所有Resource的客户端。
clientset.CoreV1().Pods
函数表示请求core核心资源组的v1资源版本下的Pod资源对象,其内部设置了APIPath请求的HTTP路径,GroupVersion请求的资源组、资源版本,NegotiatedSerializer数据的编解码器。
其中,Pods函数是一个资源接口对象,用于Pod资源对象的管理,例如,对Pod资源执行Create、Update、Delete、Get、List、Watch、Patch等操作,这些操作实际上是对RESTClient进行了封装。
vendor/k8s.io/client-go/kubernetes/typed/core/v1/pod.go
DynamicClient是一种动态客户端,它可以对任意Kubernetes资源进行RESTful操作,包括CRD自定义资源。DynamicClient与ClientSet操作类似,同样封装了RESTClient,同样提供了Create、Update、Delete、Get、List、Watch、Patch等方法。
DynamicClient与ClientSet最大的不同之处是,ClientSet仅能访问Kubernetes自带的资源(即客户端集合内的资源),不能直接访问CRD自定义资源。ClientSet需要预先实现每种Resource和Version的操作,其内部的数据都是结构化数据(即已知数据结构)。而DynamicClient内部实现了Unstructured,用于处理非结构化数据结构(即无法提前预知数据结构),这也是DynamicClient能够处理CRD自定义资源的关键。
注意:DynamicClient不是类型安全的,因此在访问CRD自定义资源时需要特别注意。例如,在操作指针不当的情况下可能会导致程序崩溃。DynamicClient的处理过程将Resource(例如PodList)转换成Unstructured结构类型,Kubernetes的所有Resource都可以转换为该结构类型。处理完成后,再将Unstructured转换成PodList。整个过程类似于Go语言的interface{}断言转换过程。另外,Unstructured结构类型是通过map[string]interface{}转换的。
类似于kubectl命令,通过DynamicClient列出所有运行的Pod资源对象,DynamicClient Example代码示例如下:
运行以上代码,列出default命名空间下的所有Pod资源对象的相关信息。首先加载kubeconfig配置信息,dynamic.NewForConfig通过kubeconfig配置信息实例化dynamicClient对象,该对象用于管理Kubernetes的所有Resource的客户端,例如对Resource执行Create、Update、Delete、Get、List、Watch、Patch等操作。
dynamicClient.Resource(gvr)
函数用于设置请求的资源组、资源版本、资源名称。Namespace函数用于设置请求的命名空间。List函数用于获取Pod列表。得到的Pod列表为unstructured.UnstructuredList指针类型,然后通过runtime.DefaultUnstructuredConverter.FromUnstructured函数将unstructured.UnstructuredList转换成PodList类型。
DiscoveryClient是发现客户端,它主要用于发现Kubernetes API Server所支持的资源组、资源版本、资源信息。Kubernetes API Server支持很多资源组、资源版本、资源信息,开发者在开发过程中很难记住所有信息,此时可以通过DiscoveryClient查看所支持的资源组、资源版本、资源信息。
kubectl的api-versions和api-resources命令输出也是通过DiscoveryClient实现的。另外,DiscoveryClient同样在RESTClient的基础上进行了封装。
DiscoveryClient除了可以发现Kubernetes API Server所支持的资源组、资源版本、资源信息,还可以将这些信息存储到本地,用于本地缓存(Cache),以减轻对Kubernetes API Server访问的压力。在运行Kubernetes组件的机器上,缓存信息默认存储于~/.kube/cache和~/.kube/http-cache下。
运行以上代码,列出Kubernetes API Server所支持的资源组、资源版本、资源信息。首先加载kubeconfig配置信息,discovery.NewDiscoveryClientForConfig通过kubeconfig配置信息实例化discoveryClient对象,该对象是用于发现Kubernetes API Server所支持的资源组、资源版本、资源信息的客户端。
discoveryClient.ServerGroupsAndResources函数会返回Kubernetes API Server所支持的资源组、资源版本、资源信息(即APIResourceList),通过遍历APIResourceList输出信息。
Kubernetes API Server暴露出/api和/apis接口。DiscoveryClient通过RESTClient分别请求/api和/apis接口,从而获取Kubernetes API Server所支持的资源组、资源版本、资源信息。其核心实现位于ServerGroupsAndResources→ServerGroups
中,代码示例如下:
vendor/k8s.io/client-go/discovery/discovery_client.go
首先,DiscoveryClient通过RESTClient请求/api接口,将请求结果存放于metav1.APIVersions结构体中。然后,再次通过RESTClient请求/apis接口,将请求结果存放于metav1.APIGroupList结构体中。最后,将/api接口中检索到的资源组信息合并到apiGroupList列表中并返回。
DiscoveryClient可以将资源相关信息存储于本地,默认存储位置为~/.kube/cache和~/.kube/http-cache。缓存可以减轻client-go对Kubernetes API Server的访问压力。默认每10分钟与Kubernetes API Server同步一次,同步周期较长,因为资源组、源版本、资源信息一般很少变动。本地缓存的DiscoveryClient如图所示。
vendor/k8s.io/client-go/discovery/cached/disk/cached_discovery.go
如果你觉得本文对你有帮助,欢迎收藏、在看、点赞。