3.3.3 Controller
Controller是 Controller-runtime的核心結構, 其實作了 Controller的基本邏輯:Controller管理一個工作隊列,并從 source.Sources中擷取 reconcile.Requests加入隊列,通過執行 reconcile.Reconciler來處理隊列中的每項 reconcile.Requests,而 reconcile.
Reconciler可以通過讀寫 Kubernetes 資源來確定叢集狀态與期望狀态一緻。
接口:
Controller接口定義在 pkg/controller/controller.go下,包括如下内容。
(1) reconcile.Reconciler:匿名接口,定義了 Reconcile(context.Context,Request)
(Result,error)。
(2) Watch(srcsource.Source,eventhandlerhandler.EventHandler,predicates
...predicate.Predicate)error:定義入隊 reconcile.Requests,Watch() 方法會從 sour-ce.Source中擷取Event, 并根據參數 Eventhandler來決定如何入隊, 根據參數Predicates進行 Event過濾,Preficates可能有多個, 隻有所有的 Preficates都傳回True 時,才會将 Event 發送給 Eventhandler 處理。
(3) Start(ctxcontext.Context)error:Controller的啟動方法,實作了 Controller接口的對象,也實作了Runnable,是以,該方法可以被Manager管理。
(4) GetLogger()logr.Logger:擷取 Controller内的 Logger,用于日志輸出。
實作:
Controller的實作在 pkg/internal/controller/controller.go下,為結構體 Controller,Controller結構體中包括的主要成員如下。
(1) Namestring:必須設定, 用于辨別 Controller,會在 Controller的日志輸出中進行關聯。
(2) MaxConcurrentReconcilesint:定義允許 reconcile.Reconciler 同時運作的最多個數,預設為 1。
(3) Doreconcile.Reconciler:定義了 Reconcile() 方法,包含了 Controller同步的業務邏輯。Reconcile()能在任意時刻被調用,接收一個對象的 Name與 Namespace,并同步叢集目前實際狀态至該對象被設定的期望狀态。
(4) MakeQueue func() workqueue.RateLimitingInterface:用 于在 Controller啟動時,建立工作隊列。由于标準的Kubernetes工作隊列建立後會立即啟動,是以,如果在 Controller啟動前就建立隊列,在重複調用 controller.New() 方法建立 Con-troller 的情況下,就會導緻 Goroutine 洩露。
(5) Queueworkqueue.RateLimitingInterface:使用上面方法建立的工作隊列。
(6) SetFieldsfunc(iinterface{})error:用 于 從 Manager中 獲 取 Controller依賴的方法, 依賴包括 Sourcess、EventHandlers和 Predicates等。 此方法存儲的是controllerManager.SetFields()方法。
(7) StartedBool:用于表示Controller 是否已經啟動。
(8) CacheSyncTimeouttime.Duration:定義了 Cache 完成同步的等待時長,超過時長會被認為是同步失敗。預設時長為 2分鐘。
(9) startWatches[ ]watchDescription:定 義 了 一 組Watch操 作 的 屬 性, 會在Controller啟動時, 根據屬性進行 Watch操作。watchDescription的定義見代碼 清單3-30,watchDescription包括 Event的源 source.Source、Event的入隊方法handler.EventHandler以及 Event的過濾方法 predicate.Predicate。
typewatchDescriptionstruct{srcsource.Source
handlerhandler.EventHandlerpredicates[]predicate.Predicate
}
(10) LogLogr.Logger:用于記錄日志的日志對象。
Controller的主要邏輯在Controller.Start()方法内,流程如圖 3-4所示。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yM2gTO0MGMzMDNxUWO2ATO1MGO0gDO0ImYjFmYmlDZz8CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
圖 3—4Controiier 邏輯
(1) 在Manager調用 Start()方法後,進入 Controller 的啟動流程,經過選舉等預處理後,Controller進入Start()方法。
(2) Controller根據 MakeQueue() 建立工作隊列,并啟動工作隊列。
(3) Controller根據 startWatches參數啟動各個 Watch 流程,并将工作隊列注入各個Watcher中。
(4) Controller根據 MaxConcurrentReconciles啟動多個 Worker程式,用于處理隊列中的對象。
(5) Work程式先從工作隊列中擷取需要處理的對象,然後調用 Controller成員 Do的 Reconcile()方法進行處理。
(6) 根據 Reconcile() 方法傳回的結果, 将對象重新入隊列或從隊列中删除。重新入隊列的方法可以是帶有一定延遲的Queue.AddAfter(), 也可以是有限速的 Queue.AddRateLimited()。重新加入的次數無限制。