k8s.io/client-go for talking to a kubernetes cluster.
k8s.io/client-go
提供了對k8s原生資源的informer和clientset等等,但對於自定義資源的操做則相對低效,須要使用 rest api 和 dynamic client 來操做,並本身實現反序列化等功能。javascript
code-generator 提供瞭如下工具用於爲k8s中的資源生成相關代碼,能夠更加方便的操做自定義資源:html
deepcopy-gen
: 生成深度拷貝對象方法client-gen
: 爲資源生成標準的操做方法(get;list;watch;create;update;patch;delete)informer-gen
: 生成informer,提供事件機制(AddFunc,UpdateFunc,DeleteFunc)來響應kubernetes的eventlister-gen
: 爲get和list方法提供只讀緩存層 code-generator整合了這些gen,使用腳本generate-groups.sh和generate-internal-groups.sh能夠爲自定義資源生產相關代碼。java
Kubebuilder是用於使用 自定義資源定義(CRD)構建Kubernetes API的框架。相似於Ruby on Rails和SpringBoot之類的Web開發框架,Kubebuilder能夠提升速度並下降開發人員管理的複雜性,以便在Go中快速構建和發佈Kubernetes API。它創建在用於構建核心Kubernetes API的規範技術的基礎之上,以提供減小樣板和麻煩的簡單抽象。git
Resource + Controller = Operator,能夠利用Kubebuilder編寫自定義資源的Operator。github
Kubebuilder
與 code-generator
均可覺得CRD生成Kubernetes API相關代碼,從代碼生成層面來說, 二者的區別在於:golang
使用Kubebuilder能夠快捷生成CRD以及相關的控制器框架,然而因爲Kubebuilder不會生成clientset等包,當別的服務想要操做CRD時將會很麻煩。web
二者結合後可使用Kubebuilder生成CRD和一整套控制器架構,再使用code-generator生成informers、listers、clientsets等。api
安裝Kubebuilder:參考官方文檔 https://cloudnative.to/kubebu...緩存
一、建立一個項目bash
mkdir -p $GOPATH/src/my.domain/example cd $GOPATH/src/my.domain/example kubebuilder init --domain my.domain tree -CL 2 . ├── bin │ └── manager ├── config │ ├── certmanager │ ├── default │ ├── manager │ ├── prometheus │ ├── rbac │ └── webhook ├── Dockerfile ├── go.mod ├── go.sum ├── hack │ └── boilerplate.go.txt ├── main.go ├── Makefile └── PROJECT 9 directories, 8 files
二、建立一個 API
kubebuilder create api --group example --version v1 --kind Guestbook Create Resource [y/n] y Create Controller [y/n] n tree -CL 3 . ├── api │ └── v1 │ ├── groupversion_info.go │ ├── guestbook_types.go │ └── zz_generated.deepcopy.go ......
注意:
若是修改了 api/v1/guestbook_types.go
,須要執行如下命令來更新代碼和manifests:
make && make manifests
初始化項目後的go.mod:
cat go.mod module my.domain/example go 1.13 require ( k8s.io/apimachinery v0.17.2 k8s.io/client-go v0.17.2 sigs.k8s.io/controller-runtime v0.5.0 )
須要將初始化的k8s庫更新到要使用的版本,如:
K8S_VERSION=v0.17.3 go get k8s.io/client-go@$K8S_VERSION go get k8s.io/apimachinery@$K8S_VERSION
k8s的版本號與 go.mod
中的 k8s.io/client-go
的版本保持一致便可。
注意:須要將依賴複製到vendor中
K8S_VERSION=v0.17.3 go get k8s.io/code-generator@$K8S_VERSION go mod vendor
須要在api目錄下建立code-generator所需的文件,並添加相關注釋。
新增 api/v1/doc.go
注意:修改groupName,package與api的version保持一致。
// +k8s:deepcopy-gen=package // Package v1 is the v1alpha1 version of the API. // +groupName=example.my.domain package v1
新增 api/v1/register.go
注意:package與api的version保持一致。
package v1 import ( "k8s.io/apimachinery/pkg/runtime/schema" ) // SchemeGroupVersion is group version used to register these objects. var SchemeGroupVersion = GroupVersion // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() }
修改 api/v1/{crd}_types.go
文件,添加註釋 // +genclient
// +genclient // +kubebuilder:object:root=true // Guestbook is the Schema for the guestbooks API type Guestbook struct {
在項目 hack
目錄下準備如下文件:
新建 hack/tools.go
文件
// +build tools package tools import _ "k8s.io/code-generator"
新建 hack/update-codegen.sh
,注意根據項目修改相應變量:
MODULE
和 go.mod
保持一致API_PKG=api
,和 api
目錄保持一致OUTPUT_PKG=generated/example
,與生成Resource時指定的group保持一致GROUP=example
, 和生成Resource時指定的group 保持一致VERSION=v1
, 和生成Resource時指定的version保持一致#!/usr/bin/env bash set -o errexit set -o nounset set -o pipefail # corresponding to go mod init <module> MODULE=my.domain/example # api package APIS_PKG=api # generated output package OUTPUT_PKG=generated/example # group-version such as foo:v1alpha1 GROUP=example VERSION=v1 GROUP_VERSION=${GROUP}:${VERSION} SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} # kubebuilder2.3.2版本生成的api目錄結構code-generator沒法直接使用 rm -rf "${APIS_PKG}/${GROUP}" && mkdir -p "${APIS_PKG}/${GROUP}" && cp -r "${APIS_PKG}/${VERSION}/" "${APIS_PKG}/${GROUP}" # generate the code with: # --output-base because this script should also be able to run inside the vendor dir of # k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir # instead of the $GOPATH directly. For normal projects this can be dropped. #client,informer,lister(注意: code-generator 生成的deepcopy不適配 kubebuilder 所生成的api) bash "${CODEGEN_PKG}"/generate-groups.sh "client,informer,lister" \ ${MODULE}/${OUTPUT_PKG} ${MODULE}/${APIS_PKG} \ ${GROUP_VERSION} \ --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt # --output-base "${SCRIPT_ROOT}" # --output-base "${SCRIPT_ROOT}/../../.."
注意:
修改 Makefile
,添加生成命令
update-codegen: chmod +x ./hack/update-codegen.sh ./hack/update-codegen.sh
項目根目錄下執行make update-codegen
便可,將生成以下代碼結構:
. ├── api │ ├── example │ │ └── v1 │ │ ├── doc.go │ │ ├── groupversion_info.go │ │ ├── guestbook_types.go │ │ ├── register.go │ │ └── zz_generated.deepcopy.go │ └── v1 │ ├── doc.go │ ├── groupversion_info.go │ ├── guestbook_types.go │ ├── register.go │ └── zz_generated.deepcopy.go ├── generated │ └── example │ ├── clientset │ ├── informers │ └── listers
以後即可以經過clientset等包對自定義資源對象進行操做。
注意事項:
kubebuilder2.3.2版本生成的api目錄結構爲 api/v1
,而code-generator須要的api目錄結構爲 api/example/v1
,相比較增長了group這一層。
hack/update-codegen.sh
腳本會自動根據kubebuilder的api生成code-generator所需目錄結構。make manifests
在生成CRD模版時,需先刪除api以及generated目錄中爲code-generator生成的代碼,纔可正常生成CRD模版。api/v1
中的types,而code-generator生成的clientset等則須要使用 api/example/v1
中的types。https://github.com/kubernetes...
https://github.com/kubernetes...