# kubebuilder(2)-原理

導(dǎo)讀:上一篇blog主要是簡單介紹了一下kubebuilder的使用,這里再分析一下kubebuilder的代碼邏輯。

1.kubebuilder的基礎(chǔ):controller

首先介紹一下k8s的一個(gè)controller的邏輯,下圖主要參考client-go給的一個(gè)workQueue的例子

controller

這里我把代碼分為通用的Common partSpecial Part。前者是client-go的基本流程,而后者部分是controller自身邏輯部分。具體過程包含8個(gè)步驟:

1.Reflector通過ListAndWatch方法去監(jiān)聽指定的Object;

func (r *Reflector) Run(stopCh <-chan struct{}) {
    klog.V(3).Infof("Starting reflector %v (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
    wait.Until(func() {
        if err := r.ListAndWatch(stopCh); err != nil {
            utilruntime.HandleError(err)
        }
    }, r.period, stopCh)
}

2.Reflector會(huì)將所監(jiān)聽到的event,包括對(duì)object的Add,Update,Delete的操作push到DeltaFIFO這個(gè)queue中;
3.Informer首先會(huì)解析event中的action和object;
4.Informer將解析的object更新到local store,也就是本地cache中的數(shù)據(jù)更新;
5.然后Informer會(huì)執(zhí)行Controller在初始化Infromer時(shí)注冊(cè)的ResourceEventHandler(這些callback是可以自己修改的);
6.ResourceEventHandler中注冊(cè)的callback會(huì)將對(duì)應(yīng)變化的object的key存入其初始化的一個(gè)workQueue;
7.最終controller會(huì)循環(huán)進(jìn)行reconcile,就是從workQueue不停地pop key,然后去local store中取到對(duì)應(yīng)的object,然后進(jìn)行處理,最終多數(shù)情況會(huì)再通過client去更新這個(gè)object。

上面這個(gè)具體過程,我看網(wǎng)上大佬們也都分析過很多次了,但是根據(jù)我的經(jīng)驗(yàn)?zāi)兀€是需要去看一遍代碼心里才有底。以后出問題或者二次開發(fā)的時(shí)候,都是需要知道重要的結(jié)構(gòu)體和API的。

2.kubebuilder的封裝

想說明一下kubebuilder實(shí)際上是提供了對(duì)client-go進(jìn)行封裝的library(準(zhǔn)確來說是runtime-controller),更加便利我們來開發(fā)k8s的operator。

我上面提到的workQueue的例子已經(jīng)實(shí)現(xiàn)了一個(gè)controller的邏輯。而kubebuilder還幫我們做了以下的額外工作:

  1. kubebuilder引入了manager這個(gè)概念,一個(gè)manager可以管理多個(gè)controller,而這些controller會(huì)共享manager的client;
  2. 如果manager掛掉或者停止了,所有的controller也會(huì)隨之停止;
  3. kubebuilder使用一個(gè)map[GroupVersionKind]informer來管理這些controller,所以每個(gè)controller還是擁有其獨(dú)立的workQueue,deltaFIFO,并且kubebuilder也已經(jīng)幫我們實(shí)現(xiàn)了這部分代碼;
  4. 我們主要需要做的開發(fā),就是寫Reconcile中的邏輯。

1.Manager通過map[GroupVersionKind]informer啟動(dòng)所有controller:

func (ip *specificInformersMap) Start(stop <-chan struct{}) {
...
        for _, informer := range ip.informersByGVK {
            go informer.Informer.Run(stop)
        }
...
    <-stop
}

2.Controller處理event的邏輯都在https://github.com/kubernetes-sigs/controller-runtime/blob/master/pkg/internal/controller/controller.go這個(gè)文件里面,其實(shí)它就是實(shí)現(xiàn)了workqueue這個(gè)例子的大部分代碼,推薦先看懂這個(gè)例子再來分析這個(gè)文件。

3.小結(jié)

寫這篇blog本來想講一下kubebuilder的代碼流程的,但是發(fā)現(xiàn)要理解kubebuilder必須先理解client-go,基本上client-go代碼熟悉之后再來分析kubebuilder就easy了...我自己太笨了,花了很多時(shí)間去啃client-go,假期余額緊張,所以關(guān)于kubebuilder自身的分析就沒寫太多了,有時(shí)間再補(bǔ)充吧。網(wǎng)上有一篇關(guān)于kubebuilder的分析,有興趣的同學(xué)可以參考一下吧,但是我覺得做二次開發(fā)一定要看自己親自看和分析一遍。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容