如何在Kubernetes中編寫自定義控制器

在這裏插入圖片描述在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述
在這裏插入圖片描述
接下來一起來看看: 聲明式API對象的編程範式
API對象的組織方式

API對象在Etcd裏的完整資源路徑是由 Group(API組)、Version(API版本)和Resource(API資源類型)三部分組成。

Kubernetes創建資源對象的流程:

首先Kubernetes讀取用戶提交的yaml文件
然後Kubernetes去匹配yaml文件中API對象的組
再次Kubernetes去匹配yaml文件中API對象的版本號
最後Kubernetes去匹配yaml文件中API對象的資源類型

因此我們需要根據需求先進行自定義資源(CRD - Custom Resource Definition),它將包括API對象組、版本號、資源類型:
在這裏插入圖片描述
在上面的yaml文件中指定group: spursyyversion: v1API的組和版本號信息、也指定了CR資源類型叫做MyResource,複數是myresources、同時還聲明該資源是Namespaced的對象。

然後我們就可以使用剛纔定義的資源對象:

  • 資源類型指定爲MyResource
  • 資源組爲spursy
  • 資源的版本號爲v1

如果只定義資源對象,而不定義相應的控制,資源對象並不能發揮任何效用。接下來我們一起看看如何自定義資源控制器。

a. 控制器如何與APIServer通信

Informer是APIServer與Kubernetes相互通信的橋樑,它通過Reflector實現ListAndWatch方法來“獲取”和“監聽”對象實例的變化
每當APIServer接收到創建、更新和刪除實例的請求,Refector都會收到“事件通知”,然後將變更的事件推送到先進先出的隊列中
Informer會不斷從上一隊列中讀取增量,然後根據增量事件的類型創建或者更新本地對象的緩存
Informer會根據事件類型觸發事先定義好的ResourceEventHandler(具體爲AddFunc、UpdatedFunc和DeleteFunc,分別對應API對象的“添加”、“更新”和“刪除”事件)
同時每隔一定的時間Informer也會對本地的緩存進行一次強制更新

b. WorkQueue同步Informer跟控制循環(Control Loop)交互的數據

c. Controller Loop 扮演這Kubernetes控制器的角色,確保期望與實際的運行的狀態是一致的

在這裏插入圖片描述
綜上所述,如何使用控制器模式,同 Kubernetes 裏 API 對象的“增、刪、改、查”進行協作,進而完成用戶業務邏輯的編寫過程。這就是“Kubernetes 編程範式”。

瞭解了Kubernetes的控制器模型和API的編程範式,接下來我將介紹 如何自定義控制器

Operator

Operator 是由 CoreOS 開發的,用來擴展 Kubernetes API,特定的應用程序控制器,它用來創建、配置和管理複雜的有狀態應用,如數據庫、緩存和監控系統。接下來我將使用Operator SDK,自定義用來控制Pod數量的特定資源。簡而言之就是實現類似Kubernetes ReplicaSet類型的資源。

在使用Operator SDK自定義資源前,我們需要明確兩點:

  1. Operator SDK的工作流

使用 SDK 創建一個新的 Operator 項目
通過添加自定義資源(CRD)定義新的資源 API
指定使用 SDK API 來 watch 的資源
定義 Operator 的協調(reconcile)邏輯
使用 Operator SDK 構建並生成 Operator 部署清單文件

  1. 明確第一資源和第二資源

像上述我們即將實現類ReplicaSet自定義資源中,第一資源是ReplicaSet自身(明確指定運行的Docker鏡像和ReplicaSet中Pod的數量)、第二資源是運行的Pod。當ReplicaSet中屬性發生變化(如自定的Docker鏡像,或者指定Pod副本的數量)或者Pod的發生變化(如Pod的實際運行數量減少),Controller控制器通過前文講的控制循環一旦發現上述變化,就會通過變更Pod中鏡像的版本或者伸縮Pod的數量調諧(reconcile)集羣中ReplicaSet資源的狀態。

瞭解了Operator 的原理,接下來我將通過一個demo演示如何通過 Operator SDK創建資源

如果小夥伴想了解更多關於Operator SDK的相關知識可參照github官方倉庫 https://github.com/operator-framework/operator-sdk

使用SDK生成go項目框架
operator-sdk new podset-operator

生成的項目文件結構如下圖:
在這裏插入圖片描述
爲剛纔生成代碼添加自定義API
operator-sdk add api --api-version=app.example.com/v1alpha1 --kind=PodSet

添加自定義控制器
operator-sdk add controller --api-version=app.example.com/v1alpha1 --kind=PodSet

修改 */podset-operator/pkg/apis/app/v1alpha1/podset_types.go文件中的PodSetSpec 和 PodSetStatus

在這裏插入圖片描述

需要特別注意:我們一旦對Operator SDK生成的框架做任何修改,都需要執行operator-sdk generate k8s,重新生成相應的pkg/apis/app/v1alpha1/zz_generated.deepcopy.go文件

最後我們需要實現控制器中自動伸縮的代碼
代碼修改是在控制器Reconcile的函數中/podset-operator/pkg/controller/podset/podset_controller.go

我需要明確一下邏輯:

PodSet或者歸屬於PodSet的Pod一旦發生變化都會觸發reconcile函數
無論是增加還是刪除Pod,Reconcile函數每次都只能增刪一個Pod,然後返回,等待下一次觸發Reconcile函數
確保歸屬於PodSet第一資源的Pod使用controllerutil.SetControllerReference()函數,這樣當第一資源刪除時,系統會自動將相應的Pod刪除

控制器的實現邏輯可參見 https://github.com/spursy/podset-operator/blob/master/pkg/controller/podset/podset_controller.go#L86

接下來 將使用Operator SDK生成部署文件
將Operator項目打包成鏡像

operator-sdk build spursyy/podset-operator

推送到docker hub

docker push spursyy/podset-operator

修改operator.yaml文件

sed -i “” ‘s|REPLACE_IMAGE|spursyy/podset-operator|g’ deploy/operator.yaml

最後是將 上一步生成的文件部署到集羣中
創建service account
create -f deploy/service_account.yaml

爲service account做RBAC認證
kubectl create -f deploy/role.yaml
kubectl create -f deploy/role_binding.yaml

部署CRD和Operator文件

kubectl create -f deploy/crds/app_v1alpha1_podset_crd.yaml
kubectl create -f deploy/operator.yaml

以上我們定義了CRD,並將Operator SDK生成的控制器代碼部署到集羣后,我們就可以實現在集羣中部署自定義的資源

echo “apiVersion: app.example.com/v1alpha1
kind: PodSet
metadata:
name: example-podset
spec:
replicas: 3” | oc create -f -

以上完整代碼在我的github 倉庫中 https://github.com/spursy/podset-operator

本次交流的內容我已經發布到知識分享平臺平臺 https://juejin.im/post/5e015ac46fb9a0160a313f68

發佈了73 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章