kubernetes使用informer机制来保证消息的实时性、可靠性、顺序性等,Kubernetes的其他组件都是通过client-go的Informer机制与Kubernetes API Server进行通信的。
主要流程如下:
- Reflector通过List获取集群的所有对象,并放到本地store缓存起来
- 然后Reflector通过Watch时刻监听集群的事件
- 如果获得集群事件就把这个事件发送到Delta FIFO
- controller从Delta FIFO中依次pop出事件并交给informer的回调函数HandleDeltas
- indexer将事件存储在本地的缓存中
- distribute负责将资源对象分发到具体的处理函数
- Rsync会把本地的缓存的资源对象同步到DeltaFIFO
比如我们要删除一个叫demo的pod,那么其主要流程如下:
- 首先是Reflector通过Watch收到要删除名叫demo的pod事件,然后将这个事件发送给Delta FIFO
- 从DeltaFIFO中pop这个事件并交给indexer进行本地处理,首先会存储这个事件,其次会从本地store中删除这个pod
- 回调函数会调用distribute去处理不同的对象
从上面可以看到其主要组件有以下几个。
(1)、Reflector
Reflector负责List&Watch指定的kubernetes资源,当Watch到监控的资源发生变化时,就会触发相应的变更事件。比如Added(资源添加)事件、Updated(资源更新)事件、Deleted(资源删除)事件,并将其资源对象存放到本地缓存DeltaFIFO中。
(2)、DeltaFIFO
DeltaFIFO就是一个资源对象存储的一个队列。
(3)、indexer
Indexer是client-go用来存储资源对象并自带索引功能的本地存储,Reflector从DeltaFIFO中将消费出来的资源对象存储至Indexer。Indexer与Etcd集群中的数据完全保持一致。client-go可以很方便地从本地存储中读取相应的资源对象数据,而无须每次从远程Etcd集群中读取,以减轻Kubernetes API Server和Etcd集群的压力。
(4)、informer
Informer
是 Client-go
中的一个核心工具包。在Kubernetes
源码中,如果 Kubernetes
的某个组件,需要 List/Get Kubernetes
中的 Object
,在绝大多 数情况下,会直接使用Informer
实例中的Lister()
方法(该方法包含 了 Get 和 List 方法),而很少直接请求Kubernetes API
。Informer
最基本 的功能就是List/Get Kubernetes
中的 Object
。
informer模式
APIServer
是集群负载提升后最容易遇到瓶颈的地方,多集群改造是我们最后的手段。但是我们必须提前做一些事情来避免一些集群性能问题。是的,在处理 client-go
时,请遵循其informer
模式。
informer的实现很复杂,但它的作用很明显:保持对集群资源的持续访问,通过缓存和事件缓解 APIServer
压力。
Kubernetes Informe
r 模式可以分为两部分:一是涉及控制器(operator
)开发,二是在 client-go
等客户端程序中实现。
Informer
http://k8s.io)\client-go\informers\core\v1\pod.go):每一个Kubernetes资源上都实现了Informer机制。每一个Informer上都会实现Informer和Lister方法,例如PodInformer,代码示例如下(staging\src[k8s.io](
定义不同资源的Informer,允许监控不同资源的资源事件。比如监控Pod的资源事件,当Pod有新增、删除、修改等事件的时候,client-go中的Watch能及时收到资源对象的变更信息。
Shared Informer
同一个资源的informer可能会被实例化多次,比如一个Pod可能会被deployment的Informer实例化,也可能会被replicaset实例化,如果一个informer一个Reflector,就会导致有许许多多的Reflector做相同的事情,会导致api server负载过重。所以client-go提供了一种shared informer机制,就是同一资源的Informer共享一个Reflector。
http://k8s.io)\client-go\informers\factory.go):其中Informers字段的定义如下(staging\src[k8s.io](
可以看到informers字段是一个map类型,其中Key是资源类型,value是SharedIndexInformer。
http://k8s.io)\client-go\informers\factory.go):而InformerFor方法添加了不同资源的infomer,如下(staging\src[k8s.io](
- 首先获取资源类型,如果存在则直接返回
- 获取rsync的时间,如果没有自定义则使用默认的时间
- 然后创建一个新的informer,更新Informers字段
最后通过Shared Informer的Start方法使f.informers中的每个informer通过goroutine持久运行。
Reflector
Reflector主要通过List&Watch来获取监控集群资源,其主要有两部分:List和Watch。其中List就是列出集群的资源,基于HTTP短链接实现。Watch是监听资源事件,是基于HTTP长连接实现。
Reflector的结构体定义如下,代码路径staging\src**k8s.io\client-go\tools\cache\reflector.go**:
可以看到Reflector定义了一个listerWatcher,而ListerWatcher是一个接口,定义如下,代码路径:staging\src**k8s.io\client-go\tools\cache\listwatch.go**:
而Lister和Watcher也是一个接口,其分别需要实现List和Watch方法,定义如下:
而ListWatch实现了这两个方法,定义如下:
而ListFunc和WatchFunc是定义的两个类型,如下:
WorkQueue
WorkQueue称为工作队列,Kubernetes的WorkQueue队列与普通FIFO(先进先出,First-In,First-Out)队列相比,实现略显复杂,它的主要功能在于标记和去重,并支持如下特性。
● 有序:按照添加顺序处理元素(item)。
● 去重:相同元素在同一时间不会被重复处理,例如一个元素在处理之前被添加了多次,它只会被处理一次。
● 并发性:多生产者和多消费者。
● 标记机制:支持标记功能,标记一个元素是否被处理,也允许元素在处理时重新排队。
● 通知机制:ShutDown方法通过信号量通知队列不再接收新的元素,并通知metric goroutine退出。
● 延迟:支持延迟队列,延迟一段时间后再将元素存入队列。
● 限速:支持限速队列,元素存入队列时进行速率限制。限制一个元素被重新排队(Reenqueued)的次数。
● Metric:支持metric监控指标,可用于Prometheus监控。
WorkQueue支持3种队列,并提供了3种接口,不同队列实现可应对不同的使用场景,分别介绍如下。
● Interface:FIFO队列接口,先进先出队列,并支持去重机制。
● DelayingInterface:延迟队列接口,基于Interface接口封装,延迟一段时间后再将元素存入队列。
● RateLimitingInterface:限速队列接口,基于DelayingInterface接口封装,支持元素存入队列时进行速率限制。
Interface
http://k8s.io)\client-go\util\workqueue\queue.go)Interface是FIFO队列,是最基础的队列,限速和延迟队列都是基于它来实现的。其提供一下方法(源码:staging\src[k8s.io](
RateLimitingInterface
RateLimitingInterface是限速队列,基于延迟队列和FIFO队列接口封装,在原有功能上增加了AddRateLimited、Forget、NumRequeues方法。限速队列的重点不在于RateLimitingInterface接口,而在于它提供的4种限速算法接口(RateLimiter)。其原理是,限速队列利用延迟队列的特性,延迟某个元素的插入时间,达到限速目的。
评论区