歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類彙總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等;
系列文章連結
- kubebuilder實戰之一:準備工作
- kubebuilder實戰之二:初次體驗kubebuilder
- kubebuilder實戰之三:基礎知識速覽
- kubebuilder實戰之四:operator需求說明和設計
- kubebuilder實戰之五:operator編碼
- kubebuilder實戰之六:構建部署執行
- kubebuilder實戰之七:webhook
- kubebuilder實戰之八:知識點小記
本篇概覽
- 作為《kubebuilder實戰》系列的第三篇,本該進入真槍實彈的operator開發環節,卻突然發現kubebuilder涉及的知識點太多太零散,如果現在就敲命令寫程式碼去實戰,即便完成了一次operator開發,但缺失大量資訊(例如操作順序怎麼安排、步驟之間如何關聯等),不但《kubebuilder實戰》系列失去參考價值,過幾個月就連我自己都看不懂這些內容了,因此,本篇暫緩實戰,我們們一起對kubebuilder開發過程中的知識點做一次速記,再從容的啟動開發工作;
- 特別說明:webhook是operator中的重要功能,其理論和實戰都需要大量篇幅,因此後面會有這方面專門的文章,本文不會涉及webhook的知識點;
- 接下來,大串講開始;
知識儲備
- 能看懂kubebuilder官方demo的程式碼、會用client物件操作kubernetes資源,以上兩點是勝任operator開發的最基本要求,否則在開發過程中會有種寸步難行的感覺,達到這些條件需要少量的知識儲備,現在欣宸已經為您準備好了,希望您能簡單瀏覽一下:
- 《Kubernetes的Group、Version、Resource學習小記》
- 《client-go實戰之一:準備工作》
- 《client-go實戰之二:RESTClient》
- 《client-go實戰之三:Clientset》
- 《client-go實戰之四:dynamicClient》
- 《client-go實戰之五:DiscoveryClient》
初始化相關知識點
- 建立operator的第一步,就是用kubebuilder命令列建立整個專案,這個在《kubebuilder實戰之二:初次體驗kubebuilder》已經試過,當時執行的是如下三行命令:
mkdir -p $GOPATH/src/helloworld
cd $GOPATH/src/helloworld
kubebuilder init --domain com.bolingcavalry
- 在用上module之後,大家已經脫離了$GOPATH的束縛,像上面那樣中規中矩的去$GOPATH/src下面操作就略有些彆扭了,來試試不用$GOPATH的初始化方式;
- 隨處新建一個目錄(路徑中不要有中文和空格),例如/Users/zhaoqin/temp/202102/15/elasticweb
- 在目錄中用go mod init elasticweb命令新建名為elasticweb的工程;
- 再執行kubebuilder init --domain com.bolingcavalry,即可新建operator工程;
基礎設施
- operator工程新建完成後,會新增不少檔案和目錄,以下幾個是官方提到的基礎設施:
- go.mod:module的配置檔案,裡面已經填充了幾個重要依賴;
- Makefile:非常重要的工具,前文我們們也用過了,編譯構建、部署、執行都會用到;
- PROJECT:kubebuilder工程的後設資料,在生成各種API的時候會用到這裡面的資訊;
- config/default:基於kustomize製作的配置檔案,為controller提供標準配置,也可以按需要去修改調整;
- config/manager:一些和manager有關的細節配置,例如映象的資源限制;
- config/rbac:顧名思義,如果像限制operator在kubernetes中的操作許可權,就要通過rbac來做精細的許可權配置了,這裡面就是許可權配置的細節;
main.go
- main.go是kubebuilder自動生成的程式碼,這是operator的啟動程式碼,裡面有幾處值得注意:
- 兩個全域性變數,如下所示,setupLog用於輸出日誌無需多說,scheme也是常用的工具,它提供了Kind和Go程式碼中的資料結構的對映,:
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
- 另外還有些設定,例如監控指標相關的,以及管理controller和webhook的manager,它會一直執行下去直到被外部終止,關於這個manage還有一處要注意的地方,就是它的引數,下圖是預設的引數,如果您想讓operator在指定namespace範圍內生效,還可以在下午的地方新增Namespace引數,如果要指定多個nanespace,就使用cache.MultiNamespacedCacheBuilder(namespaces)引數:
- main.go的內容在大多數場景無需改動,瞭解即可,接下來的API是重頭戲;
API相關(資料核心)
- API是operator的核心,當您決定使用operator時,就應該從真實需求出發,開始設計整個CRD,而這些設計最終體現在CRD的資料結構,以及對真實值和期望值的處理邏輯中;
- 在《kubebuilder實戰之二:初次體驗kubebuilder》我們們建立過API,當時的命令是:
kubebuilder create api \
--group webapp \
--version v1 \
--kind Guestbook
-
- kubebuilder自動新增了很多內容,如下圖,都是為了這個CRD服務的:
-
- 新增的內容中,最核心的當然是CRD了,也就是上圖中Guestbook資料結構所在的guestbook_types.go檔案,這個最重要的資料結構如下:
type Guestbook struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec GuestbookSpec `json:"spec,omitempty"`
Status GuestbookStatus `json:"status,omitempty"`
}
- metav1.TypeMeta:儲存了資源的Group、Version、Kind
- metav1.ObjectMeta:儲存了資源物件的名稱和namespace
- Spec:期望狀態,例如deployment在建立時指定了pod有三個副本
- Status:真實狀態,例如deployment在建立後只有一個副本(其他的還沒有建立成功),大多數資源物件都有此欄位,不過ConfigMap是個例外(想想也是,配置資訊嘛,配成啥就是啥,沒有什麼期望值和真實值的說法);
- 還有一個資料結構,就是Guestbook對應的列表GuestbookList,就是單個資源物件的集合;
- guestbook_types.go所在目錄下還有兩個檔案:groupversion_info.go定義了Group和Version,以及註冊到scheme時用到的例項SchemeBuilder,zz_generated.deepcopy.go用於實現例項的深拷貝,它們都無需修改,瞭解即可;
controller相關(業務核心)
- 前面聊過了資料核心,接下來要討論如何實現業務需求了,在operator開發過程中,儘管業務邏輯各不相同,但有兩個共性:
- Status(真實狀態)是個資料結構,其欄位是業務定義的,其欄位值也是業務程式碼執行自定義的邏輯算出來的;
- 業務核心的目標,是確保Status與Spec達成一致,例如deployment指定了pod的副本數為3,如果真實的pod沒有三個,deployment的controller程式碼就去建立pod,如果真實的pod超過了三個,deployment的controller程式碼就去刪除pod;
- 以上就是我們們的controller要做的事情,接下來看看程式碼的細節,kubebuilder建立的guestbook_controller.go就是controller,我們們的業務程式碼都寫在這個檔案中,來看看kubebuilder幫我們準備了什麼:
- 資料結構定義,如下所示,操作資源物件時用到的客戶端工具client.Client、日誌工具、Kind和資料結構的關係Scheme,這些都幫我們準備好了,真貼心:
type GuestbookReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
- SetupWithManager方法,在main.go中有呼叫,指定了Guestbook這個資源的變化會被manager監控,從而觸發Reconcile方法:
func (r *GuestbookReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&webappv1.Guestbook{}).
Complete(r)
}
- 如下圖,Reconcile方法前面有一些+kubebuilder:rbac字首的註釋,這些是用來確保controller在執行時有對應的資源操作許可權,例如紅框中就是我自己新增的,這樣controller就有權查詢pod資源物件了:
- guestbook_controller.go是operator的業務核心,而controller的核心是其Reconcile方法,將來我們們的大部分程式碼都是寫在這裡面的,主要做的事情就是獲取status,然後讓status和spec達成一致;
- 關於status,官方的一段描述值得重視,如下圖紅框,主要是說資源物件的狀態應該是每次重新計算出來的,這裡以deployment為例,想知道當前有多少個pod,有兩種方法,第一種準備個欄位記錄,每次對pod的增加和刪除都修改這個欄位,於是讀這個欄位就知道pod數量了,第二種方法是每次用client工具去實時查詢pod數量,目前官方明確推薦使用第二種方法:
- 至此,基礎知識串講就完成了,我們們按照官方資料的順序把知識點過了一遍,接下來,就是按照官方資料的順序去實戰了,讓大家久等了,下一篇,operator實戰;
你不孤單,欣宸原創一路相伴
歡迎關注公眾號:程式設計師欣宸
微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界...
https://github.com/zq2599/blog_demos