kubernetes1.9原始碼閱讀 List-Watch及Reflec

lee_lgw發表於2021-09-09

List-Watch是kubernetes的核心機制。元件kubelet、kube-controller-manager、kube-scheduler需要監控各種資源(pod、service等)的變化,當這些物件發生變化時(add、delete、update),kube-apiserver會主動通知這些元件。這個過程類似一個釋出-訂閱系統。本文章將從程式碼角度探究一下list-watch的實現方式。

原始碼分析是kubernetes tag v1.9.0

第一部分:kube-apiserver對etcd的List-watch機制

構建PodStorage

pkg/registry/core/pod/storage.go
NewStorage方法

1. kube-apiserver針對每一類資源(pod、service、endpoint、replication controller、depolyments)都會構建Storage物件,如:PodStorage;
2. PodStorage.Pod.Store封裝了對etcd的操作;
3. store.CompleteWithOptions會呼叫etcdOptions.GetRESTOptions,此方法將
呼叫generic.UndecoratedStorage建立無cache的Store;
或者呼叫genericregistry.StorageWithCacher建立帶Cache的Store;

圖片描述

StorageWithCacher

staging/src/k8s.io/apiserver/pkg/registry/generic/registry/storage_factory.go 
StorageWithCacher方法

1. 呼叫NewRawStorage,它將構建etcdHelper,etcdHelper實現Storage.Interface介面,封裝了對etcd的操作;
2. 呼叫NewCacherFromConfig,將建立Cacher物件;

圖片描述

建立Cacher

staging/src/k8s.io/apiserver/pkg/storage/cacher.go
NewCacherFromConfig方法

1. 首先,建立watchCache物件和cacheListerWatcher物件,cacheListWatcher物件是ListerWatcher介面實現,實現了List()和Watch()方法;
2. 構建Cacher物件,主要的資料成員:watchCache、reflector、watchers及incoming channel;
(1) watchCache是一個cache,用來儲存apiserver從etcd那裡watch到的物件;
(2) watchers是一個map,map的值型別為cacheWatcher,當kubelet、kube-scheduler需要watch某類資源時,他們會向kube-apiserver發起watch請求,kube-apiserver就會生成一個cacheWatcher,cacheWatcher負責將watch的資源透過http從apiserver傳遞到kubelet、kube-scheduler;
(3) Reflector物件,主要資料成員:ListerWatcher,ListerWatcher是介面物件,包括方法List()和Watch();listerWatcher包裝了Storage,主要是將watch到的物件存到watchCache中;
(4) incoming channel接收watchCacheEvent;
3. 協程呼叫cacher.dispatchEvents,watchCache將incoming channel接收watchCacheEvent新增到watchers的inputChan中;
4. 協程呼叫cacher.startCaching;

圖片描述

StartCaching

staging/src/k8s.io/client-go/tools/cache/reflector.go
ListAndWatch方法

1 執行cacheListerWatcher的List方法和Watch方法;
2 呼叫reflector的watchHandler方法;

cacheListWatcher.List/cacheListWatcher.Watch

staging/src/k8s.io/apiserver/pkg/storage/cacher.go
List方法和Watch方法

1 List方法將呼叫storage.List方法,這裡是etcdHelper.List方法;
2 Watch方法將呼叫storage.watch方法,這裡是etcdHelper.WatchList方法;

圖片描述

etcdHelper.List/etcdHelper.Watch

staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_helper.go
List方法/WatchList方法

1. etcdHelper物件是Storage介面物件的實現;
2. etcdHelper的List方法:
(1) 獲取etcd的物件(包括resourceVersion資訊);
3. etcdHelper的WatchList方法:
(1) 建立etcdWatcher;
(2) etcdWatcher物件,實現了Watch介面;
(3) etcdWatcher物件,主要的資料成員是etcdIncoming channel和outgoing channel;
(4) 協程執行etcdWatcher.translate;
(5) 最後,協程執行etcdWatcher.etcdWatch;

圖片描述

etcdWatcher.etcdWatch

staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher.go
etcdWatch方法

1. 如果resourceVersion==0, 執行etcdGetInitialWatchState(),獲取所有的pods,並將結果輸入到etcdIncoming channel;
2. 之後,不停的呼叫watcher.Next(),並將結果輸入到etcdIncoming channel;

圖片描述

etcdWatcher.translate

staging/src/k8s.io/apiserver/pkg/storage/etcd/etcd_watcher.go
translate方法

1. 讀取etcdIncoming channel資訊;
2. 呼叫etcdWatcher.sendResult進行轉化;
3. 傳送到outgoing channel;

圖片描述

reflector.watchHandler

staging/src/k8s.io/client-go/tools/cache/reflector.go
watchHandler方法

1. 讀取outgoing channel資訊,操作watchCache;

圖片描述

操作watchCache

staging/src/k8s.io/apiserver/pkg/storage/watch_cache.go
Add方法
Delete方法
Get方法
Update方法

圖片描述

處理事件watchCache.processEvent

staging/src/k8s.io/apiserver/pkg/storage/watch_cache.go
processEvent方法

1. 建立watchCacheEvent
2. 呼叫watchCache.updateCache,更新watchCache;

圖片描述

到此分析完kube-apiserver對etcd的watch機制,除此之外,kube-apiserver會向其他元件提供watch介面,下面將分析kube-apiserver的watch API。

第二部分:kube-apiserver的watch restful API

kube-apiserver提供watch restful API給其他元件(kubelet、kube-controller-manager、kube-scheduler、kube-proxy)。watch restful API的處理流程和PUT、DELETE、GET等REST API處理流程類似。

registerResourceHandlers

staging/src/k8s.io/apiserver/pkg/endpoints/installer.go
registerResourceHandlers方法

圖片描述

ListResource

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go
ListResource方法

1.呼叫rw.watch方法,這裡將會呼叫Store.watch;
2.呼叫serveWatch方法;

圖片描述

Store.watch

staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go
watch方法和watchPredicate方法

1. 呼叫Storage.Watch方法和Storage.WatchList方法,這裡將呼叫Cacher.watch方法和Cacher.WatchList方法

圖片描述

Cacher.watch

staging/src/k8s.io/apiserver/pkg/storage/cacher.go
watch方法和watchList方法

1. watch方法中將呼叫newCacheWatcher;
2. newCacheWatcher方法:
(1) 生成一個watcher,並將watcher插入到cacher.watchers中;
(2) 協程呼叫cacheWatcher.process方法,此方法將會操作input channel的訊息;

圖片描述

操作input channel

staging/src/k8s.io/apiserver/pkg/storage/cacher.go
cacheWatcher.process方法

1. 讀取input channel的資訊,並呼叫sendWatchCacheEvent方法;

圖片描述

sendWatchCacheEvent

staging/src/k8s.io/apiserver/pkg/storage/cacher.go
cacheWatcher.sendWatchCacheEvent方法

1. kube-apiserver的watch會帶過濾功能;
2. 對watchCacheEvent進行Filter,傳送到cacher.result channel中;

圖片描述

serveWatch

apiserver/pkg/endpoints/handlers/rest.go
serveWatch方法

1. 對result Channel資訊進行序列化,併傳送給呼叫者;



作者:範彬2017
連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1020/viewspace-2820573/,如需轉載,請註明出處,否則將追究法律責任。

相關文章