
k8s-list&watch源碼解析.jpg
這里以Deployment的控制器的list&watch為例:
- 1、在controller-manager的Run函數(shù)部分調(diào)用了InformerFactory.Start的方法,Start方法初始化各種類(lèi)型的informer,并且每個(gè)類(lèi)型起了個(gè)informer.Run的goroutine。需要注意的是controller-manager中是先啟動(dòng)每個(gè)資源對(duì)象的controller然后在統(tǒng)一啟動(dòng)InformerFactory;
- 2、簡(jiǎn)單的說(shuō)就是在初始化DeploymentController對(duì)象的時(shí)候完成了deployment的sharedIndexformer(本地緩存結(jié)構(gòu)體)的初始化初始化同時(shí)也完成了將deployment資源的增、刪、改的事件處理的函數(shù)(也就是上面提到的Resource Event Handlers資源事件回調(diào)函數(shù))注冊(cè)到sharedIndexformer當(dāng)中,處理deployment資源增、刪、改的函數(shù)主要是用于將變更的deployment資源實(shí)例對(duì)象存入DeploymentController對(duì)象中的worker queue,然后DeploymentController從worker queue隊(duì)列中拿出變更的實(shí)例資源進(jìn)行業(yè)務(wù)上的處理;
- 3、通過(guò)協(xié)程的方式啟動(dòng)DeploymentController的控制器,該控制器啟動(dòng)的時(shí)候會(huì)等待本地indexer緩存完成deployment資源實(shí)例的數(shù)據(jù)從api-server同步到本地;(到這里上面的步驟主要是完成DepoymentController對(duì)象的初始化、該對(duì)象的底層存儲(chǔ)結(jié)構(gòu)初始化以及該對(duì)象的增、刪、改的回調(diào)函數(shù)的注冊(cè))
- 4、然后啟動(dòng)InformerFactory.Start(會(huì)啟動(dòng)每個(gè)資源對(duì)象的shareIndexformer),對(duì)應(yīng)資源對(duì)象的(如:這里的deployment資源對(duì)象的)sharedIndexformer會(huì)初始化DeltaFIFO實(shí)例對(duì)象(即queue隊(duì)列),同時(shí)將DeltaFIFO、list&watch、Process(sharedIndexformer的一個(gè)方法用于從DeltaFIFO隊(duì)列中獲取資源對(duì)象往worker queue隊(duì)列中添加的方法即上面提到的Resource Event Handlers資源事件回調(diào)函數(shù))、資源對(duì)象種類(lèi)傳入Config初始化controller。DeltaFIFO的隊(duì)列來(lái)存儲(chǔ)對(duì)象變化的數(shù)據(jù)。然后調(diào)用processor.Run和controller.Run函數(shù);
- 5、啟動(dòng)controller后會(huì)根據(jù)DeltaFIFO對(duì)象、list&watcher、資源種類(lèi)等參數(shù)去初始化Reflector對(duì)象;
- 6、然后啟動(dòng)Reflector,Reflector的主要作用是watch指定的k8s資源,并將變化同步到本地是store中。Reflector以resyncPeriod為周期定期執(zhí)行l(wèi)ist的操作(當(dāng)非零的時(shí)候,會(huì)按該周期執(zhí)行將本地indexer緩存中的數(shù)據(jù)同步到deltafifo里面重新出發(fā)每個(gè)資源對(duì)象的更新,設(shè)置為0時(shí),Reflector不會(huì)自動(dòng)定期重新同步資源。相反,它只會(huì)在啟動(dòng)時(shí)獲取一次資源列表,并在隨后的事件中依賴(lài)于事件通知來(lái)更新本地indexer緩存),這樣就可以使用Reflector來(lái)定期處理所有的對(duì)象,也可以逐步處理變化的對(duì)象;
- 7、Reflector接著執(zhí)行ListAndWatch函數(shù),ListAndWatch第一次會(huì)列出所有的對(duì)象將這些對(duì)象同步到本地緩存indexer中,并獲取資源對(duì)象的版本號(hào),然后watch資源對(duì)象的版本號(hào)來(lái)查看是否有被變更。首先會(huì)將資源版本號(hào)設(shè)置為0,list()可能會(huì)導(dǎo)致本地的緩存相對(duì)于etcd里面的內(nèi)容存在延遲,Reflector會(huì)通過(guò)watch的方法將延遲的部分補(bǔ)充上(watch的周期默認(rèn)為1秒,超時(shí)時(shí)間默認(rèn)5分鐘),使得本地的緩存數(shù)據(jù)與etcd的數(shù)據(jù)保持一致;
- 8、最后controller.Run函數(shù)還會(huì)調(diào)用processLoop函數(shù)(即deltafifo的Pop方法將資源對(duì)象從deltaFIFO隊(duì)列中取出),processLoop通過(guò)調(diào)用HandleDeltas,再調(diào)用distribute完成對(duì)資源對(duì)象的封裝成為notification資源類(lèi)型發(fā)往processorListener的管道中,processorListener.add最終將不同變更的類(lèi)型對(duì)象加入processorListener的channel中,供processorListener.Run使用。processLoop死循環(huán)的從DeltaFIFO隊(duì)列中Pop即取出資源對(duì)象往worker queue隊(duì)列中添加,以及將資源對(duì)象同步到本地緩存indexer中;
- 9、DeploymentController的syncDeployment獲取到worker queue隊(duì)列中的資源實(shí)例進(jìn)行業(yè)務(wù)上的處理;
注意1:
Reflector中,list操作時(shí)將 resourceVersion 設(shè)置了為“0”,此時(shí)返回的數(shù)據(jù)是apiserver cache中的,并非直接讀取 etcd 而來(lái),而apiserver cache中的數(shù)據(jù)可能會(huì)因網(wǎng)絡(luò)或其他原因?qū)е屡cetcd中的數(shù)據(jù)不同。
list操作時(shí),resourceVersion 有三種設(shè)置方法:
(1)第一種:不設(shè)置,此時(shí)會(huì)從直接從etcd中讀取,此時(shí)數(shù)據(jù)是最新的;
(2)第二種:設(shè)置為“0”,此時(shí)從apiserver cache中獲取;
(3)第三種:設(shè)置為指定的resourceVersion,獲取resourceVersion大于指定版本的所有資源對(duì)象。
轉(zhuǎn)載請(qǐng)標(biāo)注出處!