k8s的client-go的使用

学习地址:https://github.com/kubernetes/client-go
如果你要安装最新的需要的环境是: go1.16+ ,使用下面的命令安装:

go get k8s.io/client-go@latest

​ client-go 是用 Golang 语言编写的官方编程式交互客户端库,提供对 Kubernetes API server 服务的交互访问。它是 Kubernetes 的核心处理框架,k8s源码中已经集成了client-go的源码,无需单独下载。源码路径为:vendor/k8s.io/client-go。

​ k8s开发者使用client-go做二次开发,所以应该熟练掌握。

1、client-go源码结构

其源码目录结构如下:

  1. discovery: 提供 DiscoveryClient 发现客户端。

  2. dynamic: 提供 DynamicClient 动态客户端。

  3. informers: 每种 K8S 资源的 Informer 实现。

  4. kubernetes: 提供 ClientSet 客户端。

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

  6. plugin: 提供 OpenStack,GCP 和 Azure 等云服务商授权插件。

  7. rest: 提供 RESTClient 客户端,对 K8S API Server 执行 RESTful 操作。

  8. scale: 提供 ScaleClient 客户端,用于扩容或缩容 Deployment, Replicaset, Replication Controller 等资源对象。

  9. tools: 提供常用工具,例如 SharedInformer, Relector, DealtFIFO 及 Indexers。 提供 Client 查询和缓存机制,以减少想 kube-apiserver 发起的请求数等。主要子目录为 /tools/cache。

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

  11. util: 提供常用方法。例如 WorkQueue 工作队列,Certificate 证书管理等。

这章我们只简单介绍下RESTClient、DiscoveryClient、DynamicClient、ClientSet这4中客户端。

2、Client客户端对象

client-go 支持4种Client客户端对象 与 k8s api server 交互的方式,Client交互对象如下图所示:
image
RESTClient 是最基础的客户端。RESTClient 对 HTTP Request 进行了封装,实现了RESTful风格的api。ClientSet、DynamicClient及DiscoveryClient客户端都是基于RESTClient 实现的。

  • RESTClient 客户端

    ​ RESTful Client 是最基础的客户端,它主要是对 HTTP 请求进行了封装,并且支持 JSON 和 Protobuf 格式数据。

  • DynamicClient 客户端

    ​ DynamicClient 与 ClientSet 最大的不同之处是,ClientSet 仅能访问k8s自带的资源,不能直接访问CRD自定义资源。DynamicClient 能处理k8s中的所有的资源对象,包括内置资源与CRD自定义资源。

  • ClientSet 客户端

    ​ ClientSet 客户端在 RESTClient 的基础上封装了对资源(Resource)和版本(Version)的管理方法。每个资源(Resource)可以理解为一个客户端,而 ClientSet 则是多个客户端的集合,每一个资源(Resource)和版本(Version)都以函数的方式暴露给开发者。ClientSet 只能处理k8s内置资源。

  • DiscoveryClient 客户端

    ​ DiscoveryClient 发现客户端,用于发现 kube-apiserver 所支持的资源组、资源版本、资源信息(即Group、Versions、Resources)

​ 以上4种客户端:RESTClient 、DynamicClient 、ClientSet 、DiscoveryClient 都可以通过kubeconfig配置信息连接到指定的 kubernetes api server。

3、kubeconfig配置管理

kubeconfig 用于管理访问 kube-apiserver 的配置信息,k8s的其他组件都使用 kubeconfig 配置信息来连接 kube-apiserver组件,例如:kubectl 访问 kube-apiserver 时,会默认加载 kubeconfig 配置信息。

