之前建立和管理CRD的client庫位於:github.com/kubernetes/…git
好比定義一個目錄api/types/v1alpha1,裏面是關於types的一些定義文件;github
metav1.ObjectMeta 類型會包含典型的任意的Kubernetes資源的metadata屬性,如name, namespace, labels, annotations。json
被Kubernetes API定義的全部資源對象、類型都須要實現k8s.io/apimachinery/pkg/runtime.Object這個接口定義,這個接口包含兩個方法GetObjectKind() 和 DeepCopyObject():後端
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 ) 複製代碼
當咱們定義好一個新的types類型而且添加了一個register註冊方法到全局的scheme編譯器後,咱們就能夠建立一個http client去加載咱們的自定義資源了。如今就要用到client-go/rest
這個RESTClient去實現了。通常而言,爲了更爲安全的方式使用API,優雅的姿式是打包這些操做到clientset中,經過rest包中的RESTClientFor
方法進行相關的封裝,而後再實現一些普適的interface接口,包含Get、Create、 Delete, Update 、List、Watch等通用接口方法,這個能夠參考Pod client set的實現ide
通常優雅的姿式去操做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:
代碼生成相比於前面的手動生成的優點在於不用手動去寫一些基礎的deepcopy,client,informer,lister
這些方法
code-generation 也是基於client-go,由於client-go 須要實現runtime.Object interface的CustomResources類型 ,這樣就要實現諸如DeepCopy深拷貝的一系列方法,code-generation 就是實現了好比深拷貝的代碼生成器,關於k8s.io/code-genera…,以下:
func (t* T) DeepCopy() *T
informer和lister至關因而controllers,抽象一層controllers去進行操做資源.
實際項目中,須要引入k8s.io/code-genera…這個工程,而後經過一些腳本生成。一個簡單的示例是github上的crd-code-generation項目,這個同時也是這篇博文 code-generation-customresources中的示例
官方的sample-controller項目也是代碼生成的,而且有關於自定義資源CRD的一些操做。
建立好工程目錄
pkg/apis/{Groupame}/{Version}
,如pkg/apis/networking.istio.io/v1
在version目錄下建立文件
文件裏面的註釋,格式,都有要求
建立自動生成腳本
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)). 複製代碼
而後經過以下命令
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的全部方法
優點:
減小很大一部分的通用實現,如deepcopy,client,informer,lister
這些方法,這個相對來講是通用的,各個CRD都要實現一套
避免本身編寫出一些不完善或者錯誤的實現
劣勢:
試想一下,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