歡迎通路我的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資訊,在控制台列印出來;
源碼下載下傳
- 本篇實戰中的源碼可在GitHub下載下傳到,位址和連結資訊如下表所示(https://github.com/zq2599/blog_demos):
名稱 | 連結 | 備注 |
---|---|---|
項目首頁 | https://github.com/zq2599/blog_demos | 該項目在GitHub上的首頁 |
git倉庫位址(https) | https://github.com/zq2599/blog_demos.git | 該項目源碼的倉庫位址,https協定 |
git倉庫位址(ssh) | [email protected]: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/[email protected]
go get k8s.io/[email protected]
- 建立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開發的時候,希望這些内容能給您提供一些參考;
你不孤單,欣宸原創一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 資料庫+中間件系列
- DevOps系列
歡迎關注公衆号:程式員欣宸
微信搜尋「程式員欣宸」,我是欣宸,期待與您一同暢遊Java世界...
https://github.com/zq2599/blog_demos