Operator SDK User Guide
Operator capability level
每種operator類(lèi)型需要不同的能力眷蜓。對(duì)于你的operator為項(xiàng)目選擇什么類(lèi)型時(shí),了解每個(gè)項(xiàng)目類(lèi)型的特性和限制是很重要的胎围。
Phase I | Phase II | Phase III | Phase IV | Phase V |
---|---|---|---|---|
基本安裝 | 無(wú)縫升級(jí) | 完整生命周期 | 深入理解 | 自動(dòng)駕駛 |
自動(dòng)化應(yīng)用程序配置和配置管理 | 支持補(bǔ)丁和小版本升級(jí) | 應(yīng)用程序生命周期,存儲(chǔ)(備份,故障恢復(fù)) | metrics吁系、alert德召、log處理和工作負(fù)載分析 | 水平/橫向擴(kuò)展,自動(dòng)配置調(diào)優(yōu)汽纤,異常檢測(cè)上岗,調(diào)度調(diào)優(yōu) |
Helm | Helm | |||
Ansible | Ansible | Ansible | Ansible | Ansible |
GO | GO | GO | GO | GO |
kubebuilder vs operator-sdk
kubebuilder和operator-sdk支持的Go項(xiàng)目之間沒(méi)有太大的區(qū)別。兩者都使用controller-tools和controller-runtime蕴坪,并且都支持基本相似的go包結(jié)構(gòu)肴掷。
他們的不同點(diǎn):
- Operator SDK支持Ansible和Helm operator,這樣很容易編寫(xiě)operator而不需要go背传,如果你對(duì)Ansible和Helm比較熟悉呆瞻。
- Operator SDK集成了Operator生命周期管理(OLM),這是Operator Framework的關(guān)鍵組件续室,對(duì)于2個(gè)集群操作很重要栋烤,比如管理員在線(xiàn)升級(jí)你的operator。
- Operator SDK包含一個(gè)scorecard subcommand挺狰,幫助你了解operator是否遵循最佳實(shí)踐明郭。
- Operator SDK包含一個(gè)e2e測(cè)試框架,它簡(jiǎn)化了針對(duì)實(shí)際集群測(cè)試操作符的工作丰泊。
- Kubebuilder包含一個(gè)envtest包薯定,允許operator開(kāi)發(fā)人員使用獨(dú)立的etcd和apiserver運(yùn)行簡(jiǎn)單的測(cè)試。
- Kubebuilder搭建了一個(gè)Makefile來(lái)幫助用戶(hù)完成operator的任務(wù)(構(gòu)建瞳购、測(cè)試话侄、運(yùn)行、代碼生成等);Operator SDK目前使用內(nèi)置的子命令学赛。每種方法都有優(yōu)缺點(diǎn)年堆。SDK團(tuán)隊(duì)將來(lái)可能會(huì)遷移到基于makefile的方法。
- Kubebuilder使用Kustomize構(gòu)建部署清單;Operator SDK使用帶有占位符的靜態(tài)文件盏浇。
- Kubebuilder最近改進(jìn)了對(duì)許可和CRD轉(zhuǎn)換webhook的支持变丧,但還沒(méi)有將其加入到SDK中。
Create a new project
operator-sdk new memcached-operator
SDK還支持使用Ansible或Helm開(kāi)發(fā)操作員绢掰。Helm使用指南痒蓬。
Operator project layout
File/Folder s | Purpose |
---|---|
cmd | 包含文件manager/main.go。operator的main程序滴劲。他將實(shí)例化一個(gè)新的manager攻晒,注冊(cè)所有pkg/apis/...下的自定義資源定義和啟動(dòng)所有在pkg/controllers/...下的controller。 |
pkg/apis | 包含自定義資源(CRD)API的樹(shù)目錄班挖。用戶(hù)可以展開(kāi)編輯pkg/apis/<group>/<version>/<kind>_types.go文件鲁捏,為每種資源類(lèi)型定義API,并將這些包導(dǎo)入它們的控制器中萧芙,以監(jiān)視這些資源類(lèi)型碴萧。 |
pkg/controller | 此pkg包含控制器實(shí)現(xiàn)乙嘀。用戶(hù)可以展開(kāi)編輯pkg/controller/<kind>/<kind>_controller.go文件末购。定義控制器的協(xié)調(diào)邏輯來(lái)處理指定kind的資源類(lèi)型破喻。 |
build | 包含Dockerfile編譯輯腳本,用于編譯operator盟榴。 |
deploy | 包含用于注冊(cè)CRD曹质、設(shè)置RBAC和將operator部署為Deployment的各種YAML清單。 |
go.mod go.sum | 描述該操作符的外部依賴(lài)項(xiàng)的Go mod清單擎场。 |
vendor | golang vendor目錄羽德,包含滿(mǎn)足此項(xiàng)目中Go import 的外部依賴(lài)項(xiàng)目的本地副本。Go modules 管理vendor目錄迅办。除非使用—vendor標(biāo)志初始化項(xiàng)目宅静,或者go mod vendor在項(xiàng)目根目錄中運(yùn)行,否則此目錄將不存在站欺。 |
我們主要是開(kāi)發(fā)pkg下api和controller姨夹。
Manager
main程序?yàn)閛perator里的cmd/manager/main.go, 用于初始化并運(yùn)行Manager。
Manager將為pkg/api /…下所有自定義資源自動(dòng)注冊(cè)schema矾策,和運(yùn)行pkg/controller/…下的所有controller磷账。
Manager可以限制namespace所有控制器要監(jiān)視的資源:
mgr, err := manager.New(cfg, manager.Options{Namespace: namespace})
默認(rèn)情況下這將是operator運(yùn)行的namespace。如果需要查看所有的namespace贾虽,請(qǐng)將namespace設(shè)置為空:
mgr, err := manager.New(cfg, manager.Options{Namespace: ""})
也可以使用 MultiNamespacedCacheBuilder 查看一組特定的namespace:
var namespaces []string // List of Namespaces
// Create a new Cmd to provide shared dependencies and start components
mgr, err := manager.New(cfg, manager.Options{
NewCache: cache.MultiNamespacedCacheBuilder(namespaces),
MapperProvider: restmapper.NewDynamicRESTMapper,
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
})
默認(rèn)情況main程序?qū)⒃O(shè)置namager的namespace使用在deploy/operator.yaml
定義的WATCH_NAMESPACE
逃糟。
Add a new Custom Resource Definition
增加一個(gè)名稱(chēng)為Memcached的Custom Resource Definition(CRD) API ,APIVersion cache.example.com/v1alpha1 和 Kind Memcached蓬豁。
operator-sdk add api --api-version=cache.limingnihao.com/v1alpha1 --kind=Memcached
Define the spce and status
修改Memcached Custom Resource(CR)的spec和status在文件pkg/apis/cache/v1alpha1/memcached_types.go
:
type MemcachedSpec struct {
// Size is the size of the memcached deployment
Size int32 `json:"size"`
}
type MemcachedStatus struct {
// Nodes are the names of the memcached pods
Nodes []string `json:"nodes"`
}
在修改*_types.go文件之后篷帅,運(yùn)行下面命令更新和生成代碼:
$ operator-sdk generate k8s
INFO[0000] Running deepcopy code-generation for Custom Resource group versions: [cache:[v1alpha1], ]
INFO[0008] Code-generation complete.
Updating CRD mainfests
現(xiàn)在MemcachedSpec
和MemcachedStatus
有一些 fields 和 possibly annotations, 必須更新API's group 和 kind 與 CRD一致. 所以需要運(yùn)行下面命令:
$ operator-sdk generate crds
INFO[0000] Running CRD generator.
INFO[0000] CRD generation complete.
storage version
創(chuàng)建 CustomResourceDefinition 時(shí)拧咳,會(huì)在 CustomResourceDefinition spec.versions 列表設(shè)置適當(dāng)?shù)姆€(wěn)定級(jí)和版本號(hào)。例如v1beta1表示第一個(gè)版本尚未穩(wěn)定。所有自定義資源對(duì)象將首先存儲(chǔ)在這個(gè)版本.
所以你項(xiàng)目的CRD必須精確地指定一個(gè)storage version.
如果轉(zhuǎn)換涉及結(jié)構(gòu)變更正林,并且需要自定義邏輯,轉(zhuǎn)換應(yīng)該使用 webhook蕾总。如果沒(méi)有結(jié)構(gòu)變更囤屹, 則使用 None 默認(rèn)轉(zhuǎn)換策略,不同版本時(shí)只有apiVersion字段有變更付魔。
使用+kubebuilder:storageversion來(lái)marker指示API服務(wù)器應(yīng)該使用的存儲(chǔ)數(shù)據(jù)的GVK聊品。該marker應(yīng)該位于Memcached類(lèi)型之上的注釋中。
(沒(méi)明白什么意思)
OpenAPI validation
當(dāng)清單生成時(shí)几苍,OpenAPIv3 schema被添加到spec.validation
塊中的CRD清單中翻屈。這個(gè)驗(yàn)證塊允許Kubernetes在創(chuàng)建或更新Memcached Custom Resource時(shí)驗(yàn)證它的屬性。
Markers (annotations) 可用于驗(yàn)證您的API配置妻坝。這些markers將始終具有+kubebuilder:validation前綴伸眶。例如惊窖,可以通過(guò)添加以下標(biāo)記來(lái)添加enum類(lèi)型規(guī)范:
// +kubebuilder:validation:Enum=Lion;Wolf;Dragon
type Alias string
CRD generation和marker文檔討論了markers在代碼中的是用。完整的OpenAPIv3 validation markers請(qǐng)參考這里
運(yùn)行下面命令厘贼,更新CRDdeploy/crds/cache.example.com_memcacheds_crd.yaml
.
operator-sdk generate crds
一個(gè)生成YAML的例子如下:
spec:
validation:
openAPIV3Schema:
properties:
spec:
properties:
size:
format: int32
type: integer
要了解有關(guān)Custom Resource Definitions中的OpenAPI v3.0驗(yàn)證模式的更多信息界酒,請(qǐng)參閱Kubernetes文檔。
Add a new Contrller
添加一個(gè)新的Controller到項(xiàng)目嘴秸,將監(jiān)視和協(xié)調(diào)Memcached資源:
$ operator-sdk add controller --api-version=cache.limingnihao.com/v1alpha1 --kind=Memcached
這將在pkg/controller/memcached/...
下搭建一個(gè)新的Controller實(shí)現(xiàn)毁欣。
這個(gè)例子將生成文件pkg/controller/memcached/memcached_controller.go
,memcached_controller.go
是具體實(shí)現(xiàn)岳掐。
示例中的Controller將為所有的Memcached CR執(zhí)行以下邏輯:
- 創(chuàng)建一個(gè)memcached Deployment如果不存在凭疮。
- 確保這些Deployment數(shù)量和
Memcached CR spec
定義的相同。 - 使用帶有memcached pods名字的狀態(tài)更新
Memcached CR
狀態(tài)串述。
接下來(lái)的兩個(gè)小節(jié)將解釋Controller如何監(jiān)視資源以及如何觸發(fā)協(xié)調(diào)循環(huán)执解。
Resources watched by the Controller
查看pkg/controller/memcached/memcached_controller.go
的Controller實(shí)現(xiàn),如何監(jiān)聽(tīng)資源纲酗。
第一個(gè)監(jiān)視對(duì)象是作為主要資源的Memcached類(lèi)型衰腌。對(duì)于每個(gè)添加/更新/刪除事件,會(huì)給那個(gè)Memcached對(duì)象發(fā)送一個(gè)調(diào)和Request(a namespace/name key):
// Watch for changes to primary resource Memcached
err = c.Watch(&source.Kind{Type: &cachev1alpha1.Memcached{}}, &handler.EnqueueRequestForObject{})
if err != nil {
return err
}
下面是對(duì)Deployments的監(jiān)事耕姊,但是event handler將每個(gè)event映射到Deplyments所有者的Request桶唐。本例子中,Memcached對(duì)象是Deployment的創(chuàng)建者茉兰,這將允許controller將Deployments作為輔助資源監(jiān)視尤泽。
// Watch for changes to secondary resource Pods and requeue the owner Memcached
err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{
IsController: true,
OwnerType: &cachev1alpha1.Memcached{},
})
if err != nil {
return err
}
Controller configurations
在初始化controller和生命watch參數(shù)時(shí),有很多的配置规脸。更多配置細(xì)節(jié)請(qǐng)參考controller godocs
- 通過(guò)MaxConcurrentReconciles選項(xiàng)設(shè)置控制器的最大并發(fā)協(xié)調(diào)數(shù)坯约。默認(rèn)為1。
_, err := controller.New("memcached-controller", mgr, controller.Options{
MaxConcurrentReconciles: 2,
...
})
- 使用predicates過(guò)濾監(jiān)視事件莫鸭。
- 選擇EventHandelr的類(lèi)型闹丐,可以將reconcile loop更改監(jiān)聽(tīng)事件為reconcile request。對(duì)于operator更復(fù)雜的primary和secondary資源關(guān)系被因,可以使用EnqueueRequestsFromMapFunc handler卿拴,可以將監(jiān)聽(tīng)事件轉(zhuǎn)換為任務(wù)的reconcile request。EnqueueRequestForObject隊(duì)列的一個(gè)請(qǐng)求包含事件源對(duì)象的Name和Namespace梨与。
Reconcile loop
每個(gè)Controller都有一個(gè)Reconciler對(duì)象和一個(gè)實(shí)現(xiàn)了reconcile循環(huán)的reconcile()方法堕花。reconcile loop通過(guò)Request argument查看主資源對(duì)象的Namespace/Name key,Memcached粥鞋,從緩存:
// Reconcile讀取Memcached對(duì)象的集群狀態(tài)缘挽,并根據(jù)讀取的狀態(tài)和Memcached. spec中的內(nèi)容進(jìn)行更改
// 如果返回error為非空或Result.Requeue為true,控制器將再次請(qǐng)求處理Request,否則在完成后將從隊(duì)列中刪除壕曼。
func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) {
// Lookup the Memcached instance for this reconcile request
memcached := &cachev1alpha1.Memcached{}
err := r.client.Get(context.TODO(), request.NamespacedName, memcached)
...
}
根據(jù)返回值苏研,Result和error,Request將重新請(qǐng)求腮郊,然后再次觸發(fā)Reconcile loop:
// Reconcile successful - don't requeue
return reconcile.Result{}, nil
// Reconcile failed due to error - requeue
return reconcile.Result{}, err
// Requeue for any reason other than error
return reconcile.Result{Requeue: true}, nil
你還可以設(shè)置Result.RequeueAfter
摹蘑,設(shè)置在一些時(shí)間之后重新請(qǐng)求Request。
import "time"
// Reconcile for any reason than error after 5 seconds
return reconcile.Result{RequeueAfter: time.Second*5}, nil
Note: 返回帶RequeueAfter的Result伴榔,是定期調(diào)整CR的方法纹蝴。
For a guide on Reconcilers, Clients, and interacting with resource Events, see the Client API doc.
Build and run the operator
在運(yùn)行operator之前,CRD必須在 Kubernetes apiserver注冊(cè):
$ kubectl create -f deploy/crds/cache.limingnihao.com_memcacheds_crd.yaml
然后有兩種方法踪少,運(yùn)行operator:
- 作為Kubernetes集群內(nèi)部的Deployment。
- 集群外部的一個(gè)Go程序糠涛。
1. Run as a Deployment inside the cluster
Note:
operator-sdk buikd
調(diào)用docker build
援奢,或者是buildah bud
。如果使用buildah
則跳過(guò)operator-sdk build
的跳過(guò)下面的說(shuō)明忍捡。如果使用docker
確保docker守護(hù)進(jìn)程正在運(yùn)行集漾,并且可以在沒(méi)有sudo的情況下運(yùn)行docker客戶(hù)機(jī)。您可以通過(guò)運(yùn)行docker version
來(lái)檢查砸脊,
Note:存在vendor/目錄具篇,運(yùn)行
$ go mod vendor
構(gòu)建memcached-operator image發(fā)布和注冊(cè):
$ operator-sdk build quay.io/$USERNAME/memcached-operator:v0.0.1
$ docker login quay.io
$ docker push quay.io/$USERNAME/memcached-operator:v0.0.1
# Update the operator manifest to use the built image name (if you are performing these steps on OSX, see note below)
$ sed -i "s|REPLACE_IMAGE|quay.io/$USERNAME/app-operator|g" deploy/operator.yaml
# On OSX use:
$ sed -i "" "s|REPLACE_IMAGE|quay.io/$USERNAME/app-operator|g" deploy/operator.yaml
或者只發(fā)布到本地
$ operator-sdk build memcached-operator:v0.0.1
Deployment清單在deploy/operator.yaml中生成。請(qǐng)確認(rèn)更新deployment imageREPLACE_IMAGE
凌埂,因?yàn)槟J(rèn)只是個(gè)占位符驱显。
containers:
- name: memcached-operator
# Replace this with the built image name
image: REPLACE_IMAGE
imagePullPolicy: IfNotPresent
安裝RBAC和發(fā)布memcached-operator:
kubectl create -f deploy/service_account.yaml
kubectl create -f deploy/role.yaml
kubectl create -f deploy/role_binding.yaml
kubectl create -f deploy/operator.yaml
kubectl create -f deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
2.Run locally outside the cluster
此方法在開(kāi)發(fā)周期中是首選的,以便更快地部署和測(cè)試瞳抓。
在環(huán)境變量中設(shè)置operator的名稱(chēng):
export OPERATOR_NAME=memcached-operator
使用$HOME/.kube/config中的默認(rèn)Kubernetes配置文件在本地運(yùn)行該operator:
$ operator-sdk run --local --namespace=default
2018/09/30 23:10:11 Go Version: go1.10.2
2018/09/30 23:10:11 Go OS/Arch: darwin/amd64
2018/09/30 23:10:11 operator-sdk Version: 0.0.6+git
2018/09/30 23:10:12 Registering Components.
2018/09/30 23:10:12 Starting the Cmd.
Create a Memcached CR
創(chuàng)建示例Memcached
的CR使用deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml`生成:
$ cat deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
apiVersion: "cache.example.com/v1alpha1"
kind: "Memcached"
metadata:
name: "example-memcached"
spec:
size: 3
$ kubectl apply -f deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
確保memcache -operator為CR創(chuàng)建部署:
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
memcached-operator 1 1 1 1 2m
example-memcached 3 3 3 3 1m
檢查pod和CR狀態(tài)埃疫,確認(rèn)memcached pods的狀態(tài)變化:
Update the size
在memcached CR 將spec.size
字段從3改成4:
apiVersion: "cache.example.com/v1alpha1"
kind: "Memcached"
metadata:
name: "example-memcached"
spec:
size: 4
$ kubectl apply -f deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml
確認(rèn)operator的deployment數(shù)量發(fā)生改變:
kubectl get deployment
cleanup
清除所有resources:
kubectl delete -f deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
kubectl delete -f deploy/operator.yaml
kubectl delete -f deploy/role_binding.yaml
kubectl delete -f deploy/role.yaml
kubectl delete -f deploy/service_account.yaml