kubernetes informer 原理解析一

一:Informer 作用

Kubernetes设计了Informer这个机制,用来作为控制器跟apiserver交互的桥梁,它主要有两方面的作用:

1)依赖Etcd的List&Watch机制,在本地维护了一份所关心的API对象的缓存。Etcd的Watch机制能够使客户端及时获知这些对象的状态变化,然后更新本地缓存,这样就在客户端为这些API对象维护了一份和Etcd数据库中几乎一致的数据,然后控制器等客户端就可以直接访问缓存获取对象的信息,而不用去直接访问apiserver,这一方面显著提高了性能,另一方面则大大降低了对apiserver的访问压力;

2)依赖Etcd的Watch机制,触发控制器等客户端注册到Informer中的事件方法。客户端可能会某些对象的某些事件感兴趣,当这些事件发生时,希望能够执行某些操作,比如通过apiserver新建了一个pod,那么kube-scheduler中的控制器收到了这个事件,然后将这个pod加入到其队列中,等待进行调度。

简单来说,Informer 主要功能就是缓存对象到本地以及根据对应的事件类型回调已注册好的 ResourceEventHandler 作相应的处理。

二:Informer 流程分析

 

 

1)Informer 中几个组件的作用:

  • Reflector:称之为反射器,实现对 apiserver 指定类型对象的监控(ListAndWatch),其中反射实现的就是把监控的结果实例化成具体的对象,最终也是调用 Kubernetes 的 List/Watch API;
  • DeltaIFIFO Queue:一个增量队列,将 Reflector 监控变化的对象形成一个 FIFO 队列,此处的 Delta 就是变化;
  • Controller:通过轮询机制不断从队列中取出Delta元素,根据元素的类型,一方面通过Indexer更新本地的缓存,一方面调用Processor来触发注册到Informer的事件方法;
  • Processer和Listener:是触发事件方法的机制,在创建Informer时,会创建一个Processer,而在向Informer中通过调用AddEventHandler()注册事件方法时,会为每一个Handler生成一个Listener,然后将该Lisener中添加到Processer中,每一个Listener中有两个channel:addCh和nextCh。Listener通过select监听在这两个channel上,当Controller从队列中取出新的元素时,会调用processer来给它的listener发送“通知”,这个“通知”就是向addCh中添加一个元素,即add(),然后一个goroutine就会将这个元素从addCh转移到nextCh,即pop(),从而触发另一个goroutine执行注册的事件方法,即run()
  • Indexer:对缓存进行增删查改的接口
  • LocalStore:就是 informer 的 cache,减少了 apiserver 的压力
  • WorkQueue:用户存储DeltalFIFO的事件object提取的key

备注:

client-go的cache包实现reflector和ListWatch接口

 

2)流程分析:

  • Informer 首先会 list/watch apiserver,Informer 所使用的 Reflector 负责与 apiserver 建立连接,Reflector 使用 ListAndWatch 的方法,会先从 apiserver 中 list 该资源(Reflector指定的资源)的所有实例,list 会拿到该对象最新的 resourceVersion,然后使用 watch 方法监听该 resourceVersion 之后的所有变化,若中途出现异常,reflector 则会从断开的 resourceVersion 处重现尝试监听所有变化,一旦该对象的实例有创建、删除、更新动作,Reflector 都会收到”事件通知”,这时,该事件及它对应的 API 对象这个组合,被称为增量(Delta),它会被放进 DeltaFIFO 中。
  • Informer 的 controller 会不断地从这个 DeltaFIFO (增量队列)中拿出一个对象,Informer 就会判断这个增量的事件类型,然后创建或更新本地的缓存。如果事件类型是 Added(添加对象),那么 Informer 会通过 Indexer 库把这个增量里的 API 对象保存到本地的缓存中,并为它创建索引,若为删除操作,则在本地缓存中删除该对象。
  • 同时 informer 的 controller 会把 object 索引所对应的 key 放到 workqueue 种,然后 controller 再调用事先注册好的 ResourceEventHandler 进行回调处理。(在 ResourceEventHandler 回调函数中,可以做一些很简单的过滤)
  • Controller 从 workqueue 里面取出 key,通过indexer从本地缓存取出object,然后启动一个 worker 来执行自己的业务逻辑,业务逻辑通常是现状不断调和到用户期望的状态。
  • 在worker中就可以使用 lister 来获取 resource,而不用频繁的访问 apiserver,因为 apiserver 中 resource 的变更都会反映到本地的 cache 中。

3)Delta FIFO Queue事件类型:

Added, Updated, Deleted, Replaced, Resync 五种

4)Informer resyncPeriod 字段作用:

Informer还会周期性的发送Resync类型的Delta元素到队列中,目的是为了周期性的触发注册到Informer中的事件方法UpdateFunc,保证对象的期望状态和实际状态一致,该周期是由一个叫做resyncPeriod的参数决定的,在向Informer中添加EventHandler时,可以指定该参数,若为0的话,则关闭该功能。

需要注意的是,Resync类型的Delta元素中的对象,是通过Indexer从缓存中获取到的,而不是直接从apiserver中拿的,即这里resync的,其实是”缓存”的对象的期望状态和实际状态的一致性。

5)正常情况下,List&Watch只会执行一次,即先执行List把数据拉过来,放入队列中,后续就进入Watch阶段。而不是不断地List。(异常或者重启会重新List)

posted @ 2021-08-19 16:24  salami_china  阅读(433)  评论(0编辑  收藏  举报