K8S源码分析Controller Manager - 4、Controller实现的一个例子-ReplicaSetController

Controller的实现基本上都是通过SharedInformer的结构去监听etcd上某种资源的变更,然后再执行对应的业务逻辑。

本文以ReplicaSetController为例,介绍一个controller如何与整个manager组合在一起。

controller启动

controllers都是在NewControllerInitializers()方法中引入到manager里的:

func NewControllerInitializers() map[string]InitFunc {

   controllers := map[string]InitFunc{}

   ....

   controllers["replicaset"] = startReplicaSetController

   ....

   return controllers

}

startReplicaSetController是启动函数,如下:

func startReplicaSetController(ctx ControllerContext) (bool, error) {

   if !ctx.AvailableResources[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicasets"}] {

      return false, nil

   }

   // 获取监听ReplicaSets/Pods的Informer

   go replicaset.NewReplicaSetController(

      ctx.InformerFactory.Extensions().V1beta1().ReplicaSets(),

      ctx.InformerFactory.Core().V1().Pods(),

      ctx.ClientBuilder.ClientOrDie("replicaset-controller"),

      replicaset.BurstReplicas,

   ).Run(int(ctx.Options.ConcurrentRSSyncs), ctx.Stop)

   return true, nil

}

创建过程如下:

// NewReplicaSetController configures a replica set controller with the specified event recorder

func NewReplicaSetController(rsInformer extensionsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, kubeClient clientset.Interface, burstReplicas int) *ReplicaSetController {

   ....

   // 初始化controller

   rsc := &ReplicaSetController{

      kubeClient: kubeClient,

      podControl: controller.RealPodControl{

         KubeClient: kubeClient,

         Recorder:   eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "replicaset-controller"}),

      },

      burstReplicas: burstReplicas,

      expectations:  controller.NewUIDTrackingControllerExpectations(controller.NewControllerExpectations()),

      queue:         workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "replicaset"),

   }

 

   // 在replica set informer上注册回调handler

   rsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{

      AddFunc:    rsc.enqueueReplicaSet,

      UpdateFunc: rsc.updateRS,

      // This will enter the sync loop and no-op, because the replica set has been deleted from the store.

      // Note that deleting a replica set immediately after scaling it to 0 will not work. The recommended

      // way of achieving this is by performing a `stop` operation on the replica set.

      DeleteFunc: rsc.enqueueReplicaSet,

   })

   rsc.rsLister = rsInformer.Lister()

   rsc.rsListerSynced = rsInformer.Informer().HasSynced

 

   // 在pod informer上注册回调

   podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{

      AddFunc: rsc.addPod,

      // This invokes the ReplicaSet for every pod change, eg: host assignment. Though this might seem like

      // overkill the most frequent pod update is status, and the associated ReplicaSet will only list from

      // local storage, so it should be ok.

      UpdateFunc: rsc.updatePod,

      DeleteFunc: rsc.deletePod,

   })

   rsc.podLister = podInformer.Lister()

   rsc.podListerSynced = podInformer.Informer().HasSynced

 

   // syncReplicaSet整个controller实际业务逻辑的入口,会被回调触发

   rsc.syncHandler = rsc.syncReplicaSet

 

   return rsc

}

Replica Set资源变更回调

Informer监听到的变更最终会回调到syncReplicaSet方法上,但当中会穿越多个协程,逻辑比较复杂。用一个时序图近似表示如下:

1.Controller变更通知

这里的controller是Informer层的结构,对于资源变更会触发HandleDeltas()方法。HandleDeltas方法会调用sharedProcessor.distribute方法,将Delta传入到processListener的channel上,等待被处理。

2.processorListener.run

run方法会不断拉取listener自己本地channel中的变更,并根据ActionType分发到注册的handler上的不同方法里。

在上文介绍的NewReplicaSetController()函数里,可以看到AddFunc对应的回调函数是enqueueReplicaSet。最终会把delta放入ReplicaSetController自己的queue队列中,等待controller处理。

3.ReplicaSetController.processNextItem

processNextItem方法会处理RepliaSetController.queue当中的变更信息,最终调用syncReplicaSet方法来处理变更,确保Pods和配置一致。

总结

每个Controller的处理逻辑都不相同,但与manager & informer的交互大体类似。

ReplicaSetController的分析中可以再次看出go实现中,调用顺序和传统面向对象语言有很大差异。

转载于:https://my.oschina.net/zhuhui/blog/3081714

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值