Kubernetes資源擴展機制(二)
上篇 介紹了k8s中資源插件機制的核心關鍵組件,今天我們繼續來看下各個組件是如何進行通信的,以及K8s中針對事件處理背後的關鍵設計。
0 1
PluginManager
PluginManager是一個上層組件,其內部包含了上篇文章中的關鍵組件,並且協調其內部數據流,而且還提供針對不同插件的具體的控制器。
核心數據結構
核心結構裏面其實就是按照數據流來進行設計的,首先需要一個感知插件desiredStateOfWorldPopulator用於感知後端服務的創建或者刪除,然後將感知到的事件加入到desiredStateOfWorld期望狀態緩存,由reconciler負責期進行底層的註冊和下線,並且將結果存儲到actualStateOfWorld實際狀態緩存 。
type pluginManager struct { // 插件感知 desiredStateOfWorldPopulator *pluginwatcher.Watcher // 協調器插件 reconciler reconciler.Reconciler // 實際狀態緩存 actualStateOfWorld cache.ActualStateOfWorld // 期望狀態緩存 desiredStateOfWorld cache.DesiredStateOfWorld }
初始化
初始化中會將dsw和asw都交給reconciler用於進行事件的感知和更新對應的緩存 。
func NewPluginManager( sockDir string, recorder record.EventRecorder) PluginManager { asw := cache.NewActualStateOfWorld() dsw := cache.NewDesiredStateOfWorld() // 這裏會將期望狀態緩存和實際狀態緩存,都交給reconciler reconciler := reconciler.NewReconciler( operationexecutor.NewOperationExecutor( operationexecutor.NewOperationGenerator( recorder, ), ), loopSleepDuration, dsw, asw, ) pm := &pluginManager{ // 啓動一個watcher並且存儲dsw期望狀態緩存,後續reconciler就可以通過dsw感知到新的狀態了 desiredStateOfWorldPopulator: pluginwatcher.NewWatcher( sockDir, dsw, ), reconciler: reconciler, desiredStateOfWorld: dsw, actualStateOfWorld: asw, } return pm }
啓動插件管理器
插件管理器啓動其實就是啓動內部的desiredStateOfWorldPopulator就會講watcher感知的事件,不斷的修改自己的內部緩存這樣reconciler就可以不斷的通過期望狀態緩存,進行對應grpc的調用從而滿足期望狀態。
func (pm *pluginManager) Run(sourcesReady config.SourcesReady, stopCh <-chan struct{}) { defer runtime.HandleCrash() // 運行期望狀態緩存,其實主要是通過watcher感知到的事件,修改自身的緩存 // 後續reconciler會週期性的獲取 pm.desiredStateOfWorldPopulator.Start(stopCh) klog.V(2).Infof("The desired_state_of_world populator (plugin watcher) starts") klog.Infof("Starting Kubelet Plugin Manager") // 週期性的運行校證數據 go pm.reconciler.Run(stopCh) metrics.Register(pm.actualStateOfWorld, pm.desiredStateOfWorld) <-stopCh klog.Infof("Shutting down Kubelet Plugin Manager") }
控制器註冊
控制器其實主要是指的reconciler通過對比期望緩存和實際緩存之間的差異,產生對應的事件之後,針對該類型的插件,後續的處理流程是什麼,比如註冊/下線具體的grpc接口和對應插件類型的處理機制。
func (pm *pluginManager) AddHandler(pluginType string, handler cache.PluginHandler) { pm.reconciler.AddHandler(pluginType, handler) }
CSI與普通設備
當前的kubelet中有註冊兩種類型的插件控制器,CSI與DEVICPLUGIn,從名字上大家也能知道大概的意思。
kl.pluginManager.AddHandler(pluginwatcherapi.CSIPlugin, plugincache.PluginHandler(csi.PluginHandler)) kl.pluginManager.AddHandler(pluginwatcherapi.DevicePlugin, kl.containerManager.GetPluginRegistrationHandler())
0 2
PluginHandler
這裏我們只介紹一個即DevicePlugin的核心實現機制。
Endpoint
Endpoint其實指的就是某個提供擴展資源的服務,在之前說的reconciler中,會獲取其對應的grpc服務的地址,後續則會直接調用grpc進行通信。 Endpoint需要感知對應的資源設備的變化,同時將對 應的設備信息,回調通知給當前的。
Manager
Manager則是主要負責實現後端真正的Register/UnRegister的具體實現,其在內部會爲每個Device創建一個Endpoint並負責收集後端提供資源服務上報上來的信息, 最終會講對應的信息發送給kubelet,然後由kubelet在負責節點信息更新的時候,將信息傳遞給APIServer。
Checkpoint
Checkpoint機制其實在很多系統中都比較常用,主要是用於週期性的將內存中的數據序列化存儲到本地的磁盤中,在後續恢復的時候,會通過磁盤重新加載之前的數據,從而實現內存資源的快速恢復。
擴展資源的整體實現流程大概就是這個樣子,從如何感知數據,註冊資源服務,獲取資源服務的資源信息,並最終彙報給kubelet,同時落地本地磁盤,實現了完整的資源從感知到上報的整體流程的探測,其不足主要是在於關於資源實體的描述,從而導致資源的分配和資源的上報上有比較大的擴展性限制,比如要實現精細化的資源分配擴展,則不太能實現。
作者:8小時coding
原文地址:http://rrd.me/fKges