Kubernetes源碼學習-Controller-P2-Controller與client-go

病毒肆虐,陰雨連綿,門房緊閉,親友不問,冷冷清清,甚是無趣。坐下寫寫代碼,總結下過去一年所學,整理兩篇文章,倒也算是樂得自在。盼疫情早日控制,春回大地,願同胞們身體安康,祝新年快樂!

P2-Controller與client-go

前言

Controller作爲k8s的資源控制組件,必定要實時地監控對比資源的目標狀態和當前狀態,這其中會與apiserver產生大量的交互。在k8s中,k8s各個組件都會與apiServer交互,因此k8s在項目中封裝了一個client-go公用模塊,路徑位於項目vendor/k8s.io/client-go,非常多的組件向ApiServer的curd操作都在client-go包中封裝,client-go是k8s項目的核心包之一。它與controller的工作流程密不可分,在讀controller源碼理解其工作流程前,必須首先對informer有一定得了解,因此本篇專門對informer機制進行簡單地介紹說明,爲後面的文章鋪墊。

ApiServer的連接方式

1.短連接

獲取kubernetes某種資源的方式有多種,常見的如kubectl、調用apiserver restful api的接口,restful api接口詳情查看官方手冊。同時也可通過kubectl命令來查看操作對應的api,例如:

kubectl get pod POD_NAME -v=9

輸出信息中會包含此操作對應的api url

但這種全量型的操作方式,在大集羣規模下,開銷還是比較大的,因此,k8s還提供長連接的watch接口。

2.長連接

watch接口是對list接口的一種改進,在調用watch接口後,首先會一次性返回list的數據,同時會保持會話連接,後續的接口對象的curd,都會產生事件由apiserver將變更數據推送給調用端,調用端接收數據後,再更新初始接收到的list的全量數據以及其他操作。

3.client-go

watch依然比較麻煩,畢竟list獲取的數據以及後續watch到的數據,需要調用端在內部處理和更新緩存。索性,官方提供了一個client-go客戶端工具包封裝,裏面提供多種apiserver相關操作,做到開箱即用,k8s各組件也都使用了它。

client-go工作模式

在client-go中,informer是對watch操作的一次再封裝, Informer是一個帶有本地緩存、索引功能的client端(list/watch),在絕大多數場景下,客戶端與apiserver的交互都是讀多寫少的,因此,做好本地緩存(Store)和索引(Index)可以大幅減少開銷提升性能。同時,informer可以註冊相應的EventHandler事件觸發器的,在執行資源更新後觸發其他連鎖操作。

工作流程圖

流程圖組件解釋

圖中有上下分層,上層邏輯由client-go內部封裝,下層的邏輯由controller內部完成,對照上圖分層說明:

上層

  • Reflector:反射器,調用 Kubernetes 的 List/Watch API,實現對 apiserver 指定類型對象的監控(List/Watch),將獲取的數據,反序列化成對象實例,存入delta 緩存隊列中;

  • DeltaIFIFO Queue:一個增量fifo緩存隊列,接收來自 Reflector 傳遞的反序列化對象;

  • Informer:是這個流程中的關鍵重要的橋樑,主要有兩個工作:1.從DeltaIFIFO Queue中獲取對象,更新LocalStore的cache數據 2.觸發後續的eventHandler,生成工作隊列對象,加入WorkQueue,供後面的controller讀取進行實際的控制處理工作。(值得注意的是,每一種資源都對應一個informer,多種資源對應多個informer,但每個informer都會與apiserver建立起一個watch長連接,通常controller都會使用SharedInformerFactory這個單例工廠模式,來使所有的informer的創建全部都經過這個單例工廠,從而保證每種資源對應的informer都是唯一且可複用的,以降低開銷。)

  • LocalStore:informer 的 cache緩存,這裏緩存的是從 apiserver 中獲取得到的對象(其中有一部分可能還在DeltaFIFO 中沒來得及放入緩存裏來),此時client再查詢對象的時候就直接從 cache 中查找,減少了 apiserver 的壓力,LocalStore 只會被 Lister 的 List/Get 讀操作的方法訪問;

下層

  • ResourceEventHandler:由controller註冊,由informer來觸發,當resource object符合過濾規則時,觸發ResourceEventHandler將其丟入WorkQueue內。

  • WorkQueue:informer更新本地的緩存後,會根據註冊的相關EventHandler,生成事件放入WorkQueue內,Controller 接收 WorkQueue 中的事件,然後相應執行controller的業務邏輯,一般來說,就是保證資源對象的目標狀態與實際狀態達成一致的邏輯。

如果你想自定義controller,關於infomer的實踐建議,參考這裏:

如何用 client-go 拓展 Kubernetes 的 API

總結

本篇先簡單介紹一下client-go包和controller組件的結合工作流程,爲後面的幾篇(deploymentCrontroller、statefulSetController)代碼分析作鋪墊,後面的文章會結合controller實例代碼再仔細講解細節。

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