• (已导出)【kubernetes系列学习】client-go学习与实践


    【kubernetes系列学习】client-go学习与实践

    release author: ningan123

    release time: 2022-08-09

    client-go客户端对象

    client-go支持RESTClient、ClientSet、DynamicClient、DiscoveryClient四种客户端与Kubernetes Api Server进行交互。

    • RESTClient:最基础的客户端,主要是对HTTP请求进行了封装,支持Json和Protobuf格式的数据。

    • DiscoveryClient:发现客户端,负责发现APIServer支持的资源组、资源版本和资源信息的(GVR)。

    • ClientSet:负责操作Kubernetes内置的资源对象,例如:Pod、Services等。

    • DynamicClient:动态客户端,可以对任意的Kubernetes资源对象进行通用操作,包括CRD。

    client-go-demo 工程初始化

    [root@master ~]# mkdir client-go-demo
    [root@master ~]#
    [root@master ~]#
    [root@master ~]# cd client-go-demo/
    [root@master client-go-demo]#
    [root@master client-go-demo]# ll
    总用量 0
    [root@master client-go-demo]#
    [root@master client-go-demo]#
    [root@master client-go-demo]# go mod init ningan.com/client-go-demo
    go: creating new go.mod: module ningan.com/client-go-demo
    [root@master client-go-demo]#
    [root@master client-go-demo]# ll
    总用量 4
    -rw-r--r-- 1 root root 42 89 04:06 go.mod
    [root@master client-go-demo]#
    [root@master client-go-demo]# cat go.mod
    module ningan.com/client-go-demo
    
    go 1.17
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    RESTClient

    RESTClient是最基础的客户端,其他的ClientSet、DynamicClient即DscoveryClient都是基于RESTClient实现的。

    RESTClient对HTTP Client进行了封装,实现了Restful风格的API。

    它具有很高的灵活性,数据不依赖于方法和资源,因此RESTClient能够处理多种类型的调用,返回不同的数据格式。

    demo示例:通过RESTClient示例列出某一命名空间下的Pod资源对象

    package main
    
    import (
    	"context"
    	"fmt"
    
    	corev1 "k8s.io/api/core/v1"
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    	"k8s.io/client-go/kubernetes/scheme"
    	"k8s.io/client-go/rest"
    	"k8s.io/client-go/tools/clientcmd"
    )
    
    /*
    	@Author: ningan
    	@Desc: 获取kube-system命名空间下的Pod列表
    */
    
    func main() {
    	/*
    		1. k8s的配置文件
    		2. 保证开发机能通过这个配置文件连接到k8s集群
    	*/
    
    	// 1. 加载配置文件,生成config对象
    	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
    	if err != nil {
    		panic(err)
    		// panic(err.Error())
    	}
    
    	// 2. 配置API路径  请求的HTTP路径
    	config.APIPath = "api" // pods,  /api/v1/pods
    	// config.APIPath = "apis" // deployments,  /apis/apps/v1/namespaces/{namespace}/deployments/{deployment}
    
    	// 3. 配置请求的资源组/资源版本 GV
    	config.GroupVersion = &corev1.SchemeGroupVersion // 无名资源组, group: " ", version: "v1"
    
    	// 4. 配置数据的编解码工具  序列化和反序列化
    	config.NegotiatedSerializer = scheme.Codecs
    
    	// 5. 通过kubeconfg配置信息实例化RESTClient对象
    	restClient, err := rest.RESTClientFor(config)
    	if err != nil {
    		panic(err)
    	}
    
    	// 6. 定义接收返回值的变量
    	result := &corev1.PodList{}
    
    	// 跟APIServer交互
    	err = restClient.
    		Get().                                                                  // RESTClient对象构建HTTP请求参数  请求方法:Get、Post、Put、Delete、Patch
    		Namespace("kube-system").                                               // 命名空间
    		Resource("pods").                                                       // 资源名
    		VersionedParams(&metav1.ListOptions{Limit: 50}, scheme.ParameterCodec). // 将一些查询选项(如limit、TimeoutSeconds)添加到请求参数中 limit参数表示最多检索出多少信息
    		Do(context.TODO()).                                                     // 执行该请求
    		Into(result)                                                            // 将kube-apiserver返回的结果(Result对象)解析到corev1.PodList对象中
    	if err != nil {
    		panic(err)
    	}
    
    	/*
    		1)Get定义请求方式,返回了一个Request结构体对象。这个Request结构体对象,就是构建访问APIServer用的。
    		2)依次执行了Namespace、Resource、VersionedParams,构建与APIServer交互的参数。
    		3)Do方法通过requets发起请求,然后通过transformResponse解析请求返回,并绑定到对应资源对象的结构体对象上。这里的话,表示的是corev1.PodList对象。
    		4)request先是检查了有没有可用的client,在这里开始调用net/http包的功能。
    	*/
    
    	/*
    		1) RESTClient发送请求的过程对Go语言标准库net/http进行了封装,由Do -> Request函数实现。
    		2) 请求发送之前需要根据请求参数生成请求的RESTful URL,由r.URL().String()函数完成。 http://xxxx:x/api/v1/namespaces/kube-system/pods?limit=1
    		3) 通过Go语言标准库net/http向RESTful URL(即kube-apiserver)发送请求,请求得到的结果存放在http.Response的Body对象中,fn函数(即transformResponse)将结果转化为资源对象。
    	*/
    
    	// 格式化输出结果
    	for _, item := range result.Items {
    		fmt.Printf("namespace: %v, name: %v, status: %v\n", item.Namespace, item.Name, item.Status.Phase)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    运行:

    [root@master demo1]# go run main.go
    namespace: kube-system, name: calico-kube-controllers-67878b879f-2x5xg, status: Running
    namespace: kube-system, name: calico-node-4xwrz, status: Running
    namespace: kube-system, name: metrics-server-68955dc6f-xvv9t, status: Running
    
    • 1
    • 2
    • 3
    • 4

    ClientSet

    RESTClient是一张最基础的客户端,使用时需要指定Resource和Version等信息,编写代码需要提前知道Resource所在的Group和对应的Version信息。

    相比RESTClient,ClientSet使用起来更加便捷,一般情况下,开发者对Kubernetes进行二次开发时通常使用ClientSet。

    ClientSet在RESTClient的基础上封装了对Resource和Version的管理方法。每一个Resource可以理解为一个客户端,而ClientSet则是多个客户端的几核,每一个Resource和Version都以函数的方法暴露给开发者,例如ClientSet提供的RbacV1、CoreV1、NetworkingV1等接口参数。

    demo示例:通过ClientSet示例列出某一命名空间下的Pod资源对象

    package main
    
    import (
    	"context"
    	"fmt"
    
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    	"k8s.io/client-go/kubernetes"
    	"k8s.io/client-go/tools/clientcmd"
    )
    
    /*
    	@Author: ningan
    	@Desc: 获取kube-system命名空间下的Pod列表
    */
    
    func main() {
    	// 1. 加载配置文件,生成config对象
    	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 2. 通过kubeconfig配置信息实例化ClientSet 该对象用于管理所有Resource的客户端
    	clientset, err := kubernetes.NewForConfig(config)
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 3. 查询
    	result, err := clientset.
    		CoreV1().            // 返回CoreV1Client实例
    		Pods("kube-system"). // 指定查询的资源预计指定资源的namespace,namespace如果为空,表示查询所有namespace
    		// Namespaces().     // 查询namespace
    		List(context.TODO(), metav1.ListOptions{Limit: 50})
    	if err != nil {
    		panic(err.Error())
    	}
    	/*
    		1) CoreV1返回CoreV1Client实例对象
    		2) Pods 调用了newPods函数,该函数返回的试PodInterface对象,PodInterface对象实现了Pods资源相关的全部方法,同时再newPods里面还将RESTClient实例对象赋值给了对应的Client属性
    		3) List内部使用RestClient与k8s APIServer进行了交互
    	*/
    
    	/*
    		1) clientset.CoreV1().Pods表示请求core核心资源组的v1资源版本下的Pod资源对象,其内部设置了APIPath请求的HTTP路径,GroupVersion请求的资源组、资源版本,NegotiatedSerializer数据的编解码器。
    		2) Pods函数是一个资源对象接口,用于Pod资源对象的管理。例如,对Pod资源执行Create、Update、Delete、Get、List、Watch、Patch等操作,这些操作实际上是对RESTClient进行了封装,可以设置选项(如Limit、TimeoutSeconds等)。
    	*/
    
    	// 4. 格式化输出结果
    	for _, item := range result.Items {
    		fmt.Printf("namespace: %v, name: %v, status: %v\n", item.Namespace, item.Name, item.Status.Phase)
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    DynamicClient

    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的处理过程将Resource(例如PodList)转化成Unstructured结构类型,Kubernetes的所有Resource都可以转化为该结构类型。处理完成后,再将Unstructured转换成PodList。整个过程类似于Go语言的interface{}断言转换过程。另外,Unstructured结构类型是通过map[string]interface{}转换的。

    两个重要的知识点:

    • Object.runtime:Kubernetes中的所有资源对象都实现了这个接口,其中包含DeepCopyObject和GetObjectKind的方法,分别用于对象深拷贝和获取对象的具体资源类型。
    • Unstructured:包含map[string]interface{}类型字段,在处理无法预知结构的数据时,将数据值存入interface{}中,待运行时利用反射判断。该结构体提供了大量的工具方法,便于处理非结构化的数据。

    demo示例:通过DynamicClient示例列出某一命名空间下的Pod资源对象

    package main
    
    import (
    	"context"
    	"fmt"
    
    	corev1 "k8s.io/api/core/v1"
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    	"k8s.io/apimachinery/pkg/runtime"
    	"k8s.io/apimachinery/pkg/runtime/schema"
    	"k8s.io/client-go/dynamic"
    	"k8s.io/client-go/tools/clientcmd"
    )
    
    /*
    	@Author: ningan
    	@Desc: 获取kube-system命名空间下的Pod列表
    */
    
    func main() {
    	// 1. 加载配置文件,生成config对象
    	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 2. 通过kubeconfig配置信息实例化客户端对象,这里是实例化动态客户端对象。该对象用于管理Kubernetes的所有Resource的客户端,例如对Resource执行Create、Update、Delete、Get、List、Watch、Patch等操作。
    	dynamicClient, err := dynamic.NewForConfig(config)
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 3. 配置需要调用的GVR
    	gvr := schema.GroupVersionResource{
    		Group:    "",
    		Version:  "v1",
    		Resource: "pods",
    	}
    
    	// 4. 发送请求,并得到返回结果
    	unstructedObj, err := dynamicClient.
    		Resource(gvr).
    		Namespace("kube-system").
    		List(context.TODO(), metav1.ListOptions{})
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 5. unstructedObj转化为结构化数据
    	podList := &corev1.PodList{}
    	err = runtime.DefaultUnstructuredConverter.FromUnstructured(
    		unstructedObj.UnstructuredContent(),
    		podList,
    	)
    	if err != nil {
    		panic(err.Error())
    	}
    	/*
    		1) Resource:基于gvr生成了一个针对于资源的客户端,也可以称之为动态资源客户端,dunamicResourceClient
    		2) Namespace:指定一个可操作的命名空间,同时它是dynamicResourceClient的方法
    		3) List:首先通过RESTClient调用k8s APIServer的接口返回了Pod的数据,返回的数据格式是二进制的Json格式,然后通过一些列的解析方法,转换成unstructured.UnstructuredList
    	*/
    
    	/*
    		1) dynamicClient.Resource()函数用于设置请求的资源组、资源版本、资源名称。
    		2) Namespace函数用于设置请求的命名空间。
    		3) List函数用户获取Pod列表,得到的Pod列表为unstructured.UnstructuredList指针类型
    		4) 然后通过runtime.DefaultUnstructuredConverter.FromUnstructured函数将unstructured.UnstructuredList转换为PodList类型。
    	*/
    
    	// 6. 格式化输出结果
    	for _, item := range podList.Items {
    		fmt.Printf("namespace: %v, name: %v, status: %v\n", item.Namespace, item.Name, item.Status.Phase)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    DiscoveryClient

    DiscoveryClient是发现客户端,它主要用于发现Kubernetes API Server所支持的资源组、资源版本、资源信息。

    Kubernetes API Server支持很多资源组、资源版本、资源信息,开发者可以通过DiscoveryClient进行查看。

    kuectlde api-versions和api-resources命令输出也是通过DiscoveryClient实现的。另外,DiscoveryClient也是子啊RESTClient的基础上进行了封装。

    DiscoveryClient除了可以发现Kubernetes API Server所支持的资源组、资源版本、资源信息,还可以将这些信息存储到本地,用于本地缓存(cache),以减轻对Kubernetes API Server访问的压力。在运行Kubernetes组件的机器上,缓存信息默认存储与/.kube/cache和/.kube/http-cache下。

    demo示例:通过DynamicClient列出Kubernetes API Server所支持的资源组、资源版本、资源信息

    package main
    
    import (
    	"fmt"
    
    	"k8s.io/apimachinery/pkg/runtime/schema"
    	"k8s.io/client-go/discovery"
    	"k8s.io/client-go/tools/clientcmd"
    )
    
    /*
    	@Author: ningan
    	@Desc: 通过DynamicClient列出Kubernetes API Server所支持的资源组、资源版本、资源信息
    */
    
    func main() {
    	// 1. 加载配置文件,生成config对象
    	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 2. 通过kubeconfig配置信息实例化discoveryClient对象,这个对象是用于发现Kubernetes API Server所支持的资源组、资源版本、资源信息的客户端。
    	discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 3. 发送请求,获取GVR数据
    	_, apiResourcesList, err := discoveryClient.ServerGroupsAndResources()
    	if err != nil {
    		panic(err.Error())
    	}
    	/*
    		1) ServerGroups负责获取gv数据
    		2) 然后调用fetchGroupVersionResources,且给这个方法传递gv参数,通过调用ServerResourcesForGroupVersion方法获取gv对应的Resource数据,同时返回一个map[gv]resourceList的数据格式
    		3) 处理map->slice,然后返回GCR slice
    	*/
    
    	/*
    		Kubernetes API Server暴露出/api和/apis接口。DiscoveryClient通过RESTClient分别请求/api和/apis接口,从而获取Kubernetes API Server所支持的资源组、资源版本、资源信息。核心实现位于:ServerGroupsAndResources->ServerGroups中
    
    	*/
    
    	for _, list := range apiResourcesList {
    		gv, err := schema.ParseGroupVersion(list.GroupVersion)
    		if err != nil {
    			panic(err.Error())
    		}
    
    		for _, resource := range list.APIResources {
    			fmt.Printf("name: %v, group: %v, version: %v\n", resource.Name, gv.Group, gv.Version)
    		}
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    [root@master demo1]# go run main.go
    name: bindings, group: , version: v1
    name: componentstatuses, group: , version: v1
    name: configmaps, group: , version: v1
    name: endpoints, group: , version: v1
    name: events, group: , version: v1
    name: limitranges, group: , version: v1
    name: namespaces, group: , version: v1
    name: namespaces/finalize, group: , version: v1
    name: namespaces/status, group: , version: v1
    name: nodes, group: , version: v1
    name: nodes/proxy, group: , version: v1
    name: nodes/status, group: , version: v1
    name: persistentvolumeclaims, group: , version: v1
    name: persistentvolumeclaims/status, group: , version: v1
    name: persistentvolumes, group: , version: v1
    name: persistentvolumes/status, group: , version: v1
    name: pods, group: , version: v1
    name: pods/attach, group: , version: v1
    name: pods/binding, group: , version: v1
    name: pods/eviction, group: , version: v1
    name: pods/exec, group: , version: v1
    name: pods/log, group: , version: v1
    name: pods/portforward, group: , version: v1
    name: pods/proxy, group: , version: v1
    name: pods/status, group: , version: v1
    name: podtemplates, group: , version: v1
    name: replicationcontrollers, group: , version: v1
    name: replicationcontrollers/scale, group: , version: v1
    name: replicationcontrollers/status, group: , version: v1
    name: resourcequotas, group: , version: v1
    name: resourcequotas/status, group: , version: v1
    name: secrets, group: , version: v1
    name: serviceaccounts, group: , version: v1
    name: services, group: , version: v1
    name: services/proxy, group: , version: v1
    name: services/status, group: , version: v1
    name: apiservices, group: apiregistration.k8s.io, version: v1
    name: apiservices/status, group: apiregistration.k8s.io, version: v1
    name: apiservices, group: apiregistration.k8s.io, version: v1beta1
    name: apiservices/status, group: apiregistration.k8s.io, version: v1beta1
    name: ingresses, group: extensions, version: v1beta1
    name: ingresses/status, group: extensions, version: v1beta1
    name: controllerrevisions, group: apps, version: v1
    name: daemonsets, group: apps, version: v1
    name: daemonsets/status, group: apps, version: v1
    name: deployments, group: apps, version: v1
    name: deployments/scale, group: apps, version: v1
    name: deployments/status, group: apps, version: v1
    name: replicasets, group: apps, version: v1
    name: replicasets/scale, group: apps, version: v1
    name: replicasets/status, group: apps, version: v1
    name: statefulsets, group: apps, version: v1
    name: statefulsets/scale, group: apps, version: v1
    name: statefulsets/status, group: apps, version: v1
    name: events, group: events.k8s.io, version: v1
    name: events, group: events.k8s.io, version: v1beta1
    name: tokenreviews, group: authentication.k8s.io, version: v1
    name: tokenreviews, group: authentication.k8s.io, version: v1beta1
    name: localsubjectaccessreviews, group: authorization.k8s.io, version: v1
    name: selfsubjectaccessreviews, group: authorization.k8s.io, version: v1
    name: selfsubjectrulesreviews, group: authorization.k8s.io, version: v1
    name: subjectaccessreviews, group: authorization.k8s.io, version: v1
    name: localsubjectaccessreviews, group: authorization.k8s.io, version: v1beta1
    name: selfsubjectaccessreviews, group: authorization.k8s.io, version: v1beta1
    name: selfsubjectrulesreviews, group: authorization.k8s.io, version: v1beta1
    name: subjectaccessreviews, group: authorization.k8s.io, version: v1beta1
    name: horizontalpodautoscalers, group: autoscaling, version: v1
    name: horizontalpodautoscalers/status, group: autoscaling, version: v1
    name: horizontalpodautoscalers, group: autoscaling, version: v2beta1
    name: horizontalpodautoscalers/status, group: autoscaling, version: v2beta1
    name: horizontalpodautoscalers, group: autoscaling, version: v2beta2
    name: horizontalpodautoscalers/status, group: autoscaling, version: v2beta2
    name: jobs, group: batch, version: v1
    name: jobs/status, group: batch, version: v1
    name: cronjobs, group: batch, version: v1beta1
    name: cronjobs/status, group: batch, version: v1beta1
    name: certificatesigningrequests, group: certificates.k8s.io, version: v1
    name: certificatesigningrequests/approval, group: certificates.k8s.io, version: v1
    name: certificatesigningrequests/status, group: certificates.k8s.io, version: v1
    name: certificatesigningrequests, group: certificates.k8s.io, version: v1beta1
    name: certificatesigningrequests/approval, group: certificates.k8s.io, version: v1beta1
    name: certificatesigningrequests/status, group: certificates.k8s.io, version: v1beta1
    name: ingressclasses, group: networking.k8s.io, version: v1
    name: ingresses, group: networking.k8s.io, version: v1
    name: ingresses/status, group: networking.k8s.io, version: v1
    name: networkpolicies, group: networking.k8s.io, version: v1
    name: ingressclasses, group: networking.k8s.io, version: v1beta1
    name: ingresses, group: networking.k8s.io, version: v1beta1
    name: ingresses/status, group: networking.k8s.io, version: v1beta1
    name: poddisruptionbudgets, group: policy, version: v1beta1
    name: poddisruptionbudgets/status, group: policy, version: v1beta1
    name: podsecuritypolicies, group: policy, version: v1beta1
    name: clusterrolebindings, group: rbac.authorization.k8s.io, version: v1
    name: clusterroles, group: rbac.authorization.k8s.io, version: v1
    name: rolebindings, group: rbac.authorization.k8s.io, version: v1
    name: roles, group: rbac.authorization.k8s.io, version: v1
    name: clusterrolebindings, group: rbac.authorization.k8s.io, version: v1beta1
    name: clusterroles, group: rbac.authorization.k8s.io, version: v1beta1
    name: rolebindings, group: rbac.authorization.k8s.io, version: v1beta1
    name: roles, group: rbac.authorization.k8s.io, version: v1beta1
    name: csidrivers, group: storage.k8s.io, version: v1
    name: csinodes, group: storage.k8s.io, version: v1
    name: storageclasses, group: storage.k8s.io, version: v1
    name: volumeattachments, group: storage.k8s.io, version: v1
    name: volumeattachments/status, group: storage.k8s.io, version: v1
    name: csidrivers, group: storage.k8s.io, version: v1beta1
    name: csinodes, group: storage.k8s.io, version: v1beta1
    name: storageclasses, group: storage.k8s.io, version: v1beta1
    name: volumeattachments, group: storage.k8s.io, version: v1beta1
    name: mutatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1
    name: validatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1
    name: mutatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1beta1
    name: validatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1beta1
    name: customresourcedefinitions, group: apiextensions.k8s.io, version: v1
    name: customresourcedefinitions/status, group: apiextensions.k8s.io, version: v1
    name: customresourcedefinitions, group: apiextensions.k8s.io, version: v1beta1
    name: customresourcedefinitions/status, group: apiextensions.k8s.io, version: v1beta1
    name: priorityclasses, group: scheduling.k8s.io, version: v1
    name: priorityclasses, group: scheduling.k8s.io, version: v1beta1
    name: leases, group: coordination.k8s.io, version: v1
    name: leases, group: coordination.k8s.io, version: v1beta1
    name: runtimeclasses, group: node.k8s.io, version: v1beta1
    name: endpointslices, group: discovery.k8s.io, version: v1beta1
    name: cukclusters, group: dubhe.welkin, version: v1alpha1
    name: cukclusters/status, group: dubhe.welkin, version: v1alpha1
    name: cuknodes, group: dubhe.welkin, version: v1alpha1
    name: cuknodes/status, group: dubhe.welkin, version: v1alpha1
    name: cuksets, group: dubhe.welkin, version: v1alpha1
    name: cuksets/status, group: dubhe.welkin, version: v1alpha1
    name: nodes, group: metrics.k8s.io, version: v1beta1
    name: pods, group: metrics.k8s.io, version: v1beta1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133

    将GVR缓存到本地

    可以发现,GVR数据其实是很少变动的,因此我们可以将GVR的数据缓存到本地,来减少Client与Apiserver交互。

    在discovery/cached中,有另外两个客户端是来实现将GVR数据缓存到本地文件中和内存中的,分别是CachedDiscoveryClient和memCacheClient。

    平时管理集群的kubectl命令也是使用这种方式来使用GVR与APIServer交互的。

    DiscoveryClient除了可以发现Kubernetes API Server所支持的资源组、资源版本、资源信息,还可以将这些信息存储到本地,用于本地缓存(cache),以减轻对Kubernetes API Server访问的压力。在运行Kubernetes组件的机器上,缓存信息默认存储与/.kube/cache和/.kube/http-cache下。

    package main
    
    import (
    	"fmt"
    	"time"
    
    	"k8s.io/apimachinery/pkg/runtime/schema"
    	"k8s.io/client-go/discovery/cached/disk"
    	"k8s.io/client-go/tools/clientcmd"
    )
    
    /*
    	@Author: ningan
    	@Desc: 将GVR数据缓存到本地
    */
    
    func main() {
    	// 1. 加载配置文件,生成config对象
    	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
    	if err != nil {
    		panic(err.Error())
    	}
    
    	// 2. 实例化客户端,本客户端负责将GVR数据缓存到本地文件中
    	cachedDiscoveryClient, err := disk.NewCachedDiscoveryClientForConfig(config, "./cache/discovery", "./cache/http", time.Minute*60)
    	if err != nil {
    		panic(err.Error())
    	}
    
    	_, apiResourcesList, err := cachedDiscoveryClient.ServerGroupsAndResources()
    	if err != nil {
    		panic(err.Error())
    	}
    
    	/*
    		1) 先从缓存文件中找GVR数据,有则直接返回,没有则调用APIServer
    		2) 嗲用APIServer获取GVR数据
    		3) 将获取到的GVR数据缓存到本地,然后返回给客户端
    
    	*/
    
    	for _, list := range apiResourcesList {
    		gv, err := schema.ParseGroupVersion(list.GroupVersion)
    		if err != nil {
    			panic(err.Error())
    		}
    
    		for _, resource := range list.APIResources {
    			fmt.Printf("name: %v, group: %v, version: %v\n", resource.Name, gv.Group, gv.Version)
    		}
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    执行go run main.go之后,确实生成了cache目录

    [root@master demo2]# tree -L 2
    .
    ├── cache
    │   ├── discovery
    │   └── http
    └── main.go
    
    3 directories, 1 file
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    参考

    Kubernetes源码剖析 5.2节 Client客户端对象

    b站视频:Client-go实战教程

  • 相关阅读:
    Spring系列19:SpEL详解
    MySQL8.0.28安装教程
    Mybatis面试题(三)
    我的创作纪念日--不知不觉一周年了呐
    105.am40刷机(linux)折腾记1-前期的准备工作1
    ARM开发(6)系统移植初步体验(搭建交叉开发环境)
    高精地图_语义地图_众包地图相关论文笔记
    稳如泰山:云计算网络连接稳定性保障之道
    C学生数据库_读取文件中学生信息1。
    Pytorch实用教程:torch.from_numpy(X_train)和torch.from_numpy(X_train).float()的区别
  • 原文地址:https://blog.csdn.net/weixin_42072280/article/details/126513498