3.3.5 Cache
1. Cache是什么
Kubernetes是典型的 Server-Client的架构,APIServer 作为集群统一的操作入口,任何对资源所做的操作(包括增删改查)都必须经过 APIServer。为了减轻 APIServer的压力,Controller-runtime 抽象出一个 Cache层,Client端对 APIServer 数据的读取和监听操作都将通过 Cache层来进行。
Cache 接口的实现见代码清单3-44。
typeCacheinterface{client.Reader
Informers
}
Cache接口定义了如下两个接口。
(1) client.Reader:用于从 Cache中获取及列举 Kubernetes集群的资源。
(2) Informers:可为不同的 GVK创建或获取对应的 Informer,并将 Index添加到对应的 Informer中。
2. Cache的初始化
在 ControllerManager的初始化启动过程中,将会构建 Cache层,以供 Manager使用。在用户没有指定 Cache初始化函数的前提下,将使用 Controller-runtime默认提供的Cache初始化函数,本节将依据默认提供的函数,阐述 Cache初始化的流程。
Controller-runtime提供的Cache初始化函数位于 pkg/cache/cache.go#L111下,完整的初始化流程如图 3-5所示。
图 3—5Cache 初始化流程
(1) 设置默认参数:若 Scheme为空, 则设置为 scheme.Scheme;若 Mapper为空, 则 通 过apiutil.NewDiscoveryRESTMapper基 于 Discovery的 信 息 构 建 出 一 个RESTMapper,用于管理所有 Object 的信息;若同步时间为空,则将 Informer的同步时间设置为 10小时。
(2)初始化 InformersMap,为 3种不同类型的Object(structured、unstructured、metadata-only)分别构建 InformersMap。
(3)初始化 specificInformersMap:该接口通过 Object与 GVK的组合信息创建并缓存 Informers。
(4)定义 List-Watch函数:为 3种不同类型的Object实现 List-Watch函数,通过该函数可对GVK进行 List和 Watch操作。
通过Cache的初始化流程,我们可以看出 Cache主要创建了InformersMap,Scheme中的每个GVK都会创建对应的Informer,再通过informersByGVK的Map,实现GVK到Informer的映射;每个Informer都会通过List-Watch函数对相应的GVK进行List和Watch操作。
3. Cache的启动
Cache启动的核心是启动创建的所有Informer(见代码清单3-45)。
func(ip*specificInformersMap)Start(ctxcontext.Context){
func(){
...
//Starteachinformer
for_,informer:=rangeip.informersByGVK{goinformer.Informer.Run(ctx.Done())
}
...
}
Informer 的启动流程主要包含以下3个步骤,具体实现细节可参考2.2.6节。
(1) 初始化 DeltaFIFO队列。
(2) 创建内部 Controller:配置 DeltaFIFO 队列和事件的处理函数。
(3) 启动 Controller:创建 Reflector,负责监听 APIServer上指定的 GVK,将 Add、Update、Delete变更事件写入 DeltaFIFO 队列中,作为变更事件的生产者;Controller中的事件处理函数HandleDeltas() 会消费这些变更事件,负责将更新写入本地 Indexer,同时将这些 Add、Update、Delete事件分发给之前注册的监听器。