日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

client-go实战之二:RESTClient

發(fā)布時(shí)間:2023/12/16 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 client-go实战之二:RESTClient 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

歡迎訪問我的GitHub

這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos

系列文章鏈接

  • client-go實(shí)戰(zhàn)之一:準(zhǔn)備工作
  • client-go實(shí)戰(zhàn)之二:RESTClient
  • client-go實(shí)戰(zhàn)之三:Clientset
  • client-go實(shí)戰(zhàn)之四:dynamicClient
  • client-go實(shí)戰(zhàn)之五:DiscoveryClient
  • 本篇概覽

    • 本文是《client-go實(shí)戰(zhàn)》系列的第二篇,前文咱們提到過client-go一共有四種客戶端:RESTClient、ClientSet、DynamicClient、DiscoveryClient,而RESTClient是最基礎(chǔ)的版本,其他三種都是基于RESTClient封裝的,今天咱們通過實(shí)戰(zhàn)編碼來學(xué)習(xí)RESTClient,熟悉最基礎(chǔ)的遠(yuǎn)程操作步驟;
    • 本篇由以下幾部分組成:
  • 簡介RESTClient
  • 每次編碼前的準(zhǔn)備工作
  • 正式編碼
  • 驗(yàn)證
  • 關(guān)鍵源碼分析
  • RESTClient簡介

    • RESTClient是client-go最基礎(chǔ)的客戶端,主要是對(duì)HTTP Reqeust進(jìn)行了封裝,對(duì)外提供RESTful風(fēng)格的API,并且提供豐富的API用于各種設(shè)置,相比其他幾種客戶端雖然更復(fù)雜,但是也更為靈活;
    • 使用RESTClient對(duì)kubernetes的資源進(jìn)行增刪改查的基本步驟如下:
  • 確定要操作的資源類型(例如查找deployment列表),去官方API文檔中找到對(duì)于的path、數(shù)據(jù)結(jié)構(gòu)等信息,后面會(huì)用到;
  • 加載配置kubernetes配置文件(和kubectl使用的那種kubeconfig完全相同);
  • 根據(jù)配置文件生成配置對(duì)象,并且通過API對(duì)配置對(duì)象就行設(shè)置(例如請(qǐng)求的path、Group、Version、序列化反序列化工具等);
  • 創(chuàng)建RESTClient實(shí)例,入?yún)⑹桥渲脤?duì)象;
  • 調(diào)用RESTClient實(shí)例的方法向kubernetes的API Server發(fā)起請(qǐng)求,編碼用fluent風(fēng)格將各種參數(shù)傳入(例如指定namespace、資源等),如果是查詢類請(qǐng)求,還要傳入數(shù)據(jù)結(jié)構(gòu)實(shí)例的指針,改數(shù)據(jù)結(jié)構(gòu)用于接受kubernetes返回的查詢結(jié)果;
    • 接下來的編碼實(shí)戰(zhàn)也是按照上述流程進(jìn)行的;

    實(shí)戰(zhàn)內(nèi)容

    • 本次實(shí)戰(zhàn)內(nèi)容很簡單:查詢kube-system這個(gè)namespace下的所有pod,然后在控制臺(tái)打印每個(gè)pod的幾個(gè)關(guān)鍵字段;
    • 感謝您耐心聽我啰嗦了一大堆,接下來開始實(shí)戰(zhàn)吧;

    源碼下載

    • 本篇實(shí)戰(zhàn)中的源碼可在GitHub下載到,地址和鏈接信息如下表所示(https://github.com/zq2599/blog_demos):
    名稱鏈接備注
    項(xiàng)目主頁https://github.com/zq2599/blog_demos該項(xiàng)目在GitHub上的主頁
    git倉庫地址(https)https://github.com/zq2599/blog_demos.git該項(xiàng)目源碼的倉庫地址,https協(xié)議
    git倉庫地址(ssh)git@github.com:zq2599/blog_demos.git該項(xiàng)目源碼的倉庫地址,ssh協(xié)議
    • 這個(gè)git項(xiàng)目中有多個(gè)文件夾,client-go相關(guān)的應(yīng)用在client-go-tutorials文件夾下,如下圖紅框所示:
    • client-go-tutorials文件夾下有多個(gè)子文件夾,本篇對(duì)應(yīng)的源碼在restclientdemo目錄下,如下圖紅框所示:

    查看官方文檔,獲取編碼所需內(nèi)容

    • 瀏覽器打開官方API文檔,地址:https://v1-19.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/
    • 找到pod的API文檔,如下圖,確定了path和namespace參數(shù):
    • 然后還要關(guān)注響應(yīng)的數(shù)據(jù)結(jié)構(gòu),如下圖紅框,返回的是:
    • 點(diǎn)擊上圖紅框中的內(nèi)容,可見PodList的詳情,這就是我們編碼時(shí)所需的數(shù)據(jù)結(jié)構(gòu):
    • 掌握了請(qǐng)求和響應(yīng)的詳細(xì)信息,可以開始編碼了;

    編碼

    • 新建文件夾restclientdemo,在里面執(zhí)行以下命令,新建module:
    go mod init restclientdemo
    • 添加k8s.io/api和k8s.io/client-go這兩個(gè)依賴,注意版本要匹配kubernetes環(huán)境:
    go get k8s.io/api@v0.20.0 go get k8s.io/client-go@v0.20.0
    • 新建main.go,內(nèi)容如下,已經(jīng)都添加了詳細(xì)的注釋,就不贅述了:
    package mainimport ("context""flag""fmt""k8s.io/client-go/kubernetes/scheme""k8s.io/client-go/rest""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir"corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""path/filepath" )func main() {var kubeconfig *string// home是家目錄,如果能取得家目錄的值,就可以用來做默認(rèn)值if home:=homedir.HomeDir(); home != "" {// 如果輸入了kubeconfig參數(shù),該參數(shù)的值就是kubeconfig文件的絕對(duì)路徑,// 如果沒有輸入kubeconfig參數(shù),就用默認(rèn)路徑~/.kube/configkubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")} else {// 如果取不到當(dāng)前用戶的家目錄,就沒辦法設(shè)置kubeconfig的默認(rèn)目錄了,只能從入?yún)⒅腥?/span>kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")}flag.Parse()// 從本機(jī)加載kubeconfig配置文件,因此第一個(gè)參數(shù)為空字符串config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)// kubeconfig加載失敗就直接退出了if err != nil {panic(err.Error())}// 參考path : /api/v1/namespaces/{namespace}/podsconfig.APIPath = "api"// pod的group是空字符串config.GroupVersion = &corev1.SchemeGroupVersion// 指定序列化工具config.NegotiatedSerializer = scheme.Codecs// 根據(jù)配置信息構(gòu)建restClient實(shí)例restClient, err := rest.RESTClientFor(config)if err!=nil {panic(err.Error())}// 保存pod結(jié)果的數(shù)據(jù)結(jié)構(gòu)實(shí)例result := &corev1.PodList{}// 指定namespacenamespace := "kube-system"// 設(shè)置請(qǐng)求參數(shù),然后發(fā)起請(qǐng)求// GET請(qǐng)求err = restClient.Get().// 指定namespace,參考path : /api/v1/namespaces/{namespace}/podsNamespace(namespace).// 查找多個(gè)pod,參考path : /api/v1/namespaces/{namespace}/podsResource("pods").// 指定大小限制和序列化工具VersionedParams(&metav1.ListOptions{Limit:100}, scheme.ParameterCodec).// 請(qǐng)求Do(context.TODO()).// 結(jié)果存入resultInto(result)if err != nil {panic(err.Error())}// 表頭fmt.Printf("namespace\t status\t\t name\n")// 每個(gè)pod都打印namespace、status.Phase、name三個(gè)字段for _, d := range result.Items {fmt.Printf("%v\t %v\t %v\n",d.Namespace,d.Status.Phase,d.Name)} }
    • 編碼完成,執(zhí)行go run main.go,即可獲取指定namespace下所有pod的信息,控制臺(tái)輸出如下:
    (base) zhaoqindeMBP:restclientdemo zhaoqin$ go run main.go namespace status name kube-system Running coredns-7f89b7bc75-5pdwc kube-system Running coredns-7f89b7bc75-nvbvm kube-system Running etcd-hedy kube-system Running kube-apiserver-hedy kube-system Running kube-controller-manager-hedy kube-system Running kube-flannel-ds-v84vc kube-system Running kube-proxy-hlppx kube-system Running kube-scheduler-hedy
    • 至此,RESTClient客戶端從編碼到驗(yàn)證都完成了;

    如何將收到的數(shù)據(jù)反序列化為PodList對(duì)象?

    • 前面的代碼比較簡單,但是有一處引起了我的興趣,如下圖紅框所示,result是corev1.PodList類型的結(jié)構(gòu)體指針,restClient收到kubernetes返回的數(shù)據(jù)后,如何知道要將數(shù)據(jù)反序列化成corev1.PodList類型呢(Into方法入?yún)㈩愋蜑閞untime.Object)?

    • 之前的代碼中有一行設(shè)置了編解碼工具:config.NegotiatedSerializer = scheme.Codecs,展開這個(gè)scheme.Codecs,可見設(shè)置的時(shí)候確定了序列化工具為runtime.Serializer:

    • Serializer的typer字段類型是runtime.ObjectTyper,這里實(shí)際上是runtime.Scheme,因此ObjectTyper.ObjectKinds方法,實(shí)際上就是Scheme.ObjectKinds方法,在里面根據(jù)s.typeToGVK[t]拿到了GVK,也就是v1.PodList:

    • 有了這個(gè)GVK就確定的返回?cái)?shù)據(jù)的類型,最終調(diào)用caseSensitiveJSONIterator.Unmarshal(data, obj)完成byte數(shù)組到對(duì)象的反序列化操作:

    • 最后還有一行關(guān)鍵代碼,將data的內(nèi)容寫到最外層的Into方法的入?yún)⒅?#xff1a;

    • 源碼分析完成,簡單來說除了利用反射獲取實(shí)際類型,還有就是Scheme內(nèi)部維護(hù)的數(shù)據(jù)類型和GVK的關(guān)系映射表;

    • 至此,RESTClient的實(shí)戰(zhàn)就完成了,希望本篇能幫助您打好基礎(chǔ),這樣后面在體驗(yàn)其他三種客戶端時(shí)已對(duì)其底層的實(shí)現(xiàn)原理了然于胸;

    你不孤單,欣宸原創(chuàng)一路相伴

  • Java系列
  • Spring系列
  • Docker系列
  • kubernetes系列
  • 數(shù)據(jù)庫+中間件系列
  • DevOps系列
  • 歡迎關(guān)注公眾號(hào):程序員欣宸

    微信搜索「程序員欣宸」,我是欣宸,期待與您一同暢游Java世界…

    總結(jié)

    以上是生活随笔為你收集整理的client-go实战之二:RESTClient的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。