1. 程式人生 > >Kubernetes Informer 詳解

Kubernetes Informer 詳解

Informer 簡介

這邊文章只是個人愛好轉載,不提供任何的意見和建議

Informer 基礎功能

Informer 是 Client-go 中的一個核心工具包。在 Kubernetes 原始碼中,如果 Kubernetes 的某個元件,需要 List/Get Kubernetes 中的 Object,在絕大多 數情況下,會直接使用 Informer 例項中的 Lister()方法(該方法包含 了 Get 和 List 方法),而很少直接請求 Kubernetes API。Informer 最基本 的功能就是 List/Get Kubernetes 中的 Object。

如下圖所示,僅需要十行左右的程式碼就能實現對 Pod 的 List 和 Get。

info

Informer 高階功能

Client-go 的首要目標是滿足 Kubernetes 的自身需求。Informer 作為其中的核心工具包,面對 Kubernetes 極為複雜業務邏輯,如果僅實現 List/Get 功能,根本無法滿足 Kubernetes 自身需求。因此,Informer 被設計為一個靈活而複雜的工具包,除 List/Get Object 外,Informer 還可以監聽事件並觸發回撥函式等,以實現更加複雜的業務邏輯。

Informer 設計思路

Informer 設計中的關鍵點

為了讓 Client-go 更快地返回 List/Get 請求的結果、減少對 Kubenetes API 的直接呼叫,Informer 被設計實現為一個依賴 Kubernetes List/Watch API 、可監聽事件並觸發回撥函式的二級快取工具包。

更快地返回 List/Get 請求,減少對 Kubenetes API 的直接呼叫

使用 Informer 例項的 Lister() 方法, List/Get Kubernetes 中的 Object 時,Informer 不會去請求 Kubernetes API,而是直接查詢快取在本地記憶體中的資料(這份資料由 Informer 自己維護)。通過這種方式,Informer 既可以更快地返回結果,又能減少對 Kubernetes API 的直接呼叫。

依賴 Kubernetes List/Watch API

Informer 只會呼叫 Kubernetes List 和 Watch 兩種型別的 API。Informer 在初始化的時,先呼叫 Kubernetes List API 獲得某種 resource 的全部 Object,快取在記憶體中; 然後,呼叫 Watch API 去 watch 這種 resource,去維護這份快取; 最後,Informer 就不再呼叫 Kubernetes 的任何 API。

用 List/Watch 去維護快取、保持一致性是非常典型的做法,但令人費解的是,Informer 只在初始化時呼叫一次 List API,之後完全依賴 Watch API 去維護快取,沒有任何 resync 機制。

筆者在閱讀 Informer 程式碼時候,對這種做法十分不解。按照多數人思路,通過 resync 機制,重新 List 一遍 resource 下的所有 Object,可以更好的保證 Informer 快取和 Kubernetes 中資料的一致性。

諮詢過 Google 內部 Kubernetes 開發人員之後,得到的回覆是: 
在 Informer 設計之初,確實存在一個 relist 無法去執 resync 操作, 但後來被取消了。原因是現有的這種 List/Watch 機制,完全能夠保證永遠不會漏掉任何事件,因此完全沒有必要再新增 relist 方法去 resync informer 的快取。這種做法也說明了 Kubernetes 完全信任 etcd。 
可監聽事件並觸發回撥函式

Informer 通過 Kubernetes Watch API 監聽某種 resource 下的所有事件。而且,Informer 可以新增自定義的回撥函式,這個回撥函式例項(即 ResourceEventHandler 例項)只需實現 OnAdd(obj interface{}) OnUpdate(oldObj, newObj interface{}) 和 OnDelete(obj interface{}) 三個方法,這三個方法分別對應 informer 監聽到建立、更新和刪除這三種事件型別。

在 Controller 的設計實現中,會經常用到 informer 的這個功能。 Controller 相關文章請見此文《如何用 client-go 拓展 Kubernetes 的 API》。

二級快取

二級快取屬於 Informer 的底層快取機制,這兩級快取分別是 DeltaFIFO 和 LocalStore。

這兩級快取的用途各不相同。DeltaFIFO 用來儲存 Watch API 返回的各種事件 ,LocalStore 只會被 Lister 的 List/Get 方法訪問 。

雖然 Informer 和 Kubernetes 之間沒有 resync 機制,但 Informer 內部的這兩級快取之間存在 resync 機制。

以上是 Informer 設計中的一些關鍵點,沒有介紹一些太細節的東西,尤其對於 Informer 兩級快取還未做深入介紹。下一章節將對 Informer 詳細的工作流程做一個詳細介紹。

Informer 詳細解析

Informer 內部主要元件

Informer 中主要包含 Controller、Reflector、DeltaFIFO、LocalStore、Lister 和 Processor 六個元件,其中 Controller 並不是 Kubernetes Controller,這兩個 Controller 並沒有任何聯絡;Reflector 的主要作用是通過 Kubernetes Watch API 監聽某種 resource 下的所有事件;DeltaFIFO 和 LocalStore 是 Informer 的兩級快取;Lister 主要是被呼叫 List/Get 方法;Processor 中記錄了所有的回撥函式例項(即 ResourceEventHandler 例項),並負責觸發這些函式。

Informer 關鍵邏輯解析

我們以 Pod 為例,詳細說明一下 Informer 的關鍵邏輯:

Informer 在初始化時,Reflector 會先 List API 獲得所有的 Pod 
Reflect 拿到全部 Pod 後,會將全部 Pod 放到 Store 中 
如果有人呼叫 Lister 的 List/Get 方法獲取 Pod, 那麼 Lister 會直接從 Store 中拿資料

Informer 初始化完成之後,Reflector 開始 Watch Pod,監聽 Pod 相關 的所有事件;如果此時 pod_1 被刪除,那麼 Reflector 會監聽到這個事件 
Reflector 將 pod_1 被刪除 的這個事件傳送到 DeltaFIFO 
DeltaFIFO 首先會將這個事件儲存在自己的資料結構中(實際上是一個 queue),然後會直接操作 Store 中的資料,刪除 Store 中的 pod_1 
DeltaFIFO 再 Pop 這個事件到 Controller 中

info02

Controller 收到這個事件,會觸發 Processor 的回撥函式

info03

LocalStore 會週期性地把所有的 Pod 資訊重新放到 DeltaFIFO 中

參考 https://blog.csdn.net/qq_21816375/article/details/78240541