使用 kubebuilder 創建並部署 k8s-operator


一、准備

本文中的示例運行環境及相關軟件版本如下:

  • Kubernetes v1.16.3
  • Go 1.15.6
  • Kubebuilder 3.1.0
  • Docker 20.10.7

安裝kubebuilder:

#下載kubebuilder 3.1.0,建議二進制版本:https://github.com/kubernetes-sigs/kubebuilder/releases
#將二進制文件copy到/usr/local/bin下 
% chmod +x kubebuilder && mv kubebuilder /usr/local/bin/
#驗證 
% kubebuilder version

二、創建項目

% mkdir guestbook 
% cd guestbook %
% go mod init guestbook //go mod管理包 
% kubebuilder init --domain xiaohongshu.org --owner "luxiu"

三、創建API

% kubebuilder create api --group redis  --version v1 --kind RedisCluster
Create Resource [y/n]
y
Create Controller [y/n]
y
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
api/v1/rediscluster_types.go
controllers/rediscluster_controller.go
Update dependencies:
$ go mod tidy
Running make:
$ make generate
go: creating new go.mod: module tmp
Downloading sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1
go: found sigs.k8s.io/controller-tools/cmd/controller-gen in sigs.k8s.io/controller-tools v0.4.1
/Users/luxiu/Desktop/luxiu/project/kubernetes/crd-test/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."

API 創建完成后,在項目根目錄下查看目錄結構:

四、安裝 CRD

這里安裝CRD到指定的k8s集群里,需要修改Makefile里連接k8s配置:

install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
        $(KUSTOMIZE) build config/crd | kubectl --context cls-j07gq3ud-context-default  apply -f -
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config.
        $(KUSTOMIZE) build config/crd | kubectl --context cls-j07gq3ud-context-default  delete -f -
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
        cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
        $(KUSTOMIZE) build config/default | kubectl --context cls-j07gq3ud-context-default apply -f -
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.
        $(KUSTOMIZE) build config/default | kubectl --context cls-j07gq3ud-context-default delete -f -

執行下面命令來安裝CRD:

 % make install
/Users/luxiu/Desktop/luxiu/project/kubernetes/crd-test/bin/controller-gen "crd:trivialVersions=true,preserveUnknownFields=false" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
/Users/luxiu/Desktop/luxiu/project/kubernetes/crd-test/bin/kustomize build config/crd | kubectl --context cls-j07gq3ud-context-default  apply -f -
customresourcedefinition.apiextensions.k8s.io/redisclusters.redis.xiaohongshu.org created

五、部署 Controller

在開始部署 controller 之前,我們需要先檢查 kubebuilder 自動生成的 YAML 文件。

修改使用 gcr.io 鏡像倉庫的鏡像地址

對於中國大陸用戶,可能無法訪問 Google 鏡像倉庫 gcr.io,因此需要修改 config/default/manager_auth_proxy_patch.yaml 文件中的鏡像地址,將其中 gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 修改為quay.io/brancz/kube-rbac-proxy:v0.8.0

有兩種方式運行 controller:

  • 本地運行,用於調試
  • 部署到 Kubernetes 上運行,作為生產使用

本地運行 controller

要想在本地運行 controller,只需要執行下面的命令,你將看到 controller 啟動和運行時輸出:

$ make run

將 Controller 部署到指定 Kubernetes集群

這里有個問題,需要修改Dockerfile中 ,給go 設置proxy代理,這樣go mod download時不至於超時連不上:

在 RUN go mod download 這行的上面加如下一行:
ENV GOPROXY="https://goproxy.cn"

構建 controller 的鏡像,並推送到公司docker harbor 上,然后在 Kubernetes 上部署 Deployment 資源,如下命令:

$ make docker-build  IMG=docker-reg.devops.xiaohongshu.com/data-infra/rediscluster:v1
$ make docker-push  IMG=docker-reg.devops.xiaohongshu.com/data-infra/rediscluster:v1
$ make deploy  IMG=docker-reg.devops.xiaohongshu.com/data-infra/rediscluster:v1