​ kubeconfig 中存储了集群、用户、命名空间和身份验证等信息,在默认情况下,kubeconfig 存在在$HOME/.kube/config路径下。配置信息如下:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1URXhOakE0TXpJeU5Gb1hEVE14TVRFeE5EQTRNekl5TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS0krClAyV3A1RDlTSk1NZllTNU1QMnFsQWx0MTh3OVptSkhjUlRxQ3R5Mms1NVloaVNrTzBXYzFaVEd2ZHZId0FqWjMKWnRFUVRwUFp0bXBaL3BUUEtNUkx5U1ZObU9PMjZhb2d0dTZJclpKbzMrQzVhTk9zQzVtTUZIUDRCcGE2aUk4Mwp0VWlORVRCRjhBbTlGdW9SVGhkZlVTelVNdUF6ZlJ5ZXU4L0NKcW4rVXJ5UjRhSE9ncHJxNmptNXZubDVqbUxoCnVMQjN5VTRMRVJUZDBmRWJIa09uRnR3cG42OEpOVnZLck1vajc3aHJ3RGdaTEVQQ0dQU0dxNEJ5dkRKQjhIWEoKb3JhUFBJVWNiNDlFcmx2TzJHOXFnODZDUWV4NEpBWEpSTldjcjlsblJtaEdoTkJwc1VXZ3VFRm1iMUxINjREdwpsMWVqbENURXJqblNqNjRZLzJzQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFJbDhJaStKWW1YOWdlVjVxaDUvWStIRFRhbjAKR2VldldQamtvdnFza0dReW1PT0hIak4rRHdPK2dZemVodGNUSUtPWVQvczhjOFlEUm1GTng4ZUI4RWVTRkJNaQpBWnMzaUE4b0NFTkdQUGF3QWdDbEFBTGp0SmNLOXR4RHdGdm5WcUsrUGk3bW52cmJtUVhxQzJRS1JRcEQ1VnlpCjZFeWRQdGlFZWRvSm93ZC9rdHh2UVlDSitGZFRBZHl3VVlxQzk1UDBLczhUanpEUDNaRVZnYkJER05kT0hIWVcKUXNOeG5DaDB0ZlpEbkl6ZCtCZ25SSDNLL1c0bWVCOXpYTzFrWVNLK2NGbFduWG40OUo1QmlEMkI3ZHk3eWt1Kwo0MUdvdGVrSjc3NXIySFlyR2dmaG9mYWtCenZnZEV2U1J0Y243OVkwTkZ6dmhUeFZIRWp5VExqTEY4TT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    server: https://127.0.0.1:16443
  name: cluster-10.9.244.32
contexts:
- context:
    cluster: cluster-10.9.244.32
    user: kubernetes-admin
  name: kubernetes-admin@cluster-10.9.244.32
current-context: kubernetes-admin@cluster-10.9.244.32
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJQ3p5OXR6SzhhclV3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TVRFeE1UWXdPRE15TWpSYUZ3MHlNakV4TVRZd09ETXlNalphTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXZ2UnhDaHVzblo1MU1zYU0KN01FZkVaUzdFb3ZlZUZTRTJ2MVZtOWt2U3dpVzVUclhqOG1LdWFjVWszZVdBMDdmVHdjMkJ3ZjNjVEFNazAxTQpHbU41bzEvcFdkam40TjdsdmxkeEZKclVVVkZGK3k4SUxySkVVdUhWdEtLUHZkM29jakxBTktwbGRCcWtrTTZVCmlKL0JKa3lvOXpPUWpBN0dUVmtBdTlQaFNDRktQUVhibjZHUUIrZW1LN1cxTFRkM1diQ2tacGE2NjVpUWhLRzMKKzhRMXJlMHFzcm9kQzNnV0Vna0N5TjNRUzIwRGowa0drMzJvWkp3Zkx5cUJOaUFNVzZ2azRpVjJqaEFTWDRYSwpEZ3pQVUNOUDFSSFkxZitkTEtBNzhoNXMremhTUi93VkxXajVPUlIvZ1hhcFRtZG80dy84NEpKbExwTWVScXJGCjQ0Y1Rhd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKNWZQMHVScWJhbkJLTnl5eVErVzVmaExQejYzK0hEVGNiTgptUTlKdFlNUk1MN3hkWkxRVXM1T1N1cWo4QWNiMWNXSXFNNkRhUmJVc2dlTFh6SEg3WDJjUzF5T1gvSFJ5L0ZPClBKdFcwRlhkbVhWWE1PbU5JWldwVWRmT08vYkx2eURhY2N4RkZ6alFkVksvdmg5Q2VqNkYvWnpVWXdkVlQ1eXQKenVYZ2llV2VxTFpzT1hZMlhyWmN5Vzg4Ky9VYUVaczdYR01xVEhSYjlUQi9iTTlxL0FnWHRscThlZEZvS1JkZwpYd2hFY0RzOWZuS2RwSG13QlVkV1lDcDFNNmVzamtObk9mMVU4Rk9OeXdUNm5xVG52VkgzQ1UzTkQxMSs5Y2IyCm1qSmVXK0QrRUd1VXZTR2tSamdLY1VYS1NCWXhwVWFoOWFWWGN3RjNnakhxa1RaaHZ0VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdnZSeENodXNuWjUxTXNhTTdNRWZFWlM3RW92ZWVGU0UydjFWbTlrdlN3aVc1VHJYCmo4bUt1YWNVazNlV0EwN2ZUd2MyQndmM2NUQU1rMDFNR21ONW8xL3BXZGpuNE43bHZsZHhGSnJVVVZGRit5OEkKTHJKRVV1SFZ0S0tQdmQzb2NqTEFOS3BsZEJxa2tNNlVpSi9CSmt5bzl6T1FqQTdHVFZrQXU5UGhTQ0ZLUFFYYgpuNkdRQitlbUs3VzFMVGQzV2JDa1pwYTY2NWlRaEtHMys4UTFyZTBxc3JvZEMzZ1dFZ2tDeU4zUVMyMERqMGtHCmszMm9aSndmTHlxQk5pQU1XNnZrNGlWMmpoQVNYNFhLRGd6UFVDTlAxUkhZMWYrZExLQTc4aDVzK3poU1Ivd1YKTFdqNU9SUi9nWGFwVG1kbzR3Lzg0SkpsTHBNZVJxckY0NGNUYXdJREFRQUJBb0lCQUdKYURwclJOREFldkdpQgpvWFlUNWdldEhrbG9KeGE5R1l5ZGJPbVBqRzlPSmtJODgyZ0l1MTN4ODRRYzFQUXhQSTA4dnBRU2cxMFdEWFFWCkhQeCtmZGtxL2txYmtKcmUwMkFkTTQ0VVRRVHhJbVZFalNkWUJCN1lXTFRvQWJjZVE2b0YvNzlnZ0U2enBrMDcKU1greElNKzBMbGJjaFRmT0tFOFFaM05XcHpMNXBWTEh2eEFyYWNNMWg0K1d4NDZnNHJRN3JwS1BUa2VFa1loYwo3amE2TWl6UjEvZDFUNERqa2JGUnU3SVNSNVpvWithL0o2dGkzSStoc0lqaU0yeE5sQ0Y0MXVZa0lDSkhnMkZYCnlyZkYwZm1YS2c1T1oweWFHTUhTdUNpbE9UUUlnYndMN3RMMWR0bU5YaTBvTzdZbXF5MHFaSVdlV1BRVitJUWkKOXREdXFVa0NnWUVBOXg2TzJCaVBqdzAyUENYQ0xhcHZpVHNCeFRmNVFCbVpkZlEvNFJubGY1T3IwZ2ZmdmgzbApNUDBYYUZraWdaUW83NmJvZlFRd0VNZWdnRkFXNkhFSkVOQTd4Z2NsVlFxTHVST2pUTVNkRVUraUl1eXZ0VFZmClJZYTUxODdCTEFwWThnRHQzQjhjVlN6RGQvdlIrVmJ4MFNJVGdTbVFGSUdtdC9TWmdnMFp4cjhDZ1lFQXhkRXUKeXIwaUxHNWtyRHN3VmxVc3RsU2lHQmxBZEhOMld1eEFncmw5UTdSWEt0V3B0allqTnhMdVJoU1dLOEYzYjBlQwoyaUQxWTljMkgyNmJYelA1OEorTkZyMmNzYmJKdFNmWi9xcXE3Q3V0K2liUng1Q0IyQm1UZDVpWWhqWTNRUjQzCnlOWFhhR2dzUzFQQWt6Q1dVcmVuVHh6bzFBNzRnN05PZjhLVGFsVUNnWUFOaDNyQ2tmV3FHMHNRMS9CZGw2c3IKbEROd25MUGtzb0lZVnhyNE0vYkFtVkVhMnB1QlNSbTNLT1FUTG00Wk1nZGJ0NE9hOUpPOUYzRE9GWlJyZldURgpxdURhNHFGRW1xTXpxc09SL0dHdEJQTVhmbVhRUWUvSldxcnFDY1BCcVg5ZElIZmxTVDYvMndlSWxoelV6ZEhIClpWbzBCQmFEU09YYnhHUnpIa3grK1FLQmdDeXZOL2FzQ3BBbXo2N29IOThnbGwwSmVTUWdjQ0xlQWhvL3k4SzcKeThRRGRMMUVUblhPZk4zdjlNcjMwNFJHeTRmamkzZGlnb3Z2RFZiRVVXeUwvU1dScFBsQ0U2ZEJOd2NvM1dGZApoQWFkUjB0K2dWeW5FKzJRdVhNR2tVMmY2Wk5ZRkJuVjFEYk5jVlFDc3ptTWZDaHJPK3Z2QjlqL0dMd0hRUEF6Ckw4R1JBb0dCQVBVSnZ5NHlsRG1TdkJheFZrdGdXRjRYc096cytCR0sweFI0VEdZa0JNODhRTHFLTVU1RFZCV3MKdjVQQ2xFMVcxOHVJWkZMTzdGUXd5U1ZwZ0cwZ3NOcVBDRjdwVVZmRjg0VkFiWmxCdGJNSWdCcFRIMjU0M2FHegpQMGZNdnFEaU91bksxa0VaWDh4YkdMTHFXZjBBTGgwUkVmbDBTL3pmZ1RDUDBzTTZtKzdJCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==

