client-go 基本概念

client-go 基本概念

Client 类型

  • RESTClient :最基本的客户端,提供组基本的封装
  • Clientset:是一个Client 的集群,在Clientset 中包含了所有的k8s内置资源的Client,通过Clientset便可以很方便的操纵如pod、service 资源
  • dynamicClient:动态客户端,可以操作任意k8s的资源,包括CRD定义的资源
  • DiscoveryClient:用于发现k8s 提供的资源组、资源版本和资源信息,比如:kubectl api-resources。

代码结构:

client-go源码https://github.com/kubernetes/client-go

client-go源码目录结构

  • The kubernetes package contains the clientset to access Kubernetes API.
  • The discovery package is used to discover APIs supported by a Kubernetes API server.
  • The dynamic package contains a dynamic client that can perform generic operations on arbitrary Kubernetes API objects.
  • The transport package is used to set up auth and start a connection.
  • The tools/cache package is useful for writing controllers.
  • The rest packages contains restclient
# tree client-go/ -L 1
client-go/
  ├── discovery
  ├── dynamic
  ├── informers
  ├── kubernetes
  ├── listers
  ├── plugin
  ├── rest
  ├── scale
  ├── tools
  ├── transport
  └── util
  • discovery:提供 DiscoveryClient 发现客户端

  • dynamic:提供 DynamicClient 动态客户端

  • informers:每种 kubernetes 资源的 Informer 实现

  • kubernetes:提供 ClientSet 客户端

  • listers:为每一个 Kubernetes 资源提供 Lister 功能,该功能对 Get 和 List 请求提供只读的缓存数据

  • plugin:提供 OpenStack、GCP 和 Azure 等云服务商授权插件

  • rest:提供 RESTClient 客户端,对 Kubernetes API Server 执行 RESTful 操作

  • scale:提供 ScaleClient 客户端,用于扩容或缩容 Deployment、ReplicaSet、Relication Controller 等资源对象

  • tools:提供常用工具,例如 SharedInformer、Reflector、DealtFIFO 及 Indexers。提供 Client 查询和缓存机制,以减少向 kube-apiserver 发起的请求数等

  • transport:提供安全的 TCP 连接,支持 Http Stream,某些操作需要在客户端和容器之间传输二进制流,例如 exec、attach 等操作。该功能由内部的 spdy 包提供支持

  • util:提供常用方法,例如 WorkQueue 功能队列、Certificate 证书管理等

RESTClient

  • RESTClient是 client-go 最基础的客户端,主要是对HTTP Reqeust进行了封装,对外提供RESTful风格的API,并且提供丰富的API用于各种设置,相比其他几种客户端虽然更复杂,但是也更为灵活;

  • 使用RESTClient对kubernetes的资源进行增删改查的基本步骤如下:

    1. 确定要操作的资源类型(例如查找deployment列表),去官方API文档中找到对于的path、数据结构等信息,后面会用到;
    2. 加载配置kubernetes配置文件(和kubectl使用的那种kubeconfig完全相同);
    3. 根据配置文件生成配置对象,并且通过API对配置对象就行设置(例如请求的path、Group、Version、序列化反序列化工具等);
    4. 创建RESTClient实例,入参是配置对象;
    5. 调用RESTClient实例的方法向kubernetes的API Server发起请求,编码用fluent风格将各种参数传入(例如指定namespace、资源等),如果是查询类请求,还要传入数据结构实例的指针,改数据结构用于接受kubernetes返回的查询结果;

Clientset

通过sdk里封装好的方法,对k8s里的一类资源进行操作。

ClientSet在RestClient的基础上封装了对Resouorce和Version的管理方法。

一个Resource可以理解为一个客户端,而ClientSet是多个客户端的集合

其操作资源对象时需要指定Group、指定Version,然后根据Resource获取,但是clientset不支持自定义crd(CustomResourceDefinition)。

更新configmap

configMap := v1.ConfigMap{
        ObjectMeta: metav1.ObjectMeta{
            Name: "xxx",
        },
        Data: map[string]string{
            "xxx.yaml": string(yaml),
        },
    }
_, err = clientset.CoreV1().ConfigMaps(xxx).Update(ctx, configMap, metav1.UpdateOptions{})

DynamicClient

DynamicClient是一种动态客户端它可以对任何资源进行restful操作包括crd自定义资源,不同于 clientset,dynamic client 返回的对象是一个 map[string]interface{}

利用DynamicClient更新自定义资源

resource := schema.GroupVersionResource{Group: "xxx", Version: "v1", Resource: "xxx"}
    // 先查询,有的情况下就更新,没有就创建
    xxx, err := k8sProxy.DynamicClient.Resource(resource).Get(ctx, xxx, metav1.GetOptions{})
    if err == nil {
        if err := unstructured.SetNestedField(xxx.Object, pop.Name, "spec", "pop"); err != nil {
            return err
        }
        _, err = k8sProxy.DynamicClient.Resource(resource).Update(ctx, xxx, metav1.UpdateOptions{})
    } else if k8sErrors.IsNotFound(err) {
        xxx := &unstructured.Unstructured{
            Object: map[string]interface{}{
                "apiVersion": "xxx/v1",
                "kind":       "xxx",
                "metadata": map[string]interface{}{
                    "name": xxx,
                },
                "spec": map[string]interface{}{
                    "pop":     pop.Name,
                },
            },
        }
        _, err = k8sProxy.DynamicClient.Resource(resource).Create(ctx, xxx, metav1.CreateOptions{})
    }
    return err

DiscoveryClient

DiscoveryClient是发现客户端,主要用于发现api server支持的资源组 资源版本 资源信息,k8s api server 支持很多资源组 资源版本,资源信息,此时可以通过DiscoveryClient来查看

kubectl的api-version和api-resource也是通过DiscoveryClient来实现的,还可以将信息缓存在本地cache,以减轻api的访问压力,默认在./kube/cache和./kube/http-cache下。

package main

import (
	"flag"
	"fmt"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/discovery"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/homedir"
	"path/filepath"
)

func main() {
	var kubeconfig *string

	if home := homedir.HomeDir(); home != "" {
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}

	flag.Parse()

	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	
	discoverClient, err := discovery.NewDiscoveryClientForConfig(config)
	if err != nil {
		panic(err)
	}
	_, apiResourceList, err := discoverClient.ServerGroupsAndResources()
	for _, v := range apiResourceList {
		gv, err := schema.ParseGroupVersion(v.GroupVersion)
		if err != nil {
			panic(err)
		}
		for _, resource := range v.APIResources {
			fmt.Println("name:", resource.Name, "    ", "group:", gv.Group, "    ", "version:", gv.Version)
		}
	}
}

Reference:

https://www.huweihuang.com/article/source-analysis/client-go-source-analysis/

https://cloud.tencent.com/developer/article/2114992

https://juejin.cn/post/6962869412785487909

posted @ 2022-10-14 11:32  sixinshuier  阅读(422)  评论(0编辑  收藏  举报