Kubernetes client-go實戰應用


Kubernetes client-go實戰應用

github上client-go官方項目工程html

實戰應用

  • sample-controller示例
    • 官方的一個簡單的Controller示例,能夠處理任何CRD資源
    • The main.go and controller.go contains the sample code to watch for the CRD and do some task accordingly.
    • 採用code-generator 的方式
  • kubernetes-crd-example
    • 一個簡單的處理任何CRD資源的示例

client-go手動操做CRD

之前建立和管理CRD的client庫位於:github.com/kubernetes/…git

1,定義types類型

好比定義一個目錄api/types/v1alpha1,裏面是關於types的一些定義文件;github

metav1.ObjectMeta 類型會包含典型的任意的Kubernetes資源的metadata屬性,如name, namespace, labels, annotations。json

2,定義DeepCopy深拷貝方法

被Kubernetes API定義的全部資源對象、類型都須要實現k8s.io/apimachinery/pkg/runtime.Object這個接口定義,這個接口包含兩個方法GetObjectKind() 和 DeepCopyObject():後端

  • GetObjectKind():
    • 內置的metav1.TypeMeta結構已經實現
  • DeepCopyObject():
    • 須要咱們本身去實現這個方法
    • 目的是生成deep copy 對象,C++中有這樣的用法,名爲:深拷貝,深拷貝意味着會從新生成對象並拷貝對象中的全部字段、地址等數據;淺拷貝僅僅是對象的引用,並無生成新的對象。
    • 須要手動去寫各類字段域的賦值

3,經過scheme註冊types類型

Scheme定義了序列化和反序列化API對象的方法,用於將group、版本和類型信息轉換爲Go模式和從Go模式轉換爲Go模式的類型註冊表,以及不一樣版本的Go模式之間的映射。api

當和API Server通訊的時候可以處理新的types類型的話就須要先讓client可以知道有這個新的types類型存在。緩存

AddToScheme 會利用到反射,所以新定義的types類型的結構體的命名必需要和自定義的Kind的命名(如VirtualService)保持一致,不然會找不到對應的kind,安全

var ( SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) AddToScheme   = SchemeBuilder.AddToScheme ) 複製代碼
  • AddToScheme: runtime.SchemeBuilder的一個外部方法,當Kubernetes註冊新定義的types類型後,就能夠在任何地方調用這個方法

4,啓動一個HTTP client

當咱們定義好一個新的types類型而且添加了一個register註冊方法到全局的scheme編譯器後,咱們就能夠建立一個http client去加載咱們的自定義資源了。如今就要用到client-go/rest這個RESTClient去實現了。通常而言,爲了更爲安全的方式使用API,優雅的姿式是打包這些操做到clientset中,經過rest包中的RESTClientFor方法進行相關的封裝,而後再實現一些普適的interface接口,包含Get、Create、 Delete, Update 、List、Watch等通用接口方法,這個能夠參考Pod client set的實現ide

5,構建Informer

通常優雅的姿式去操做Kubernetes的資源並實時作出響應的方案是採用client-go的informer,它的工做模式是:初始時使用List()去加載資源的全部相關實例,而後使用Watch()進行訂閱更新;使用初始對象List列表和從watch訂閱更新到的數據會構建一個本地緩存,該緩存能夠快速訪問任何自定義資源而無需每次都訪問API  Server。像Pod、Deployment等資源對象都是採用這種方式。ui

k8s.io/client-go/tools/cache包中提供了一個Informer方法cache.NewInformer,這個cache.NewInformer返回兩個參數Store 和Controller:

  • Controller: 控制 List() 和 Watch() 的調用並填充Store
  • Store: 返回從API Server獲取的資源的最新狀態
    • 能夠經過這個Store去訪問咱們的自定義資源CRDs

code-generator自動代碼生成操做CRD

代碼生成相比於前面的手動生成的優點在於不用手動去寫一些基礎的deepcopy,client,informer,lister這些方法