kubeconfig配置信息通常包含3个部分,分别介绍如下:

  • clusters:定义kubernetes集群信息,例如kube-apiserver 的服务地址及集群的证书信息等。
  • users:定义kubernetes集群用户身份验证的客户端凭据,例如 client-certificate、client-key等信息。
  • contexts:定义kubernetes集群用户信息和命名空间等,用于将请求发送到指定的集群。

client-go会读取 kubeconfig 配置信息并生成config对象,用于与kube-apiserver通讯,代码如下:

config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
if err != nil {
    panic(err.Error())
}

在上述代码中,clientcmd.BuildConfigFromFlags 函数会读取kubeconfig配置信息并实例化 rest.Config 对象。

4、RESTClient客户端

RESTClient是最基础的客户端,其他的客户端都是基于它实现的。RESTClient对HTTP Request 进行了封装,实现了Restful 风格的api。

​ 类似于kubectl命令,通过RESTClient列出所有运行pod资源对象,代码如下:

package main

import (
    "flag"
    "fmt"
    "context"
    "k8s.io/client-go/rest"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
    "path/filepath"
    "k8s.io/client-go/kubernetes/scheme"
    corev1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

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)
    if err != nil {
        panic(err.Error())
    }

    config.APIPath = "api"
    config.GroupVersion = &corev1.SchemeGroupVersion
    config.NegotiatedSerializer = scheme.Codecs

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

    result := &corev1.PodList{}
    err = restClient.Get().
        Namespace("whalebase").
        Resource("pods").
        VersionedParams(&metav1.ListOptions{Limit: 500}, scheme.ParameterCodec).
        Do(context.TODO()).
        Into(result)

    for _, d := range result.Items {
        fmt.Printf("namespace:%v \t name:%v \t status:%+v\n", d.Namespace, d.Name, d.Status.Phase)
    }
}

运行以上代码,列出 whalebase 命名空间下所有 pod 资源对象的相关信息。首先加载 kubeconfig 配置信息,并设置 config.APIPath 请求的 HTTP 路径。然后设置 config.GroupVersion 请求的资源组/资源版本。最后设置 config.NegotiatedSerializer 数据的编解码器。

