kubernetes1.9原始碼閱讀 List-Watch及Reflec
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- kubernetes1.9原始碼閱讀 kubelet對pod資源的wat原始碼
- GVUserDefaults原始碼閱讀及使用原始碼
- 【原始碼閱讀】AndPermission原始碼閱讀原始碼
- kubernetes程式碼閱讀-apiserver之list-watch篇APIServer
- 【原始碼閱讀】Glide原始碼閱讀之with方法(一)原始碼IDE
- 【原始碼閱讀】Glide原始碼閱讀之into方法(三)原始碼IDE
- ReactorKit原始碼閱讀React原始碼
- AQS原始碼閱讀AQS原始碼
- CountDownLatch原始碼閱讀CountDownLatch原始碼
- HashMap 原始碼閱讀HashMap原始碼
- delta原始碼閱讀原始碼
- 原始碼閱讀-HashMap原始碼HashMap
- NGINX原始碼閱讀Nginx原始碼
- Mux 原始碼閱讀UX原始碼
- HashMap原始碼閱讀HashMap原始碼
- fuzz原始碼閱讀原始碼
- RunLoop 原始碼閱讀OOP原始碼
- express 原始碼閱讀Express原始碼
- muduo原始碼閱讀原始碼
- stack原始碼閱讀原始碼
- 【原始碼閱讀】Glide原始碼閱讀之load方法(二)原始碼IDE
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- JDK原始碼閱讀:Object類閱讀筆記JDK原始碼Object筆記
- Laravel 原始碼閱讀 - QueueLaravel原始碼
- Vollery原始碼閱讀(—)原始碼
- 使用OpenGrok閱讀原始碼原始碼
- 如何閱讀Java原始碼?Java原始碼
- buffer 原始碼包閱讀原始碼
- 原始碼閱讀技巧篇原始碼
- 如何閱讀框架原始碼框架原始碼
- 再談原始碼閱讀原始碼
- Laravel 原始碼閱讀 - EloquentLaravel原始碼
- 如何閱讀jdk原始碼?JDK原始碼
- express 原始碼閱讀(全)Express原始碼
- Vuex原始碼閱讀分析Vue原始碼
- React原始碼閱讀:setStateReact原始碼
- ArrayList原始碼閱讀(增)原始碼
- ThreadLocal原始碼閱讀thread原始碼