Client-go
简介
client-go是对K8s集群的二次开发工具,所以client-go是k8s开发者的必备工具之一。client-go实现对kubernetes集群中资源对象(包括deployment、service、ingress、replicaSet、pod、namespace、node等)的增删改查等操作。
client-go主要提供了四种类型的客户端:
RESTClient: 是对HTTP Request进行了封装,实现了RESTful风格的API。其他客户端都是在RESTClient基础上的实现。可与用于k8s内置资源和CRD资源
ClientSet:是对k8s内置资源对象的客户端的集合,默认情况下,不能操作CRD资源,但是通过client-gen代码生成的话,也是可以操作CRD资源的。
DynamicClient:不仅能对K8S内置资源进行处理,还可以对CRD资源进行处理,不需要client-gen生成代码即可实现。
DiscoveryClient:用于发现kube-apiserver所支持的资源组、资源版本、资源信息(即Group、Version、Resources)
RestClient
RESTClient是对HTTP Request 进行了封装,是实现了RESTful风格的API封装。
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
| package main
import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes/scheme" )
func main() { config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile) if err != nil { panic(err) } config.GroupVersion = &v1.SchemeGroupVersion config.NegotiatedSerializer = scheme.Codecs config.APIPath = "/api"
restClient, err := rest.RESTClientFor(config) if err != nil { panic(err) }
pod := v1.Pod{} err = restClient.Get().Namespace("default").Resource("pods").Name("test").Do(context.TODO()).Into(&pod)
if err != nil { println(err) }else { println(pod.Name) } }
|
clientSet
ClientSet客户端默认是对k8s内置资源对象客户端的集合,通过ClientSet客户端可以操作k8s的内置资源对象。
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
| package main
import ( "context" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd"
)
func main() { config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile) if err != nil { panic(err) } clientset, err := kubernetes.NewForConfig(config) if err != nil { panic(err) }
pod, err := clientset.CoreV1().Pods("default").Get(context.TODO(), "test", v1.GetOptions{}) if err != nil { println(err) }else { println(pod.Name) }
}
|
DynamicClient
DynamicClient的特点就是除了可以使用k8s内置资源外,还可以使用CRD资源。dynamicClient的原理就是传入的资源数据都是使用map[string]interface{}结构。dynamicClient内部还是restClient.
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
| package main
import ( "context" "fmt" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" "k8s.io/client-go/tools/clientcmd" )
func getDynamicClientExample(kubeconfig string) { config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) if err != nil { panic(err) } client, err := dynamic.NewForConfig(config) if err != nil { panic(err) }
deployment := &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ "name": "demo-deployment", }, "spec": map[string]interface{}{ "replicas": 2, "selector": map[string]interface{}{ "matchLabels": map[string]interface{}{ "app": "demo", }, }, "template": map[string]interface{}{ "metadata": map[string]interface{}{ "labels": map[string]interface{}{ "app": "demo", }, },
"spec": map[string]interface{}{ "containers": []map[string]interface{}{ { "name": "web", "image": "nginx:1.12", "ports": []map[string]interface{}{ { "name": "http", "protocol": "TCP", "containerPort": 80, }, }, }, }, }, }, }, }, } deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"} ctx := context.Background() fmt.Println("Creating deployment...") result, err := client.Resource(deploymentRes).Namespace("default").Create(ctx,deployment, v1.CreateOptions{}) if err != nil { panic(err) } fmt.Printf("Created deployment %q.\n", result.GetName()) }
|
DiscoveryClient
DiscoveryClient是发现客户端,主要用于发现k8s api-server所支持的资源组、资源版本及资源信息。
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
| package main
import ( "fmt" "k8s.io/client-go/discovery" "k8s.io/client-go/tools/clientcmd" )
func getDisCoveryClient(kubeconfig string) { config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) if err != nil { panic(err) } discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) if err != nil { panic(err) } _, APIResourceList, err := discoveryClient.ServerGroupsAndResources() if err != nil { panic(err) } for _, list := range APIResourceList { fmt.Println(list) } }
|
informer在kubernetes系统中,保证各个组件之间消息的实时性、可靠性、顺序性等。k8s各组件通过client-go的informer机制与k8s apiserver通信。
Informer:controller机制的基础,循环处理object对象,从Reflector取出数据,然后将数据给到Indexer去缓存,提供对象事件的handler接口
Informer机制中的ListAndWatch、DeltaFIFO队列和Indexer等对于实现以上特性非常重要。下面这张图就是Informer机制运行原理图:

起点是自定义的Controller,Controller会通过ListAndWatch机制从apiserver获取感兴趣的资源对象信息(初始化controller时,会指定感兴趣资源对象的List和watch方法)。controller的内部包含了reflector和DeltaFIFO,controller就是通过reflector中的list和watch将资源对象信息装入DeltaFIFO队列,然后Controller会一直尝试从队列中pop数据,并根据数据中对象的操作类型作事件通知给各Listener并将资源对象存入本地存储Indexer中。
1、Reflector
用于监控(Watch)指定的kubernetes资源,当监控的资源发生变化时,触发相应的变更事件,如add、update、delete等,并将其资源对象存入本地缓存DeltaFIFO中,然后Informer会从队列里面取数据。
https://blog.csdn.net/u013276277/article/details/108592288
2、DeltaFIFO队列
DeltaFIFO可以分开理解,FIFO是一个先进先出的队列,它拥有队列操作的基本方法,例如Add、Update、Delete、List、Pop、Close等,而Delta是一个资源对象存储,它可以保存资源对象的操作类型,例如Added(添加)操作类型、Updated(更新)操作类型、Deleted(删除)操作类型、Sync(同步)操作类型等
https://blog.csdn.net/u013276277/article/details/108653733
3、Indexer
是client-go用来存储资源对象冰紫带索引功能的本地存储,Refelctor从DeltaFIFO消费出来的资源对象存储至indexer。indexer与etcd集群保持一致。client-go可以很方便的从本地存储中读取响应的资源对象数据,而无需每次从etcd读取,以减轻kubernetes apiserver对etcd的压力。
https://blog.csdn.net/u013276277/article/details/108657739
https://mp.weixin.qq.com/s/xCa6yZTk0X76IZhOx6IbHQ