一文带您了解client-go的四种客户端

author author     2022-12-04     445

关键词:

Client-Go 简介

Client-Go 是负责与 Kubernetes APIServer 服务进行交互的客户端库,利用 Client-Go 与Kubernetes APIServer 进行的交互访问,来对 Kubernetes 中的各类资源对象进行管理操作,包括内置的资源对象及CRD。

Client-Go 不仅被 Kubernetes 项目本身使用,其它围绕着 Kubernetes 的生态,也被大量的使用,例如:kubectl、ETCD-operator等等。

Client-Go 客户端

Client-Go 共提供了 4 种与 Kubernetes APIServer 交互的客户端。分别是 RESTClient、DiscoveryClient、ClientSet、DynamicClient。

  • RESTClient:最基础的客户端,主要是对 HTTP 请求进行了封装,支持 Json 和 Protobuf 格式的数据。
  • DiscoveryClient:发现客户端,负责发现 APIServer 支持的资源组、资源版本和资源信息的。
  • ClientSet:负责操作 Kubernetes 内置的资源对象,例如:Pod、Service等。
  • DynamicClient:动态客户端,可以对任意的 Kubernetes 资源对象进行通用操作,包括 CRD。

一文带您了解

RESTClient

RESTClient 是所有客户端的父类,这也是为啥前面说,它是最基础的客户端的原因。

它提供了 RESTful 对应的方法的封装,如:Get()、Put()、Post()、Delete() 等。通过这些封装发方法与 Kubernetes APIServer RESTful API 进行交互。

因为它是所有客户端的父类,所以它可以操作 Kubernetes 内置的所有资源对象以及 CRD。

运行以下代码,将得到 default 下的 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 : lanyulei
@Desc :
*/

func main()
// 加载配置文件,生成 config 对象
config, err := clientcmd.BuildConfigFromFlags("", "../../kubeconfig")
if err != nil
panic(err.Error())


// 配置 API 路径
config.APIPath = "api"

// 配置分组版本
config.GroupVersion = &corev1.SchemeGroupVersion

// 配置数据的编解码器
config.NegotiatedSerializer = scheme.Codecs

// 实例化 RESTClient
restClient, err := rest.RESTClientFor(config)
if err != nil
panic(err.Error())


// 定义返回接收值
result := &corev1.PodList

err = restClient.Get().
Namespace("default"). // 查询的 Namespace
Resource("pods"). // 查询的资源类型
VersionedParams(&metav1.ListOptionsLimit: 100, scheme.ParameterCodec). // 参数及序列化工具
Do(context.TODO()). // 发送请求
Into(result) // 写入返回值
if err != nil
panic(err.Error())


// 输出返回结果
for _, d := range result.Items
fmt.Printf("namespace: %v, name: %v, status: %v\\n", d.Namespace, d.Name, d.Status.Phase)

输出结果

➜  demo1 go run main.go
namespace: default, name: 1231-589c58c8c5-27r94, status: Pending
namespace: default, name: 1231-b6896fd77-7bkgk, status: Pending
namespace: default, name: web-96d5df5c8-rcw6r, status: Running
namespace: default, name: web-96d5df5c8-rdzpr, status: Running

RESTClient 其实就是底层使用 net/http 库,将调用 Kubernetes APIServer 的 API 请求,进行了封装,对参数和返回结果进行了序列化及反序列化,有兴趣的话,可以看下源码,分析一下请求过程。这里就不多介绍了。

ClientSet

上面介绍了 RESTClient,它虽然可以操作 Kubernetes 的所有资源对象,但是使用起来确实比较复杂,需要配置的参数过于繁琐,因此,为了更优雅的更方便的与 Kubernetes APIServer 进行交互,则需要进一步的封装。

前面有过介绍,ClientSet 是基于 RESTClient 的封装,同时 ClientSet 是使用预生成的 API 对象与 APIServer 进行交互的,这样做更方便进行二次开发。

ClientSet 是一组资源对象客户端的集合,例如负责操作 Pods、Services 等资源的 CoreV1Client,负责操作 Deployments、DaemonSets 等资源的 AppsV1Client 等。通过这些资源对象客户端提供的操作方法,即可对 Kubernetes 内置的资源对象进行 Create、Update、Get、List、Delete 等操作。

运行以下代码,将得到 default 下的 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 : lanyulei
@Desc :
*/

func main()
// 加载配置文件,生成 config 对象
config, err := clientcmd.BuildConfigFromFlags("", "../../kubeconfig")
if err != nil
panic(err.Error())


// 实例化 ClientSet
clientset, err := kubernetes.NewForConfig(config)
if err != nil
panic(err.Error())


// 查询 default 下的 pods 部门资源信息
pods, err := clientset.
CoreV1(). // 实例化资源客户端,这里标识实例化 CoreV1Client
Pods("default"). // 选择 namespace,为空则表示所有 Namespace
List(context.TODO(), metav1.ListOptions) // 查询 pods 列表
if err != nil
panic(err.Error())


