5. informer源碼分析-概要分析

k8s client-go k8s informers 實現了持續獲取集群的所有資源對象監聽集群的資源對象變化功能,并在本地維護了全量資源對象的內存緩存,以減少對 apiserver、對 etcd 的請求壓力。Informers 在啟動的時候會首先在客戶端調用 List 接口來獲取全量的對象集合,然后通過 Watch 接口來獲取增量的對象,然后更新本地緩存

1. k8s informer 概述

我們都知道可以使用 k8s 的 Clientset 來獲取所有的原生資源對象,那么怎么能持續的獲取集群的所有資源對象,或監聽集群的資源對象數據的變化呢?這里不需要輪詢去不斷執行 List 操作,而是調用 Watch 接口,即可監聽資源對象的變化,當資源對象發生變化,客戶端即可通過 Watch 接口收到資源對象的變化。

Watch 接口雖然可以直接使用,但一般情況下很少直接使用,因為往往由于集群中的資源較多,我們需要自己在客戶端去維護一套緩存,而這個維護成本比較大。

也是因為如此,client-go 提供了自己的實現機制,Informers 應運而生。informers 實現了持續獲取集群的所有資源對象、監聽集群的資源對象變化功能,并在本地維護了全量資源對象的內存緩存,以減少對 apiserver、對 etcd 的請求壓力。Informers 在啟動的時候會首先在客戶端調用 List 接口來獲取全量的對象集合,然后通過 Watch 接口來獲取增量的對象,然后更新本地緩存

此外 informers 也有很強的健壯性,當長期運行的 watch 連接中斷時,informers 會嘗試拉起一個新的 watch 請求來恢復連接,在不丟失任何事件的情況下恢復事件流。另外,informers 還可以配置一個重新同步的周期參數,每間隔該周期,informers 就會重新 List 全量數據

在 informers 的使用上,通常每個 GroupVersionResource(GVR)只實例化一個 informers,但有時候我們在一個應用中往往會在多個地方對同一種資源對象都有 informer 的需求,所以就有了共享 informer,即 SharedInformerFactory。所以可以通過使用 SharedInformerFactory 來實例化 informers,這樣本地內存緩存就只有一份,通知機制也只有一套,大大提高了效率,減少了資源浪費。

1.1 k8s informer 架構

在這里插入圖片描述

1.2 k8s informer 包含部件

k8s client-go informer 主要包括以下部件:

  • Reflector:Reflector 從 kube-apiserver 中 list&watch 資源對象,然后調用 DeltaFIFO 的 Add/Update/Delete/Replace 方法將資源對象及其變化包裝成 Delta 并將其丟到 DeltaFIFO 中;
  • DeltaFIFO:DeltaFIFO 中存儲著一個 map 和一個 queue,即map[object key]Deltas 以及 object key 的 queue,Deltas 為 Delta 的切片類型,Delta 裝有對象及對象的變化類型(Added/Updated/Deleted/Sync) ,Reflector 負責 DeltaFIFO 的輸入,Controller 負責處理 DeltaFIFO 的輸出;
  • Controller:Controller 從 DeltaFIFO 的 queue 中 pop 一個 object key 出來,并獲取其關聯的 Deltas 出來進行處理,遍歷 Deltas,根據對象的變化更新 Indexer 中的本地內存緩存,并通知 Processor,相關對象有變化事件發生;
  • Processor:Processor 根據對象的變化事件類型,調用相應的 ResourceEventHandler 來處理對象的變化;
  • Indexer:Indexer 中有 informer 維護的指定資源對象的相對于 etcd 數據的一份本地內存緩存,可通過該緩存獲取資源對象,以減少對 apiserver、對 etcd 的請求壓力;
  • ResourceEventHandler:用戶根據自身處理邏輯需要,注冊自定義的的 ResourceEventHandler,當對象發生變化時,將觸發調用對應類型的 ResourceEventHandler 來做處理。

根據 informer 架構,對 k8s informer 的分析將分為以下幾部分進行,本篇為概要分析:
(1)informer概要分析;
(2)informer之初始化與啟動分析;
(3)informer之Reflector分析;
(4)informer之DeltaFIFO分析;
(5)informer之Controller&Processor分析;
(6)informer之Indexer分析;


2. informer 使用示例代碼