code-generation 也是基於client-go,由於client-go 須要實現runtime.Object  interface的CustomResources類型 ,這樣就要實現諸如DeepCopy深拷貝的一系列方法,code-generation  就是實現了好比深拷貝的代碼生成器,關於k8s.io/code-genera…,以下:

  • deepcopy-gen: 給自定義type類型T建立一個DeepCopy方法func (t* T) DeepCopy() *T
  • client-gen: 給自定義資源的APIGroups建立clientsets
  • informer-gen:經過informers給自定義資源建立一個基礎接口方法去操做自定義資源
  • lister-gen: 爲GET和LIST請求建立一個listers監聽器

informer和lister至關因而controllers,抽象一層controllers去進行操做資源.

實際項目中,須要引入k8s.io/code-genera…這個工程,而後經過一些腳本生成。一個簡單的示例是github上的crd-code-generation項目,這個同時也是這篇博文 code-generation-customresources中的示例

官方的sample-controller項目也是代碼生成的,而且有關於自定義資源CRD的一些操做。

1,定義好相關目錄和文件

  • 建立好工程目錄

    • pkg/apis/{Groupame}/{Version},如pkg/apis/networking.istio.io/v1
  • 在version目錄下建立文件

    • doc.go
    • types.go : 資源對象的定義
    • regsiter.go:Scheme和register type
  • 文件裏面的註釋,格式,都有要求

  • vendor

    • 將code-generator項目引入的vendor下
  • 建立自動生成腳本

    • 調用vendor/k8s.io/code-generator/generate-groups.sh生成

注意點:types不能有interface{} ,不然自動生成的時候會生成出錯,所以其實也不建議經過代碼自動生成,仍是手動去編寫會更好。

type VirtualServiceSpec struct { Hosts    []string    `json:"hosts"` Gateways []string    `json:"gateways"` Http     interface{} `json:"http"` } 報錯以下: /v1/zz_generated.deepcopy.go" (107:37: expected ';', found '{' (and 5 more errors)). 複製代碼

2,生成代碼

而後經過以下命令

generate-groups.sh <generators> <output-package> <apis-package> <groups-versions> ... vendor/k8s.io/code-generator/generate-groups.sh all github.com/openshift-evangelists/crd-code-generation/pkg/client github.com/openshift-evangelists/crd-code-generation/pkg/apis example.com:v1 ... 能夠同時指定多個輸出目錄 vendor/k8s.io/code-generator/generate-groups.sh all \   base-code-example/istio/crd-code-generation-service/pkg/client base-code-example/istio/crd-code-generation-service/pkg/apis \   "example.com:v1 networking.istio.io:v1" \   --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt 複製代碼

能夠生成client的全部方法

3,自動生成的優劣

優點:

  • 減小很大一部分的通用實現,如deepcopy,client,informer,lister這些方法,這個相對來講是通用的,各個CRD都要實現一套

  • 避免本身編寫出一些不完善或者錯誤的實現

劣勢:

  • 很是嚴格的定義,包括註釋,都要按照要求去實現
  • type定義的struct,暫時不支持interface類型的轉換,相對來講不方便,須要嚴格知道spec的全部域和字段的準確類型

istio中client-go的處理

試想一下,istio中的資源、對象都是Kubernetes的CRDs,那麼必然,istio中確定有處理好Kubernetes  CRD的方式,咱們知道目前都是採用client-go,那麼istio中必然會有大量的client-go的引用和使用,經過源碼能夠發現確實如此而且都是採用RESTClient,clientset是包含RESTClient的。

在源碼路徑/Users/meitu/Documents/work_Meitu/goDev/Applications/src/istio.io/istio/pilot/pkg/config/kube/crd中就是相關CRD的處理,而後/Users/meitu/Documents/work_Meitu/goDev/Applications/src/istio.io/istio/pilot/pkg/config/kube/crd/types.go是istio中全部一些經常使用資源的定義如DestinationRule、Gateway、VirtualService等。這樣的話,咱們本身要經過client-go去實現後端服務,去開發的話,就能夠參考istio源碼中的一些定義和基本方法,而後結合client-go的通常性處理去實現後端服務程序。

參考

Accessing Kubernetes CRDs from the client-go package

Kubernetes Deep Dive: Code Generation for CustomResources

k8s.io/code-genera…

官方的sample-controller項目

github上的crd-code-generation項目

相關文章
相關標籤/搜索