含林 發表於 2022-4-4 21:44:00

k8s的client-go的使用

<p>学习地址:https://github.com/kubernetes/client-go<br>
如果你要安装最新的需要的环境是: go1.16+ ,使用下面的命令安装:</p>
<pre><code class="language-shell">go get k8s.io/client-go@latest
</code></pre>
<p>​ client-go 是用 Golang 语言编写的官方编程式交互客户端库,提供对 Kubernetes API server 服务的交互访问。它是 Kubernetes 的核心处理框架,k8s源码中已经集成了client-go的源码,无需单独下载。源码路径为:vendor/k8s.io/client-go。</p>
<p>​ k8s开发者使用client-go做二次开发,所以应该熟练掌握。</p>
<h4 id="1client-go源码结构">1、client-go源码结构</h4>
<p>其源码目录结构如下:</p>
<ol>
<li>
<p><strong>discovery</strong>: 提供 DiscoveryClient 发现客户端。</p>
</li>
<li>
<p><strong>dynamic</strong>: 提供 DynamicClient 动态客户端。</p>
</li>
<li>
<p><strong>informers</strong>: 每种 K8S 资源的 Informer 实现。</p>
</li>
<li>
<p><strong>kubernetes</strong>: 提供 ClientSet 客户端。</p>
</li>
<li>
<p><strong>listers</strong>: 为每一个 K8S 资源提供 Lister 功能,该功能对 Get 和 List 请求提供只读的缓存数据。</p>
</li>
<li>
<p><strong>plugin</strong>: 提供 OpenStack,GCP 和 Azure 等云服务商授权插件。</p>
</li>
<li>
<p><strong>rest</strong>: 提供 RESTClient 客户端,对 K8S API Server 执行 RESTful 操作。</p>
</li>
<li>
<p><strong>scale</strong>: 提供 ScaleClient 客户端,用于扩容或缩容 Deployment, Replicaset, Replication Controller 等资源对象。</p>
</li>
<li>
<p><strong>tools</strong>: 提供常用工具,例如 SharedInformer, Relector, DealtFIFO 及 Indexers。 提供 Client 查询和缓存机制,以减少想 kube-apiserver 发起的请求数等。主要子目录为 /tools/cache。</p>
</li>
<li>
<p><strong>transport</strong>: 提供安全的 TCP 连接,支持 HTTP Stream,某些操作需要在客户端和容器之间传输二进制流,例如 exec,attach 等操作。该功能由内部的 SPDY 包提供支持。</p>
</li>
<li>
<p><strong>util</strong>: 提供常用方法。例如 WorkQueue 工作队列,Certificate 证书管理等。</p>
</li>
</ol>
<p>这章我们只简单介绍下RESTClient、DiscoveryClient、DynamicClient、ClientSet这4中客户端。</p>
<h4 id="2client客户端对象">2、Client客户端对象</h4>
<p>client-go 支持4种Client客户端对象 与 k8s api server 交互的方式,Client交互对象如下图所示:<br>
<img src="https://img2022.cnblogs.com/blog/2828750/202204/2828750-20220404213955273-752107809.png"><br>
RESTClient 是最基础的客户端。RESTClient 对 HTTP Request 进行了封装,实现了RESTful风格的api。ClientSet、DynamicClient及DiscoveryClient客户端都是基于RESTClient 实现的。</p>
<ul>
<li>
<p><strong>RESTClient 客户端</strong></p>
<p>​ RESTful Client 是最基础的客户端,它主要是对 HTTP 请求进行了封装,并且支持 JSON 和 Protobuf 格式数据。</p>
</li>
<li>
<p><strong>DynamicClient 客户端</strong></p>
<p>​ DynamicClient 与 ClientSet 最大的不同之处是,ClientSet 仅能访问k8s自带的资源,不能直接访问CRD自定义资源。DynamicClient 能处理k8s中的所有的资源对象,包括内置资源与CRD自定义资源。</p>
</li>
<li>
<p><strong>ClientSet 客户端</strong></p>
<p>​ ClientSet 客户端在 RESTClient 的基础上封装了对<strong>资源</strong>(Resource)和<strong>版本</strong>(Version)的管理方法。每个<strong>资源</strong>(Resource)可以理解为一个客户端,而 ClientSet 则是多个客户端的集合,每一个<strong>资源</strong>(Resource)和<strong>版本</strong>(Version)都以函数的方式暴露给开发者。ClientSet 只能处理k8s内置资源。</p>
</li>
<li>
<p><strong>DiscoveryClient 客户端</strong></p>
<p>​ DiscoveryClient 发现客户端,用于发现 kube-apiserver 所支持的资源组、资源版本、资源信息(即Group、Versions、Resources)</p>
</li>
</ul>
<p>​ 以上4种客户端:RESTClient 、DynamicClient 、ClientSet 、DiscoveryClient 都可以通过kubeconfig配置信息连接到指定的 kubernetes api server。</p>
<h4 id="3kubeconfig配置管理">3、kubeconfig配置管理</h4>
<p>kubeconfig 用于管理访问 kube-apiserver 的配置信息,k8s的其他组件都使用 kubeconfig 配置信息来连接 kube-apiserver组件,例如:kubectl 访问 kube-apiserver 时,会默认加载 kubeconfig 配置信息。</p>
<p>​ kubeconfig 中存储了集群、用户、命名空间和身份验证等信息,在默认情况下,kubeconfig 存在在$HOME/.kube/config路径下。配置信息如下:</p>
<pre><code class="language-yaml">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==
</code></pre>
<p>kubeconfig配置信息通常包含3个部分,分别介绍如下:</p>
<ul>
<li>clusters:定义kubernetes集群信息,例如kube-apiserver 的服务地址及集群的证书信息等。</li>
<li>users:定义kubernetes集群用户身份验证的客户端凭据,例如 client-certificate、client-key等信息。</li>
<li>contexts:定义kubernetes集群用户信息和命名空间等,用于将请求发送到指定的集群。</li>
</ul>
<p>client-go会读取 kubeconfig 配置信息并生成config对象,用于与kube-apiserver通讯,代码如下:</p>
<pre><code class="language-golang">config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
if err != nil {
    panic(err.Error())
}
</code></pre>
<p>在上述代码中,clientcmd.BuildConfigFromFlags 函数会读取kubeconfig配置信息并实例化 rest.Config 对象。</p>
<h4 id="4restclient客户端">4、RESTClient客户端</h4>
<p>RESTClient是最基础的客户端,其他的客户端都是基于它实现的。RESTClient对HTTP Request 进行了封装,实现了Restful 风格的api。</p>
<p>​ 类似于kubectl命令,通过RESTClient列出所有运行pod资源对象,代码如下:</p>
<pre><code class="language-golang">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 = &amp;corev1.SchemeGroupVersion
    config.NegotiatedSerializer = scheme.Codecs

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

    result := &amp;corev1.PodList{}
    err = restClient.Get().
      Namespace("whalebase").
      Resource("pods").
      VersionedParams(&amp;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)
    }
}
</code></pre>
<p>运行以上代码,列出 whalebase 命名空间下所有 pod 资源对象的相关信息。首先加载 kubeconfig 配置信息,并设置 config.APIPath 请求的 HTTP 路径。然后设置 config.GroupVersion 请求的资源组/资源版本。最后设置 config.NegotiatedSerializer 数据的编解码器。</p>
<p>​ rest.RESTClientFor 函数通过 kubeconfig 配置信息实例化 RESTClient 对象,RESTClient 对象构建 HTTP 请求参数,例如GET函数设置请求方法为get操作,它还支持post、put、delete、patch 等请求方法。Namespace 函数设置命名空间。 Resource 函数设置请求的资源名称。VersionedParams 函数将一些查询选项(如limit、TimeoutSeconds等)添加到请求参数中。通过Do函数执行该请求,并将 kube-apiserver 返回的结果(Result对象)解析到 corev1.PodList 对象中。最终格式化输出结果。</p>
<h4 id="5clientset-客户端">5、ClientSet 客户端</h4>
<p>RESTClient 最基础的客户端,使用时需要指定 Resource 和 Version 等信息,编写代码时需要提前知道 Resource 所在的 Group 和对应的 Version 信息。相比 RESTClient ,ClientSet 使用起来更加便捷,一般情况下,开发者对kubernetes进行二次开发时通常使用 ClientSet。</p>
<p>ClientSet 在 RESTClient 的基础上封装了对 Resource 和 Version 的管理方法。每一个 Resource 可以理解为一个客户端, 而ClientSet 则是多个客户端的集合,每一个 Resource 和 Version 都以函数的形式暴露给开发者。例如 ClientSet 提供的 RbacV1、CoreV1、NetworkingV1 等接口函数,多个 ClientSet 多资源集合如下图:<br>
<img src="https://img2022.cnblogs.com/blog/2828750/202204/2828750-20220404214222353-1098186604.png"><br>
与 api-server 交互,示例代码如下:</p>
<pre><code class="language-golang">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 = &amp;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)
    }
}
</code></pre>
<h4 id="6dynamicclient-客户端">6、DynamicClient 客户端</h4>
<p>DynamicClient 是一种动态客户端,它可以与任意 kubernetes 资源进行 RESTful 操作,包括 CRD 自定义资源。DynamicClient 与 ClientSet 操作类似,同样封装了RESTClient,同样提供了Create、Update、Get、List、Watch、Patch 等方法。</p>
<p>​ DynamicClient 与 ClientSet 最大的不同之处是,ClientSet 仅能访问 kubernetes 自带的资源,不能访问 CRD 自定义资源。 ClientSet 需要预先 实现每种 Resource、Version 的操作,其内部都是结构化数据(即已知数据结构)。而 DynamicClient 内部实现了 Unstructured,用于处理非结构化数据结构(即无法预先提前预知数据结构),这也是 DynamicClient 能够处理CRD自定义资源的关键。</p>
<p>​ DynamicClient 的处理过程将 Resource (例如PodList)转换成 Unstructured 结构类型, kubernetes 的所有 Resource 都可以转化成该结构类型。处理完成后,再将 Unstructured 转换成 PodList 。整个过程类似于Go语言的interface{}断言转换过程,另外, Unstructured 结构类型是通过 mapinterface{} 转换的。</p>
<pre><code class="language-golang">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 := &amp;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)
    }
}
</code></pre>
<p>dynamicClient.Resource(gvr) 函数用于设置请求的资源组、资源版本、资源名称。Namespace 函数用于设置请求的命名空间。List 函数用于获取 pod 列表。得到的pod列表为 unstructured.UnstructuredList 指针类型,然后通过 runtime.DefaultUnstructuredConverter 函数将 unstructured.UnstructuredList 转换成 PodList 类型。</p>
<h4 id="7discoveryclient客户端">7、DiscoveryClient客户端</h4>
<p>DiscoveryClient 是发现客户端,它主要用于发现 Kubernetes API Server 所支持的资源组、资源版本、资源信息,开发者在开发过程中很难记住所有的信息,此时可以通过 DiscoveryClient 查看所支持的资源组、资源版本、资源信息。</p>
<p>​ kubectl api-versions 和 api-resources 命令输出也是通过 DiscoveryClient 实现的。另外, DiscoveryClient 同样在 RESTClient 的基础上进行了封装。</p>
<p>​ DiscoveryClient 除了可以发现 Kubernetes API Server 所支持的资源组、资源版本、资源信息,还可以将这些信息存储到本地,用于本地缓存(Cache),以减轻对 Kubernetes API Server 访问的压力。在运行 Kubernetes 组件的机器删,缓存信息默认存储于~/.kube/cache 和 ~/.kube/http-cache 下。</p>
<p>​ 类似于kubectl命令,通过 DiscoveryClient 列出 Kubernetes API Server 所支持的资源组、资源版本、资源信息,代码如下:</p>
<pre><code class="language-golang">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)
      }
    }
}
</code></pre>
<p>运行以上代码,列出 Kubernetes API Server 所支持的资源组、资源版本、资源信息。首先加载 kubeconfig 配置信息,discovery.NewDiscoveryClientForConfig 通过 kubeconfig 配置信息实例化 discoveryclient 对象,该对象是用于发现 Kubernetes API Server 所支持的资源组、资源版本、资源信息的客户端。</p>
<p>​ discoveryClient.ServerGroupsAndResources 函数会返回 Kubernetes API Server 所支持的 资源组、资源版本、资源信息(即APIResourceList),通过遍历 APIResourceList 输出信息。</p><br><br>
来源:https://www.cnblogs.com/liweiboy/p/16100627.html
頁: [1]
查看完整版本: k8s的client-go的使用