client-go實戰之五:DiscoveryClient


歡迎訪問我的GitHub

https://github.com/zq2599/blog_demos

內容:所有原創文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;

關於DiscoveryClient

  • 本文是《client-go實戰》系列的第五篇,主角是最后一種客戶端:DiscoveryClient,咱們之前學習的Clientset和dynamicClient都是面向資源對象的(例如創建deployment實例、查看pod實例),而DiscoveryClient則不同,它聚焦的是資源,例如查看當前kubernetes有哪些Group、Version、Resource,下面是DiscoveryClient數據結構的字段和關聯方法,再次看到了熟悉的restClient字段,還有一眾方法皆是與Group、Version、Resource有關:

在這里插入圖片描述

  • 從上圖可見,DiscoveryClient數據結構有兩個字段:restClient和LegacyPrefix,這個LegacyPrefix是啥呢?去看看新建DiscoveryClient實例的方法,如下圖紅框,原來是個固定字符串/api,看起來像是url中的一部分:

在這里插入圖片描述

  • 挑一個DiscoveryClient的關聯方法看看,如下圖紅框,果然,LegacyPrefix就是url中的一部分:

在這里插入圖片描述

  • 相比其他幾個客戶端,DiscoveryClient要更簡單一些,干脆直接實戰吧!

需求確認

  • 本次實戰的需求很簡單:從kubernetes查詢所有的Group、Version、Resource信息,在控制台打印出來;

源碼下載

名稱 鏈接 備注
項目主頁 https://github.com/zq2599/blog_demos 該項目在GitHub上的主頁
git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該項目源碼的倉庫地址,https協議
git倉庫地址(ssh) git@github.com:zq2599/blog_demos.git 該項目源碼的倉庫地址,ssh協議
  • 這個git項目中有多個文件夾,client-go相關的應用在client-go-tutorials文件夾下,如下圖紅框所示:

在這里插入圖片描述

  • client-go-tutorials文件夾下有多個子文件夾,本篇對應的源碼在discoveryclientdemo目錄下,如下圖紅框所示:

在這里插入圖片描述

編碼

  • 新建文件夾discoveryclientdemo,在里面執行以下命令,新建module:
go mod init discoveryclientdemo
  • 添加k8s.io/api和k8s.io/client-go這兩個依賴,注意版本要匹配kubernetes環境:
go get k8s.io/api@v0.20.0
go get k8s.io/client-go@v0.20.0
  • 新建main.go,內容如下,內部已有詳細注釋,要重點關注的是ServerGroupsAndResources方法的第二個返回值,它的數據結構中有切片,切片的每個元素里面又有切片,這才是每個資源的信息:
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

	// home是家目錄,如果能取得家目錄的值,就可以用來做默認值
	if home:=homedir.HomeDir(); home != "" {
		// 如果輸入了kubeconfig參數,該參數的值就是kubeconfig文件的絕對路徑,
		// 如果沒有輸入kubeconfig參數,就用默認路徑~/.kube/config
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		// 如果取不到當前用戶的家目錄,就沒辦法設置kubeconfig的默認目錄了,只能從入參中取
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}

	flag.Parse()

	// 從本機加載kubeconfig配置文件,因此第一個參數為空字符串
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)

	// kubeconfig加載失敗就直接退出了
	if err != nil {
		panic(err.Error())
	}

	// 新建discoveryClient實例
	discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)

	if err != nil {
		panic(err.Error())
	}

	// 獲取所有分組和資源數據
	APIGroup, APIResourceListSlice, err := discoveryClient.ServerGroupsAndResources()

	if err != nil {
		panic(err.Error())
	}

	// 先看Group信息
	fmt.Printf("APIGroup :\n\n %v\n\n\n\n",APIGroup)

	// APIResourceListSlice是個切片,里面的每個元素代表一個GroupVersion及其資源
	for _, singleAPIResourceList := range APIResourceListSlice {

		// GroupVersion是個字符串,例如"apps/v1"
		groupVerionStr := singleAPIResourceList.GroupVersion

		// ParseGroupVersion方法將字符串轉成數據結構
		gv, err := schema.ParseGroupVersion(groupVerionStr)

		if err != nil {
			panic(err.Error())
		}

		fmt.Println("*****************************************************************")
		fmt.Printf("GV string [%v]\nGV struct [%#v]\nresources :\n\n", groupVerionStr, gv)

		// APIResources字段是個切片,里面是當前GroupVersion下的所有資源
		for _, singleAPIResource := range singleAPIResourceList.APIResources {
			fmt.Printf("%v\n", singleAPIResource.Name)
		}
	}
}
  • 執行go run main.go,截取部分執行結果如下,所有資源都被打印出來了:
...
*****************************************************************
GV string [discovery.k8s.io/v1beta1]
GV struct [schema.GroupVersion{Group:"discovery.k8s.io", Version:"v1beta1"}]
resources :

endpointslices
*****************************************************************
GV string [flowcontrol.apiserver.k8s.io/v1beta1]
GV struct [schema.GroupVersion{Group:"flowcontrol.apiserver.k8s.io", Version:"v1beta1"}]
resources :

flowschemas
flowschemas/status
prioritylevelconfigurations
prioritylevelconfigurations/status
  • 以上就是DiscoveryClient的基本用法,您是否覺得這樣的實戰太easy了,那咱們就來個延伸閱讀,看看DiscoveryClient的周邊場景;

kubectl中如何使用DiscoveryClient

  • kubectl api-versions命令,大家應該不陌生吧,可以返回當前kubernetes環境的所有Group+Version的組合,如下:
zhaoqin@zhaoqindeMBP-2 discoveryclientdemo % kubectl api-versions
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
...
  • 通過查看kubectl源碼可見,上述命令的背后就是使用了DiscoveryClient來實現的,如下圖紅框所示:

在這里插入圖片描述

  • 還有一處沒有明確:上圖紅框2中的o.discoveryClient究竟是不是DiscoveryClient呢?雖然名字很像,但還是瞅一眼才放心,結果這一瞅有了新發現,如下所示,discoveryClient的數據結構是CachedDiscoveryInterface
type APIVersionsOptions struct {
	discoveryClient discovery.CachedDiscoveryInterface

	genericclioptions.IOStreams
}
  • 從名稱CachedDiscoveryInterface來看,kubectl對GVR數據是做了本地緩存的,想想也是,GVR不經常變化,沒必要每次都去API Server拉取,關於緩存的細節請參考:staging/src/k8s.io/client-go/discovery/cached/disk/cached_discovery.go ,這里就不展開了;

  • 至此,client-go的四種客戶端工具實戰以及相關源碼的淺層次分析就全部完成了,在您做client-go開發的時候,希望這些內容能給您提供一些參考;

你不孤單,欣宸原創一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 數據庫+中間件系列
  6. DevOps系列

歡迎關注公眾號:程序員欣宸

微信搜索「程序員欣宸」,我是欣宸,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM