client-go架构
以下是client-go
的官方架构图
一、Indexer
Indexer
保存来自api-server
的资源,使用list-watch
方式来维护资源的增量变化。通过这种方式可以减少对api-server
的访问,减少api-server
端的压力。
Indexer
继承Store
接口,使用多个索引扩展Store
并限制每个累加器仅保存当前对象(在Delete后为空)。
Store
接口定义了对象的增删改查等方法。
而cache
实现了Indexer
接口,它定义了线程安全和key的序列化方法
|
|
而ThreadSafeStore
是一个允许对后台存储进行并发访问的接口,类似于Indexer
,但是不需要知道如何从对象obj中取出key。
通过NewStore
和NewIndexer
初始化cache返回Store
或Indexer
指针。
- indexer实际的对象存储在
threadSafeMap
中 indexers
划分了不同类型的索引值(indexName,如namespace),并按照索引类型进行索引(indexFunc,如MetaNamespaceIndexFunc
),得到符合该对象的索引键,一个对象在一个索引类型中可以有多个索引键- items的键值对保存了实际对象
以namespace
为索引类型,
1、从indexers
获取计算namespace
的IndexFunc
2、用IndexFunc
计算入参obj相关的所有namespaces,indeices
中保存了所有namespaces下面的对象键,可以获取特定namespace下的对象键
3、在items
中可以通过对象键得到对象
二、DeltaFIFO
DeltaFIFO是一个生产者-消费者队列,生产者为Reflector,消费者为Pop()
方法。
DeltaFIFO
实现了Queue
和Store
接口,使用Deltas
保存对象状态的变更(Add/Delete/Update),Deltas缓存了针对相同对象的多个状态变更信息,如Delta[0]存储了pod的更新,最老的状态变更为Oldest()
,最新的状态变更为Newest
。
其中knownObjects
类型为KeyListerGetter
,接口方法ListKeys
和GetByKey
也是Store
接口中的方法,而实际上,knownObjects
也是使用Store/Indexer
来初始化的,也就是说可以通过ListKeys
和GetByKey
方法获取Store/Indexer
中的对象键。
initialPopulationCount
表示是否完成全量同步,在Replace
增加,在Pop
减少,当initialPopulationCount=0
且populated=true
表示Pop
了所有的Replace
添加到DeltaFIFO
对象,populated
用于判断是DeltaFIFO中是否为初始化状态(即没有处理过任何对象).
在
NewSharedIndexInformer
中初始化了sharedIndexInformer
,用NewIndexer
初始化Indexer
,在Run
方法中用s.indexer
作为DeltaFIFO
的knowObjects
。
DeltaFIFO
实现了Queue
接口。
在list-watch
的list
步骤中,会调用Replace
方法来对DeltaFIFO
进行全量更新:
1、Sync
所有DeltaFIFO
中的对象,全部加入到DeltaFIFO
中
2、如果knownObjects
为空,则删除DeltaFIFO
中不存在的对象,
3、如果knownObjects
非空,获取knownObjects
中不存在的对象,在DeltaFIFO
删除
三、List-Watch
Lister
用于获取某个资源的全量,Watcher
用于获取某个资源的增量变化。
实际使用中Lister和Watcher都从apiServer获取资源信息,Lister一般用于首次获取某资源(如Pod)的全量信息,而Watcher用于持续获取该资源的增量变化信息。
在例子的workqueue可以看到调用NewListWatchFromClient
的地方
|
|
而这个资源名称在k8s.io/api/core/v1/types.go
中定义。
其中clientset
中定义API group
,这些都定义在client-go/kubernetes/typed
中。
返回的RESTClient()
返回值为Interface
接口类型,封装了对资源的操作方法。
|
|
而在List-Watch
的List
时就调用了Get
方法。
四、Reflector
Reflector
使用ListerWatcher
获取资源,将其保存在store
中,这里的store
就是DeltaFIFO
。
ListAndWatch
在Reflector.Run
启动,并以resyncPeriod
周期性调度。
在List时获取资源的首个resourceVersion值,在Watch时获取资源的增量变化,然后将获取到的resourceVersion保存起来
五、WorkQueue
用于保存infromer中handler处理后的数据。
六、Controller
|
|
config中的Queue就是DeltaFIFO。
Controller定义了如何调度Reflector。
Controller的运行就是执行了Reflector.Run
,相当于启动了一个DeltaFIFO
的生产者,使用wait.Until
启动一个消费者。
|
|
processLoop
运行了DeltaFIFO.Pop
方法,消费DeltaFIFO
对象,如果运行失败会重新添加AddIfNotPresent
。
七、ShareInformer
一个是启动了Controller,一个是注册了process
的handler方法,run
方法接受nextCh
的值,将其作为参数传给handler处理,而pop
将addCh
中的元素传送给pendingNotifications
,并读取元素,传给nextCh
。
也就是说pop
负责管理数据,run
负责处理数据。
这个handler
就是例子中写的AddFunc
,UpdateFunc
,DeleteFunc