圖解kubernetes中informer機制基礎設計原理

kubernetes中的informer機制可能是實現集羣控制模塊的最核心的設計之一了,本文從informer如何獲取數據開始,然後介紹了爲了減少apiserver而設計的緩存、索引、無界隊列、共享informer等機制歡迎一起交流學習

1. informer的本質

1.1 設計目標

image.png 之前說到kubernetes裏面的apiserver的只負責數據的CRUD接口實現,並不負責業務邏輯的處理,所以k8s中就通過外掛controller通過對應資源的控制器來負責事件的處理,controller如何感知事件呢?答案就是informer

1.2 基於chunk的消息通知

image.png watcher的設計在之前的文章中已經介紹,服務端是如何將watcher感知到的事件發送給informer呢?我們提到過apiserver本質上就是一個http的rest接口實現,watch機制則也是基於http協議,不過不同於一般的get其通過chunk機制,來實現消息的通知

1.3 reflector

image.png 服務端通過chunk進行數據的發送,在客戶端同樣的需要根據對應的chunk來進行數據的解包,同時還要維護這個長鏈接

2. 設計優化

爲了緩解apiserver的壓力,informer自身做了很多相關的優化工作,其本質上爲兩個大的方面:優先使用本地緩存和複用連接,每個人看到的可能都不太一樣,本文是基於源碼的個人理解,歡迎交流

2.1 本地緩存

image.png 通過listwatch接口主要分爲兩部分,list接口我們可以獲取到對應資源當前版本的全量資源,watch接口可以獲取到後續變更的資源,通過全量加增量的數據,就構成了在client端一份完整的數據(基於當前版本的),那後續如果要獲取對應的數據,就直接可以通過本地的緩存來進行獲取,爲此informer抽象了cache這個組件,並且實現了store接口,如果後續要獲取資源,則就可以通過本地的緩存來進行獲取

2.2 本地索引

image.png 上面將資源緩存在本地的內存中,那如果我們要進行數據查詢,快速檢索數據,這個時候就需要用到informer裏面的indexer, 我們可以註冊不同的索引函數,在添加對象的時候,會通過indexer爲其建立對應的索引,這樣後續我們就可以通過key來檢索獲取元數據

2.3 無界隊列

image.png 爲了協調數據生產與消費的不一致狀態,在cleint-go中通過實現了一個無界隊列來進行數據的緩衝,當reflector獲取到數據之後,只需要將數據寫入到無界隊列中,則就可以繼續watch後續事件,從而減少阻塞時間, 下面的事件去重也是在該隊列中實現的

2.4 事件去重

image.png 事件去重是指的,在上面的無界隊列中,如果針對某個資源的事件重複被觸發,則就只會保留相同事件最後一個事件作爲後續處理

到此對於事件接收和數據緩存相關優化就結束了,接下就是處理層的優化

2.5 複用連接

image.png 在k8s中一些控制器可能會關注多種資源,比如Deployment可能會關注Pod和replicaset,replicaSet可能還會關注Pod,爲了避免每個控制器都獨立的去與apiserver建立鏈接,k8s中抽象了sharedInformer的概念,即共享的informer, 針對同一資源只建立一個鏈接

2.6 基於觀察者模式的註冊

image.png 因爲彼此共用informer,但是每個組件的處理邏輯可能各部相同,在informer中通過觀察者模式,各個組件可以註冊一個EventHandler來實現業務邏輯的注入

2.7 無界隊列

前面提到過一個無界隊列,而此處是針對單個eventHandler的無界隊列,其實主要是爲了協調各個組件的處理速度的不一致

3. 設計總結

image.png 本文從informer如何獲取數據開始,然後介紹了爲了減少apiserver而設計的緩存、索引、無界隊列、共享informer等機制, 拋個小問題, 基於listwatch和informer機制會不會丟事件,如果丟事件會不會影響最終的結果,歡迎加羣討論

微信號:baxiaoshi2020 關注公告號閱讀更多源碼分析文章 圖解源碼 本文由博客一文多發平臺 OpenWrite 發佈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章