// 输出 Pods 资源信息
for _, item := range pods.Items
fmt.Printf("namespace: %v, name: %v\\n", item.Namespace, item.Name)

输出结果

➜  demo1 go run main.go 
namespace: default, name: 1231-589c58c8c5-27r94
namespace: default, name: 1231-b6896fd77-7bkgk
namespace: default, name: web-96d5df5c8-rcw6r
namespace: default, name: web-96d5df5c8-rdzpr

DynamicClient

DynamicClient 是一种动态客户端,通过动态指定资源组、资源版本和资源等信息,来操作任意的 Kubernetes 资源对象的一种客户端。即不仅仅是操作 Kubernetes 内置的资源对象,还可以操作 CRD。这也是与 ClientSet 最明显的一个区别。

使用 ClientSet 的时候,程序会将所用的版本与类型紧密耦合。而 DynamicClient 使用嵌套的 map[string]interface 结构存储 Kubernetes APIServer 的返回值,使用反射机制,在运行的时候,进行数据绑定,这种方式更加灵活,但是却无法获取强数据类型的检查和验证。

此外,在介绍 DynamicClient 之前,还需要了解另外两个重要的知识点,Object.runtime 接口和 Unstructured 结构体。

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

运行以下代码,将得到 default 下的 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 : lanyulei
@Desc :
*/

func main()
// 加载配置文件,生成 config 对象
config, err := clientcmd.BuildConfigFromFlags("", "../../kubeconfig")
if err != nil
panic(err.Error())


// 实例化 DynamicClient
dynamicClient, err := dynamic.NewForConfig(config)
if err != nil
panic(err.Error())


// 设置要请求的 GVR
gvr := schema.GroupVersionResource
Group: "",
Version: "v1",
Resource: "pods",


// 发送请求,并得到返回结果
unStructData, err := dynamicClient.Resource(gvr).Namespace("default").List(context.TODO(), metav1.ListOptions)
if err != nil
panic(err.Error())


// 使用反射将 unStructData 的数据转成对应的结构体类型,例如这是是转成 v1.PodList 类型
podList := &corev1.PodList
err = runtime.DefaultUnstructuredConverter.FromUnstructured(
unStructData.UnstructuredContent(),
podList,
)
if err != nil
panic(err.Error())


// 输出 Pods 资源信息
for _, item := range podList.Items
fmt.Printf("namespace: %v, name: %v\\n", item.Namespace, item.Name)

输出结果

➜  demo1 go run main.go
namespace: default, name: 1231-589c58c8c5-27r94
namespace: default, name: 1231-b6896fd77-7bkgk
namespace: default, name: web-96d5df5c8-rcw6r
namespace: default, name: web-96d5df5c8-rdzpr

DiscoveryClient

前面咱们介绍了 3 种客户端,都是针对与资源对象管理的。而 DiscoveryClient 则是针对于资源的。用于查看当前 Kubernetes 集群支持那些资源组、资源版本、资源信息。

运行以下代码,将得到 Kubernetes 集群的资源列表。

package main

import (
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
"k8s.io/client-go/tools/clientcmd"
)

/*
@Author : lanyulei
@Desc :
*/

func main()
// 加载配置文件,生成 config 对象
config, err := clientcmd.BuildConfigFromFlags("", "../../kubeconfig")
if err != nil
panic(err.Error())


// 实例化 DiscoveryClient
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
if err != nil
panic(err.Error())


_, apiResources, err := discoveryClient.ServerGroupsAndResources()
if err != nil
panic(err.Error())


for _, list := range apiResources
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)


输出结果

➜  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
...

一文带您了解5g的价值与应用

  一文带您了解5G的价值与应用  5G最有趣的一点是:大多数产品都是先有明确应用场景而后千呼万唤始出来。而5G则不同,即将到来的5G不仅再一次印证了科学技术是第一生产力还给不少用户带来了迷茫——我们为什... 查看详情

一文带您了解区块链五大分类

一、开放技术1、公有链:每个人可参加典型案例:比特币BTC、以太坊ETH特点:系统最为开放,所有人都能够参加区块链数据的维护和读取,易于部署应用程序,完全去中心化不会受到其他机构操纵。2、联... 查看详情

一文带您了解微服务的前生今世

一、微服务的现状及未来1.服务架构的演变1.1单体架构  单体架构应该是我们最先接触到的架构实现了,在单体架构中使用经典的三层模型,即表现层,业务逻辑层和数据访问层。  单体架构只适合在应用初期... 查看详情

一文带您了解微服务的前生今世

一、微服务的现状及未来1.服务架构的演变1.1单体架构  单体架构应该是我们最先接触到的架构实现了,在单体架构中使用经典的三层模型,即表现层,业务逻辑层和数据访问层。  单体架构只适合在应用初期... 查看详情