​ rest.RESTClientFor 函数通过 kubeconfig 配置信息实例化 RESTClient 对象,RESTClient 对象构建 HTTP 请求参数,例如GET函数设置请求方法为get操作,它还支持post、put、delete、patch 等请求方法。Namespace 函数设置命名空间。 Resource 函数设置请求的资源名称。VersionedParams 函数将一些查询选项(如limit、TimeoutSeconds等)添加到请求参数中。通过Do函数执行该请求,并将 kube-apiserver 返回的结果(Result对象)解析到 corev1.PodList 对象中。最终格式化输出结果。

5、ClientSet 客户端

RESTClient 最基础的客户端,使用时需要指定 Resource 和 Version 等信息,编写代码时需要提前知道 Resource 所在的 Group 和对应的 Version 信息。相比 RESTClient ,ClientSet 使用起来更加便捷,一般情况下,开发者对kubernetes进行二次开发时通常使用 ClientSet。

ClientSet 在 RESTClient 的基础上封装了对 Resource 和 Version 的管理方法。每一个 Resource 可以理解为一个客户端, 而ClientSet 则是多个客户端的集合,每一个 Resource 和 Version 都以函数的形式暴露给开发者。例如 ClientSet 提供的 RbacV1、CoreV1、NetworkingV1 等接口函数,多个 ClientSet 多资源集合如下图:
image
与 api-server 交互,示例代码如下:

package main

import (
    "context"
    "flag"
    "fmt"
    v1 "k8s.io/api/core/v1"
    "k8s.io/apimachinery/pkg/api/errors"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/util/json"
    "k8s.io/client-go/kubernetes"
    "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)
    if err != nil {
        panic(err.Error())
    }

    // create the clientset
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
    if err != nil {
        panic(err.Error())
    }
    fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))

    // 获取mysql的pod
    namespace := "whalebase"
    pod := "mysql-0"
    mysqlPod, err := clientset.CoreV1().Pods(namespace).Get(context.TODO(), pod, metav1.GetOptions{})
    if errors.IsNotFound(err) {
        fmt.Printf("Pod %s in namespace %s not found\n", pod, namespace)
    } else if statusError, isStatus := err.(*errors.StatusError); isStatus {
        fmt.Printf("Error getting pod %s in namespace %s: %v\n",
            pod, namespace, statusError.ErrStatus.Message)
    } else if err != nil {
        panic(err.Error())
    } else {
        fmt.Printf("Found pod %s in namespace %s\n", pod, namespace)
        bytes, _ := json.Marshal(mysqlPod)
        fmt.Println("pod信息:",string(bytes))
    }

    fmt.Println("--------------------------------")
    // 获取mysql的StatefulSets
    sts, _ := clientset.AppsV1().StatefulSets(namespace).Get(context.TODO(), "mysql", metav1.GetOptions{})
    bytes, _ := json.Marshal(sts)
    fmt.Println("sts信息:",string(bytes))
    fmt.Println("--------------------------------")
    //创建pod
    var nginxPod *v1.Pod = &v1.Pod {
        TypeMeta: metav1.TypeMeta{Kind:"Pod",APIVersion:"v1"},
        ObjectMeta: metav1.ObjectMeta{Name:"nginx-pod"},
        Spec: v1.PodSpec{
            Containers: []v1.Container{
                v1.Container{
                    Name: "nginx",
                    Image: "nginx:1.8",
                },
            },
        },
    }
    _, err = clientset.CoreV1().Pods("default").Create(context.TODO(), nginxPod, metav1.CreateOptions{})
    if err != nil {
        fmt.Println(err)
    }
}

6、DynamicClient 客户端

DynamicClient 是一种动态客户端,它可以与任意 kubernetes 资源进行 RESTful 操作,包括 CRD 自定义资源。DynamicClient 与 ClientSet 操作类似,同样封装了RESTClient,同样提供了Create、Update、Get、List、Watch、Patch 等方法。

