1. 定义
K8S的Informer模块封装list-watch API,用户只需要指定资源,编写好事件处理函数(AddFunc, UpdateFunc,DeleteFunc等), Informer首先通过list API罗列资源,然后调用watch API监听资源的变更事件,并将结果放到一个FIFO队列,队列的另一头进程取出事件,并调用相关的注册函数处理事件。Informer还维护了一个只读的Map Store的缓存,主要目的是提升查询效率,降低apiserver负载。
Informer是Client-go中的一个核心工具包,在K8s源码中,如果K8s的某个组件,需要List/Get k8s中的object,在大多数情况下,会直接使用Informer实例中的Lister方法,很少直接请求K8s API,Informer最基本的功能是List/Get K8s中的object。
2. 设计思路
2.1. 关键点
- 更快返回List/Get请求的结果,减少对K8s API的直接调用
- 依赖K8s List/Watch API
- 可监听事件并触发回调函数的二级缓存工具包
2.2. 更快返回List/Get请求的结果,减少对K8s API的直接调用
Informer实例的LIster()方法,List/Get K8s中的object时,Informer不会直接去请求K8s API,而是直接去查找内存中的数据(Informer自己维护),通过这种方式,Informer可以更快的返回结果,又能减少对K8s API的直接调用。
2.3. 依赖K8s List/Watch API
Informer只会调用Kubernetes List和Watch两种类型的API。Informer在初始化的时,先调用Kubernetes List API获得某种resource的全部Object,缓存在内存中; 然后,调用Watch API去watch这种resource,去维护这份缓存; 最后,Informer就不再调用Kubernetes的任何 API。
只调用一次List API,之后完全依赖Watch API去维护缓存,没有任何resync机制,现有的List/Watch机制完全能够保证不会漏掉任何事件,也说明了K8s完全信任etcd。
2.4. 可监听事件并触发回调函数的二级缓存工具包
Informer通过Kubernetes Watch API监听某种resource下的所有事件。
Informer可以添加自定义的回调函数,这个回调函数实例(即ResourceEventHandler实例),只需实现OnAdd(ob jinterface{})OnUpdate(oldObj, newObj interface{}) 和OnDelete(obj interface{}) 三个方法,这三个方法分别对应informer监听到创建、更新和删除这三种事件类型。
2.5. 二级缓存
二级缓存是informer的底层缓存机制,两级缓存分别是DeltaFIFO和LocalStore。两级缓存的用处各不相同,DelataFIFO用来储存watch API返回的各种事件,LocalStotre只会被Lister的List/Get方法访问。两级缓存之间存在resync机制。
2.6. 关键逻辑介绍
- Informer 在初始化时,Reflector 会先 List API 获得所有的 Pod
- Reflect 拿到全部 Pod 后,会将全部 Pod 放到 Store 中
- 如果有人调用 Lister 的 List/Get 方法获取 Pod, 那么 Lister 会直接从 Store 中拿数据
- Informer 初始化完成之后,Reflector 开始 Watch Pod,监听 Pod 相关 的所有事件;如果此时 pod_1 被删除,那么 Reflector 会监听到这个事件
- Reflector 将 pod_1 被删除 的这个事件发送到 DeltaFIFO
- DeltaFIFO 首先会将这个事件存储在自己的数据结构中(实际上是一个 queue),然后会直接操作 Store 中的数据,删除 Store 中的 pod_1
- DeltaFIFO 再 Pop 这个事件到 Controller 中
- Controller 收到这个事件,会触发 Processor 的回调函数
- LocalStore 会周期性地把所有的 Pod 信息重新放到 DeltaFIFO 中