一文快速带您了解kmmcompose和flutter的现状|开发者说·dtalk

本文原作者:恋猫de小郭,原文发布于:GSYTech又到了喜闻乐见的环节,「本篇主要是科普KMM、Compose和Flutter的最新现状」,对于Compose和Flutter大家可能并不陌生,但是对于KMM也许会存在疑惑,KMM全称KotlinMultiplatformM... 查看详情

一文读懂redis的四种模式,单机主从哨兵集群(代码片段)

前言:redis有多种模式:单机模式、主从模式、哨兵模式、集群模式1.单机模式安装一个redis,启动起来,业务调用即可。单机在很多场景也是有使用的,例如在一个并非必须保证高可用的情况下。优点:部... 查看详情

rabbitmq一文彻底弄懂rabbitmq的四种交换机原理及springboot实战应用(代码片段)

四大交换机工作原理及实战应用交换机概念direct直连交换机工作模式图解springboot代码Fanout扇出交换机工作模式图解springboot代码Topic主题交换机工作模式图解springboot代码header交换机交换机概念交换机可以理解成具有路由表的路由... 查看详情

注意细节,阿里架构师一文详解springdi的四种依赖注入方式

参考技术A2.1了解DI的思想顾名思义,依赖注入是由“依赖”和“注入”两个词汇组合而成,那么我们再一次顺藤摸瓜,分别分析这两个词语!2.2依赖关于谁依赖与谁,当然是应用程序依赖于IOC容器。因为应用程序依赖于IOC容器提... 查看详情

mysql的四种启动方式

mysql的四种启动方式:1、mysqld启动mysql服务器:./mysqld--defaults-file=/etc/my.cnf--user=root客户端连接:mysql--defaults-file=/etc/my.cnformysql-S/tmp/mysql.sock2、mysqld_safe启动mysql服务器:./mysqld_safe--defaults-file=/etc/my 查看详情

spark的四种模式(代码片段)

...的spark集群,不依赖其他集群,分为Master和work。    客户端向Master注册应用,Master向work发送消息,依次启动Driver,executor,Driver负责向executors发送任务 查看详情

深入了解delphi7中的四种消息框

...essage、MessageDlg、Application.MessageBox、MessageBox。下面来深入了解下这四种形式的实现和使用。1.ShowMessage显示一个带"OK"按钮的消息框 使用这个函数可以显示一个简单的带"OK"按钮的消息框,消息框的标题是应用程序的标题名,参... 查看详情

rocketmq(13)——指定nameserver的四种方式(代码片段)

...式无论是生产者还是消费者,对于NameServer来讲它们都是客户端,它们都需要与NameServer进行连接,可以有四种方式指定需要连接的NameServer的地址。通过程序指定这是我们最熟悉的方式,之前进行的介绍都是通过这种方式指定的。... 查看详情

rocketmq(13)——指定nameserver的四种方式(代码片段)

...式无论是生产者还是消费者,对于NameServer来讲它们都是客户端,它们都需要与NameServer进行连接,可以有四种方式指定需要连接的NameServer的地址。通过程序指定这是我们最熟悉的方式,之前进行的介绍都是通过这种方式指定的。... 查看详情

html导出pdf的四种方式

...链接中文特殊字符、样式导出样例备注jsPDF1、整个过程在客户端执行(不需要服务器参与),调用简单1、生成的pdf为图片形式,且内容失真支持支持支持不支持支持支持  查看详情

一文了解「区块链桥」:区块链桥的工作方式及四种类型

区块链桥如何帮助实现不同网络之间的互操作性。区块链桥如何帮助实现不同网络之间的互操作性。近10年前,比特币为区块链奠定了基础。十多年后的今天,有100多个活跃的区块链公共网络存在。然而,当构建在不... 查看详情

rocketmq(13)——指定nameserver的四种方式(代码片段)

...式无论是生产者还是消费者,对于NameServer来讲它们都是客户端,它们都需要与NameServer进行连接,可以有四种方式指定需要连接的NameServer的地址。通过程序指定这是我们最熟悉的方式,之前进行的介绍都是通过这种方式指定的。... 查看详情

你知道web项目中http请求与响应的四种情况吗(代码片段)

...超文本传输协议(HyperTextTransferProtocol--HTTP)是一个设计来使客户端和服务器顺利进行通讯的协议。HTTP在客户端和服务器之间以request-responseprotocol(请求-回复协议)工作。【Http 查看详情

一文快速带您了解kmmcompose和flutter的现状|开发者说·dtalk

本文原作者:恋猫de小郭,原文发布于:GSYTech又到了喜闻乐见的环节,「本篇主要是科普KMM、Compose和Flutter的最新现状」,对于Compose和Flutter大家可能并不陌生,但是对于KMM也许会存在疑惑,KMM全称KotlinMultiplatformM... 查看详情