使用大致過程如下:
(1)構建與 kube-apiserver 通信的 config 配置;
(2)初始化與 apiserver 通信的 clientset;
(3)利用 clientset 初始化 shared informer factory 以及 pod informer;
(4)注冊 informer 的自定義 ResourceEventHandler;
(5)啟動 shared informer factory,開始 informer 的 list & watch 操作;
(6)等待 informer 從 kube-apiserver 同步資源完成,即 informer 的 list 操作獲取的對象都存入到 informer 中的 indexer 本地緩存中;
(7)創建 lister,可以從 informer 中的 indexer 本地緩存中獲取對象;

func main() {// 自定義與kube-apiserver通信的config配置master := "192.168.1.10" // apiserver urlkubeconfig := "/.kube/config"config, err = clientcmd.BuildConfigFromFlags(master, kubeconfig)if err != nil {klog.Fatalf("Failed to create config: %v", err)}// 或使用k8s serviceAccount機制與kube-apiserver通信// config, err = rest.InClusterConfig()// 初始化與apiserver通信的clientsetclientset, err := kubernetes.NewForConfig(config)if err != nil {klog.Fatalf("Failed to create client: %v", err)}// 初始化shared informer factory以及pod informerfactory := informers.NewSharedInformerFactory(clientset, 30*time.Second)podInformer := factory.Core().V1().Pods()informer := podInformer.Informer()// 注冊informer的自定義ResourceEventHandlerinformer.AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc:    xxx,UpdateFunc: xxx,DeleteFunc: xxx,})// 啟動shared informer factory,開始informer的list & watch操作stopper := make(chan struct{})go factory.Start(stopper)// 等待informer從kube-apiserver同步資源完成,即informer的list操作獲取的對象都存入到informer中的indexer本地緩存中 // 或者調用factory.WaitForCacheSync(stopper)if !cache.WaitForCacheSync(stopper, informer.HasSynced) {runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync"))return}// 創建listerpodLister := podInformer.Lister()// 從informer中的indexer本地緩存中獲取對象podList, err := podLister.List(labels.Everything())if err != nil {fmt.Println(err)}}

以上只是對 K8s informer 做了簡單的介紹,以及簡單的寫了一下如何使用 informer 的示例代碼,后面將開始對 informer 的各個部件做進一步的源碼分析。

從圖中可以看出,k8s informer主要包括以下幾個部分:

2.1.Reflector

(1)Reflector 從 kube-apiserver 中 list 資源對象列表,然后調用 DeltaFIFO 的 Replace 方法將 object 包裝成 Sync/Deleted 類型的 Delta 丟進 DeltaFIFO 中;

(2)Reflector 從 kube-apiserver 中 watch 資源對象的變化,然后調用 DeltaFIFO 的 Add/Update/Delete 方法將 object 包裝成 Added/Updated/Deleted 類型的 Delta 丟到 DeltaFIFO 中;

2.2.DeltaFIFO

DeltaFIFO 中存儲著一個 map 和一個 queue;

(1)其中 queue 可以看成是一個先進先出隊列,一個 object 進入 DeltaFIFO 中,會判斷 queue 中是否已經存在該 object key,不存在則添加到隊尾;

(2)map 即 map[object key]Deltas,是 object key 和 Deltas 的映射,Deltas 是 Delta 的切片類型,Delta 中存儲著 DeltaType 和 object;另外,Deltas 最末尾的兩個 Deleted 類型的 Delta 會被去重;

DeltaType 有4種,分別是 Added、Updated、Deleted、Sync

2.3.Controller

Controller 從 DeltaFIFO 的 queue 中 pop 一個 object key 出來,并從 DeltaFIFO 的 map 中獲取其對應的 Deltas 出來進行處理,遍歷 Deltas,根據 object 的變化類型更新 Indexer 本地緩存,并通知 Processor 相關對象有變化事件發生:

(1)如果 DeltaType 是 Deleted,則調用 Indexer 的 Delete 方法,將 Indexer 本地緩存中的 object 刪除,并構造 deleteNotification struct,通知 Processor 做處理;

(2)如果 DeltaType 是 Added/Updated/Sync,調用 Indexer 的 Get 方法從 Indexer 本地緩存中獲取該對象,存在則調用 Indexer 的 Update 方法來更新 Indexer 緩存中的該對象,隨后構造 updateNotification struct,通知 Processor 做處理;如果 Indexer 中不存在該對象,則調用 Indexer 的 Add 方法將該對象存入本地緩存中,并構造 addNotification struct,通知 Processor 做處理;

2.4.Processor

Processor 根據 Controller 的通知,即根據對象的變化事件類型(addNotification、updateNotification、deleteNotification),調用相應的 ResourceEventHandler(addFunc、updateFunc、deleteFunc)來處理對象的變化。

2.5.Indexer

Indexer 中有 informer 維護的指定資源對象的相對于 etcd 數據的一份本地內存緩存,可通過該緩存獲取資源對象,以減少對 apiserver、對etcd 的請求壓力。

informer 所維護的緩存依賴于 threadSafeMap 結構體中的 items 屬性,其本質上是一個用 map 構建的鍵值對,資源對象都存在 items 這個 map 中,key 為資源對象的 namespace/name 組成,value 為資源對象本身,這些構成了 informer 的本地緩存。

Indexer 除了維護了一份本地內存緩存外,還有一個很重要的功能,便是索引功能了。索引的目的就是為了快速查找,比如我們需要查找某個 node 節點上的所有 pod、查找某個命名空間下的所有 pod 等,利用到索引,可以實現快速查找。關于索引功能,則依賴于 threadSafeMap 結構體中的 indexers 與 indices 屬性。

2.6.ResourceEventHandler

用戶根據自身處理邏輯需要,注冊自定義的的 ResourceEventHandler,當對象發生變化時,將觸發調用對應類型的 ResourceEventHandler 來做處理。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714086.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++中boost庫的安裝及使用(Windows)

Boost庫的安裝及使用 引言使用現有的boost庫安裝及使用引言 C++開發中經常會用到boost庫,本文記錄一下Windows上boost在visual studio2019上的使用。 Boost庫是一個跨平臺的C++庫集合,旨在為C++開發者提供一系列高質量的通用功能。不同的Visual Studio(VS)版本并不要求安…

日常科研中經常使用的命令

Linux目錄樹狀結構 1. Windows是磁盤分區,Linux不區分盤符,所有文件都在根目錄斜線下面; 2. 根目錄顯示不同,Linux是一個斜線,而windows是盤符,然后冒號; 3. 分割目錄Linux用斜線&#xff0c…

React編寫組件時,如何省略.tsx后綴

省略.tsx后綴 當tsconfig.json配置了,需要重啟后才會生效 {"compilerOptions": {"allowJs": true,"jsx": "react-jsx",} }當進行以上配置后,導入組件時添加后綴,Eslint報錯如下: An im…

【算法集訓】基礎算法:基礎排序 - 冒泡排序

一、基本理解 貼上圖解,更容易理解代碼:https://visualgo.net/zh/sorting 冒泡排序(Bubble Sort)又稱為泡式排序,是一種簡單的排序算法。 核心思想: 它重復地走訪過要排序的數列,一次比較兩個元素,如果它…

性能比較:in和exists

當在Hive SQL中使用NOT IN和NOT EXISTS時,性能差異主要取決于底層數據的組織方式、數據量大小、索引的使用情況以及具體查詢的復雜程度。下面是對這兩種方法的性能分析: 1. NOT IN:- 工作原理:NOT IN子查詢會逐個比較主查詢中的值…

化肥工業5G智能制造工廠數字孿生可視化平臺,推進化肥行業數字化轉型

化肥工業5G智能制造工廠數字孿生可視化平臺,推進化肥行業數字化轉型。隨著科技的不斷發展,數字化轉型已經成為各行各業發展的必然趨勢。在化肥工業領域,5G智能制造工廠數字孿生可視化平臺的應用正在逐漸普及,為行業數字化轉型提供…

Java 循環結構 - while ,do…while 及 for,

目錄 Java中有三種主要的循環結構: while 循環 實例 do…while 循環 實例 for循環 實例 三種循環之間的區別 增強 for 循環 實例 break 關鍵字 語法 實例 continue 關鍵字 語法 實例 順序結構的程序語句只能被執行一次。 如果您想要同樣的操作執行…

租用云服務器租時要注意的問題有哪些?

隨著云計算的不斷發展,對云計算服務器的需求也越來越大。 那么,我們應該如何以正確的態度和方法來選擇云服務器呢? 租用云服務器需要注意哪些問題? 1.了解您需要的云服務類型 了解您的云計算需求將使您了解您正在尋求的服務類型…

web運行時安全

1.輸入驗證 對傳遞的數據的格式、長度、類型(前端和后端都要)進行校驗。 對黑白名單校驗:比如前端傳遞了一個用戶名,可以搜索該用戶是否在白名單或者黑名單列表。 針對黑名單校驗,比如: // 手機號驗證…

讓兩個電腦通信的方法(TCP連接,UDP連接,C/S架構)

目錄 TCP-面向連接UDP-面向無連接C/S架構服務器和客戶端的工作過程C/S架構例子 讓兩個電腦通信的方法是 在C/S的基礎上,采用TCP和UDP的方式連接 TCP-面向連接 UDP-面向無連接 C/S架構 服務器和客戶端的工作過程 C/S架構例子 服務器與客戶端通信的過程類似公司與客戶…

微信小程序云開發教程——墨刀原型工具入門(添加交互事件)

引言 作為一個小白,小北要怎么在短時間內快速學會微信小程序原型設計? “時間緊,任務重”,這意味著學習時必須把握微信小程序原型設計中的重點、難點,而非面面俱到。 要在短時間內理解、掌握一個工具的使用&#xf…

殿堂級Flink源碼極精課程預售

一、為什么我們要讀源碼? 1、讓個人技術快速成長: 優秀的開源框架,底層的源碼設計思想也非常優秀,同時還有含有大量的設計模式和并發編程技術,優秀的解決方案,熟讀源碼對猿們技術提升有很大幫助 2、新技術學習能力: Java開源碼框架的源碼熟讀后,若出現…

第一篇:參考資料地址

javaGuide JavaGuide(Java學習&面試指南) | JavaGuide 清華學生總結的 小林coding labuladong labuladong 的算法筆記 | labuladong 的算法筆記 【華仔說技術】kafka的系列文章 https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg3MTcxMDgxNA…

【Datawhale組隊學習:Sora原理與技術實戰】Sora技術原理

Sora能力邊界探索 最大支持60秒高清視頻生成,以及基于已有短視頻的前后擴展,同時保持人物/場景的高度一致性如奶茶般絲滑過渡的視頻融合能力同一場景的多角度/鏡頭的生成能力具有動態攝像機運動的視頻。隨著攝像機的移動和旋轉,人和其 他場景…

x-pack的破解方式和免費jar包!!可直接用!!

原理介紹 我們平時為es安裝x-pack組件,用elasticsearch-plugin install x-pack ,安裝成功后。 1.cd $es目錄/pulgins/x-pack 里面有一個x-pack-5.6.2.jar ,將jar包反編譯,然后將里面的licence的程序改下。再編譯成jar包。 2…

通過筆記本橋接打印機組成網絡打印機其它電腦與之相連各種問題匯總

根據描述需要一臺低配閑置筆記本(有無線網卡),一臺普通臺式打印機(不帶WIFI)就可以組成網絡打印機,能省1000塊不? 1. 讓筆記本安裝驅動使其可以打印。 2. 讓筆記本上的打印機共享,…

解決 MacOS Sonoma 14 系統下修改用戶名無法進入系統的歷史Bug

蘋果系統祖傳Bug概述 在MacOS中如果在系統偏好設置/用戶和群組中嘗試修改用戶名或用戶ID,當且僅當只有一個管理員賬號的時候重啟,就可能面臨到無法進入操作系統,即使出現了登錄框,但是一直是 loading狀態在這個期間,你…

javaScript 深淺拷貝

javaScript深淺拷貝 淺拷貝 自己創建一個新的對象,來接受你要重新復制或引用的對象值。如果對象屬性是基本的數據類型,復制的就是基本類型的值給新對象,但如果屬性是引用數據類型,復制的就是內存中的地址,如果其中一個…

Python 編程中的迭代器、生成器和裝飾器探究【第110篇—迭代器】

Python 編程中的迭代器、生成器和裝飾器探究 在Python編程中,迭代器(Iterators)、生成器(Generators)和裝飾器(Decorators)是三個強大的概念,它們為代碼的可讀性、效率和靈活性提供…

PaddleOCR的部署教程(實操環境安裝、數據集制作、實際應用案例)

文章目錄 前言 PaddleOCR簡介 一、PaddleOCR環境搭建 因為我之前安裝過cuda和cudnn,查看cuda的版本根據你版本安裝合適的paddlepaddle版本(之前沒有安裝過cuda的可以看我這篇文章Ubuntu20.04配置深度學習環境yolov5最簡流程) 1.創建一個…