在初始化項目時,kubebuilder 會自動根據項目名稱創建一個 Namespace,如本文中的guestbook-system ,查看 Deployment 對象和 Pod 資源。

% k8sdev get deployment -n guestbook-system
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
guestbook-controller-manager   1/1     1            1           25h
% k8sdev get pod  -n guestbook-system
NAME                                            READY   STATUS    RESTARTS   AGE
guestbook-controller-manager-79fd58d674-fvm2m   2/2     Running   0          145m

六、創建 CR

該創建自定義資源對象CR了,如原生中的rc/deployment等對象

% k8sdev apply -f config/samples/redis_v1_rediscluster.yaml
rediscluster.redis.xiaohongshu.org/rediscluster-sample created
% k8sdev get RedisCluster
NAME                  AGE
rediscluster-sample   38s

至此一個基本的 Operator 框架已經創建完成,但這個 Operator 只是修改了 etcd 中的數據而已,實際上什么事情也沒做,因為我們沒有在 Operator 中的增加業務邏輯。

七、開發業務邏輯

下面我們將修改 CRD 的數據結構並在 controller 中增加一些日志輸出。

修改 CRD

我們將修改api/v1/guestbook_types.go 文件的內容,在 CRD 中增加 FirstNameLastName 和 Status 字段。

// GuestbookSpec defines the desired state of Guestbook
type GuestbookSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// Foo is an example field of Guestbook. Edit guestbook_types.go to remove/update
	FirstName string `json:"firstname"`
	LastName  string `json:"lastname"`
}

// GuestbookStatus defines the observed state of Guestbook
type GuestbookStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file
	Status string `json:"Status"`
}

修改 Reconcile 函數

Reconcile 函數是 Operator 的核心邏輯,Operator 的業務邏輯都位於 controllers/guestbook_controller.go 文件的 Reconcile 函數中

func (r *GuestbookReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	_ = log.FromContext(ctx)

	// your logic here
	// 獲取當前的 CR,並打印
	logger := log.FromContext(ctx)
	obj := &webappv1.Guestbook{}
	if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
		logger.Error(err, "Unable to fetch object")
		return ctrl.Result{}, nil
	} else {
		logger.Info("Greeting from Kubebuilder to", obj.Spec.FirstName, obj.Spec.LastName)
	}

	// 初始化 CR 的 Status 為 Running
	obj.Status.Status = "Running"
	if err := r.Status().Update(ctx, obj); err != nil {
		logger.Error(err, "unable to update status")
	}

	return ctrl.Result{}, nil
}

運行測試

  • 安裝CRD(同上)
  • 部署controller(同上)
  • 創建CR

 修改 config/samples/redis_v1_rediscluster.yaml 文件中的配置

apiVersion: redis.xiaohongshu.org/v1
kind: RedisCluster
metadata:
  name: rediscluster-sample
spec:
  # Add fields here
  firstname: Jimmy
  lastname: Song

執行下面命令,創建CR:

$ k8sdev apply -f  config/samples/redis_v1_rediscluster.yaml

查看controller里的運行日志:

% k8sdev get pod  -n guestbook-system
NAME                                            READY   STATUS    RESTARTS   AGE
guestbook-controller-manager-79fd58d674-fvm2m   2/2     Running   0          3h53m

% k8sdev logs -f guestbook-controller-manager-79fd58d674-fvm2m -n guestbook-system -c manager
2022-03-08T08:24:04.641Z	INFO	controller-runtime.manager.controller.guestbook	Greeting from Kubebuilder to	{"reconciler group": "webapp.my.domain", "reconciler kind": "Guestbook", "name": "guestbook-sample", "namespace": "default", "Jimmy": "Song"}
2022-03-08T08:24:04.651Z	INFO	controller-runtime.manager.controller.guestbook	Greeting from Kubebuilder to	{"reconciler group": "webapp.my.domain", "reconciler kind": "Guestbook", "name": "guestbook-sample", "namespace": "default", "Jimmy": "Song"}

 

 

參考:部署k8s operator

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM