带你读《云原生应用开发 Operator原理与实践》第三章 Kubebuilder 原理3.2 Kubebuilder 模块分析(四)

3.2.3         Client初始化

实现 Controller 时,不可避免地需要对某些资源类型进行创建、删除、更新和查询,这些操作就是通过Client实现的,查询功能实际查询的是本地的 Cache,写操作是直接访问 APIServer。Client是进行初始化的过程见代码清单 3-11。

//ctrl.NewManager⽤于创建 Manager,在创建Manager的过程中会初始化相应的Client

mgr,err:=ctrl.NewManager(ctrl.GetConfigOrDie(),ctrl.Options{

Scheme:                scheme,

MetricsBindAddress:                       metricsAddr,Port:         9443,

HealthProbeBindAddress:probeAddr,LeaderElection:       enableLeaderElection,LeaderElectionID:       "8bf23ea1.my.domain",


 

})

 

//...

 

iferr=(&controllers.GuestbookReconciler{

//将 Manager的 Client传给Controller

//并且调⽤SetupWithManager⽅法传⼊Manager进⾏ Controller的初始化

Client:mgr.GetClient(),

Log:ctrl.Log.WithName("controllers").WithName("Guestbook"),Scheme:mgr.GetScheme(),

}).SetupWithManager(mgr);err!=nil{

setupLog.Error(err,"unabletocreatecontroller","controller","Guestbook")

os.Exit(1)


}

 

在 Manager初始化过程中创建 Client,见代码清单 3-12。

funcNew(config*rest.Config,optionsOptions)(Manager,error){

//...

//如果⽤户没有指定⾃⼰⽤的Client,那么在 setOptionsDefaults函数中会创建

//默认的Client

options=setOptionsDefaults(options)

 

//...

//创建Cache⽤于Client读操作

cache,err:=options.NewCache(config,cache.Options{Scheme:options.Scheme,

Mapper:mapper,Resync:options.SyncPeriod,Namespace:options.Namespace})

 

//...

clientOptions:=client.Options{Scheme:options.Scheme,Mapper:mapper}

 

apiReader,err:=client.New(config,clientOptions)

iferr!=nil{

returnnil,err

}

 

//初始化⽤于写操作的Client

writeObj,err:=options.ClientBuilder.

WithUncached(options.ClientDisableCacheFor...).Build(cache,config,clientOptions)

iferr!=nil{


 

 

returnnil,err

}

 

//dryRun模式

ifoptions.DryRunClient{

writeObj=client.NewDryRunClient(writeObj)

}

}

 

初始化默认的 Client,见代码清单 3-13。


funcsetOptionsDefaults(optionsOptions)Options{

//...

//如果⽤户没有指定Client,那么创建默认的 Client

ifoptions.ClientBuilder==nil{options.ClientBuilder=NewClientBuilder()

}

//如果⽤户没有指定Cache,那么创建默认的 Cache

ifoptions.NewCache==nil{options.NewCache=cache.New

}

//...

}

 

Manager 启动的入口函数一般在 main() 函数中,具体见代码清单 3-14。

setupLog.Info("startingmanager")

if err:=mgr.Start(ctrl.SetupSignalHandler());err!=nil{setupLog.Error(err,"problemrunningmanager")os.Exit(1)

}

 

MGR的类型是一个Interface,底层实际上调用的是 controllerManager的Start方法。Start方法的主要逻辑就是启动 Cache、Controller,将整个事件流运转起来。

代码清单 3-15展示了启动逻辑。

func(cm*controllerManager)Start(ctxcontext.Context)(errerror){


 

...

//根据是否需要选举来选择启动⽅式

gocm.startNonLeaderElectionRunnables()gofunc(){

ifcm.resourceLock!=nil{

err:=cm.startLeaderElection()iferr!=nil{

cm.errChan<-err

}

}else{

close(cm.elected)

gocm.startLeaderElectionRunnables()

}

}()

..


}

 

选举和非选举方式的启动逻辑类似,都是先初始化Cache,再启动 Controller,见代码清单 3-16。

func(cm*controllerManager)startNonLeaderElectionRunnables(){cm.mu.Lock()

defercm.mu.Unlock()

 

//启动Cache

cm.waitForCache(cm.internalCtx)

 

//启动Controller

for_,c:=rangecm.nonLeaderElectionRunnables{cm.startRunnable(c)

}

}

上一篇:带你读《云原生应用开发 Operator原理与实践》第三章 Kubebuilder 原理3.3 Controller-runtime 模块分析(二)


下一篇:带你读《云原生应用开发 Operator原理与实践》第三章 Kubebuilder 原理3.2 Kubebuilder 模块分析(三)