Files
notes_estom/kubenets/operator/05 client-go.md
yinkanglong 498eb76a3d $date
2023-08-18 08:55:09 +08:00

7.4 KiB
Raw Blame History

Client-go

简介

client-go是对K8s集群的二次开发工具所以client-go是k8s开发者的必备工具之一。client-go实现对kubernetes集群中资源对象包括deployment、service、ingress、replicaSet、pod、namespace、node等的增删改查等操作。

client-go主要提供了四种类型的客户端

  1. RESTClient 是对HTTP Request进行了封装实现了RESTful风格的API。其他客户端都是在RESTClient基础上的实现。可与用于k8s内置资源和CRD资源

  2. ClientSet:是对k8s内置资源对象的客户端的集合默认情况下不能操作CRD资源但是通过client-gen代码生成的话也是可以操作CRD资源的。

  3. DynamicClient:不仅能对K8S内置资源进行处理还可以对CRD资源进行处理不需要client-gen生成代码即可实现。

  4. DiscoveryClient用于发现kube-apiserver所支持的资源组、资源版本、资源信息即Group、Version、Resources

RestClient

RESTClient是对HTTP Request 进行了封装是实现了RESTful风格的API封装。

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() {
	//RESTCLIENT
	//config
	config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
	if err != nil {
		panic(err)
	}
	config.GroupVersion = &v1.SchemeGroupVersion
	config.NegotiatedSerializer = scheme.Codecs
	config.APIPath = "/api"

	//client
	restClient, err := rest.RESTClientFor(config)
	if err != nil {
		panic(err)
	}

	//get data
	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的内置资源对象。

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() {
	//clientset
	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.

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()
	// Create Deployment
	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所支持的资源组、资源版本及资源信息。

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)
	}
}

2 Informer机制

informer在kubernetes系统中保证各个组件之间消息的实时性、可靠性、顺序性等。k8s各组件通过client-go的informer机制与k8s apiserver通信。

Informercontroller机制的基础循环处理object对象从Reflector取出数据然后将数据给到Indexer去缓存提供对象事件的handler接口

Informer机制中的ListAndWatch、DeltaFIFO队列和Indexer等对于实现以上特性非常重要。下面这张图就是Informer机制运行原理图

起点是自定义的ControllerController会通过ListAndWatch机制从apiserver获取感兴趣的资源对象信息初始化controller时会指定感兴趣资源对象的List和watch方法。controller的内部包含了reflector和DeltaFIFOcontroller就是通过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