深入了解 K8s 扩展神器 client-go 的详细用法
1. 简介
当使用 Kubernetes 进行应用程序的开发和部署时,client-go 是一个非常重要的工具。它是 Kubernetes 的官方客户端库,提供了与 Kubernetes ApiServer 进行通信的接口和实现。
client-go 主要提供以下几个功能:
与 Kubernetes ApiServer 进行通信:client-go 提供了与 Kubernetes ApiServer 进行通信的接口和实现,包括基本的 http 请求和更深层次的封装。开发人员可以使用 client-go 创建、更新和删除 Kubernetes 中的资源。 访问 Kubernetes ApiServer 中的资源:client-go 提供了访问 Kubernetes ApiServer 中资源的方法,包括使用 ClientSet 进行基于对象的访问和使用 DynamicClient 进行基于无类型的访问。 处理 Kubernetes 资源的事件:client-go 提供了一种称为 Informer 的机制,它可以监听 Kubernetes ApiServer 中的资源变更事件。开发人员可以使用 Informer 实现资源的快速检索和本地缓存,从而减轻对 ApiServer 的访问压力。 发现 Kubernetes ApiServer 中的资源:client-go 还提供了 DiscoveryClient 接口,该接口可以用于在 Kubernetes ApiServer 中查找特定资源的详细信息。 总的来说,client-go 是 Kubernetes 开发人员不可或缺的工具之一。它提供了丰富的功能和灵活的接口,使开发人员能够更轻松地构建和管理 Kubernetes 应用程序。
2. Client
多种 client 介绍
RESTClient 最基础的客户端,其他的 ClientSet、DyanmicClient、DiscoveryClient 都是基于 RESTClient 实现的
ClientSet 对 k8s 内置资源的客户端集合。如获取 pod 资源对象的 client
clientset.CoreV1().Pods("")
DynamicClient 动态客户端,它可以对任意 k8s 资源进行 RESTful 操作,包括 CRD 资源。与 ClientSet 最大的不同是,ClientSet 仅能访问 k8s 自带的资源,不能直接访问 CRD 资源。
DiscoveryClient 发现客户端,主要用于发现 k8sApiServer 所支持的资源组,资源版本资源信息。
Clientset 和 dynamicClient 都是面向资源对象的(例如创建 deployment 实例、查看 pod 实例),而 DiscoveryClient 则不同,它聚焦的是资源
参考: https://www.cnblogs.com/bolingcavalry/p/15249712.html
加载kubeconfig及各客户端初始化的方法
1package config
2
3import (
4 "k8s.io/client-go/discovery"
5 "k8s.io/client-go/dynamic"
6 "k8s.io/client-go/kubernetes"
7 "k8s.io/client-go/rest"
8 "k8s.io/client-go/tools/clientcmd"
9 "log"
10)
11
12const kubeConfigFilePath = "/Users/ShadowYD/.kube/config"
13
14type K8sConfig struct {
15}
16
17func NewK8sConfig() *K8sConfig {
18 return &K8sConfig{}
19}
20// 读取kubeconfig 配置文件
21func (this *K8sConfig) K8sRestConfig() *rest.Config {
22 config, err := clientcmd.BuildConfigFromFlags("", kubeConfigFilePath)
23 if err != nil {
24 log.Fatal(err)
25 }
26 return config
27}
28// 初始化 clientSet
29func (this *K8sConfig) InitClient() *kubernetes.Clientset {
30 c, err := kubernetes.NewForConfig(this.K8sRestConfig())
31
32 if err != nil {
33 log.Fatal(err)
34 }
35
36 return c
37}
38
39// 初始化 dynamicClient
40func (this *K8sConfig) InitDynamicClient() dynamic.Interface {
41 c, err := dynamic.NewForConfig(this.K8sRestConfig())
42
43 if err != nil {
44 log.Fatal(err)
45 }
46
47 return c
48}
49
50// 初始化 DiscoveryClient
51func (this *K8sConfig) InitDiscoveryClient() *discovery.DiscoveryClient {
52 return discovery.NewDiscoveryClient(this.InitClient().RESTClient())
53}
示例
1package main
2
3import (
4 "context"
5 "flag"
6 "fmt"
7 "path/filepath"
8 "time"
9
10 "k8s.io/apimachinery/pkg/api/errors"
11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12 "k8s.io/client-go/kubernetes"
13 "k8s.io/client-go/tools/clientcmd"
14 "k8s.io/client-go/util/homedir"
15)
16
17func main() {
18 var kubeconfig *string
19 if home := homedir.HomeDir(); home != "" {
20 kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
21 } else {
22 kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
23 }
24 flag.Parse()
25
26 // 获取配置对象
27 config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
28 if err != nil {
29 panic(err.Error())
30 }
31
32 // 创建 clientset
33 clientset, err := kubernetes.NewForConfig(config)
34 if err != nil {
35 panic(err.Error())
36 }
37 for {
38 // 调用list方法时才会请求apiserver
39 pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
40 if err != nil {
41 panic(err.Error())
42 }
43 fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
44
45 // 获取pod信息
46 namespace := "default"
47 pod := "soa-test-service-5fd6fd67fd-7ktdg"
48 _, err = clientset.CoreV1().Pods(namespace).Get(context.TODO(), pod, metav1.GetOptions{})
49 if errors.IsNotFound(err) {
50 fmt.Printf("Pod %s in namespace %s not found\n", pod, namespace)
51 } else if statusError, isStatus := err.(*errors.StatusError); isStatus {
52 fmt.Printf("Error getting pod %s in namespace %s: %v\n",
53 pod, namespace, statusError.ErrStatus.Message)
54 } else if err != nil {
55 panic(err.Error())
56 } else {
57 fmt.Printf("Found pod %s in namespace %s\n", pod, namespace)
58 }
59
60 time.Sleep(10 * time.Second)
61 }
62}
3. Informer
关注点:indexer 、 informer 、事件注册机制等,下面这篇文章写的比较详细,这里不多做赘述。
参考:https://www.cnblogs.com/charlieroro/p/10330390.html