​ DynamicClient 与 ClientSet 最大的不同之处是,ClientSet 仅能访问 kubernetes 自带的资源,不能访问 CRD 自定义资源。 ClientSet 需要预先 实现每种 Resource、Version 的操作,其内部都是结构化数据(即已知数据结构)。而 DynamicClient 内部实现了 Unstructured,用于处理非结构化数据结构(即无法预先提前预知数据结构),这也是 DynamicClient 能够处理CRD自定义资源的关键。

​ DynamicClient 的处理过程将 Resource (例如PodList)转换成 Unstructured 结构类型, kubernetes 的所有 Resource 都可以转化成该结构类型。处理完成后,再将 Unstructured 转换成 PodList 。整个过程类似于Go语言的interface{}断言转换过程,另外, Unstructured 结构类型是通过 map[string]interface{} 转换的。

package main

import (
    "context"
    "flag"
    "fmt"
    "k8s.io/apimachinery/pkg/runtime"
    "k8s.io/client-go/dynamic"
    "k8s.io/client-go/tools/clientcmd"
    "path/filepath"
    "k8s.io/client-go/util/homedir"
    corev1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/runtime/schema"
)

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)
    if err != nil {
        panic(err.Error())
    }

    dynamicClient, err := dynamic.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    gvr := schema.GroupVersionResource{Version: "v1",Resource: "pods"}
    unstructuredList, err := dynamicClient.Resource(gvr).Namespace("whalebase").List(context.TODO(), metav1.ListOptions{Limit: 500})
    if err != nil {
        panic(err.Error())
    }

    podList := &corev1.PodList{}
    err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredList.UnstructuredContent(),podList)
    if err != nil {
        panic(err.Error())
    }

    for _, d := range podList.Items {
        fmt.Printf("namespace:%v \t name:%v \t status:%+v\n", d.Namespace, d.Name, d.Status.Phase)
    }
}

dynamicClient.Resource(gvr) 函数用于设置请求的资源组、资源版本、资源名称。Namespace 函数用于设置请求的命名空间。List 函数用于获取 pod 列表。得到的pod列表为 unstructured.UnstructuredList 指针类型,然后通过 runtime.DefaultUnstructuredConverter 函数将 unstructured.UnstructuredList 转换成 PodList 类型。

7、DiscoveryClient客户端

DiscoveryClient 是发现客户端,它主要用于发现 Kubernetes API Server 所支持的资源组、资源版本、资源信息,开发者在开发过程中很难记住所有的信息,此时可以通过 DiscoveryClient 查看所支持的资源组、资源版本、资源信息。

​ kubectl api-versions 和 api-resources 命令输出也是通过 DiscoveryClient 实现的。另外, DiscoveryClient 同样在 RESTClient 的基础上进行了封装。

​ DiscoveryClient 除了可以发现 Kubernetes API Server 所支持的资源组、资源版本、资源信息,还可以将这些信息存储到本地,用于本地缓存(Cache),以减轻对 Kubernetes API Server 访问的压力。在运行 Kubernetes 组件的机器删,缓存信息默认存储于~/.kube/cache 和 ~/.kube/http-cache 下。

​ 类似于kubectl命令,通过 DiscoveryClient 列出 Kubernetes API Server 所支持的资源组、资源版本、资源信息,代码如下:

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)
    if err != nil {
        panic(err.Error())
    }

    discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    _, APIResourceList, err := discoveryClient.ServerGroupsAndResources()
    if err != nil {
        panic(err.Error())
    }

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

运行以上代码,列出 Kubernetes API Server 所支持的资源组、资源版本、资源信息。首先加载 kubeconfig 配置信息,discovery.NewDiscoveryClientForConfig 通过 kubeconfig 配置信息实例化 discoveryclient 对象,该对象是用于发现 Kubernetes API Server 所支持的资源组、资源版本、资源信息的客户端。

​ discoveryClient.ServerGroupsAndResources 函数会返回 Kubernetes API Server 所支持的 资源组、资源版本、资源信息(即APIResourceList),通过遍历 APIResourceList 输出信息。

posted @ 2022-04-04 21:44  liweiboy  阅读(5135)  评论(0编辑  收藏  举报