k8s-client-go源码剖析(二)

本文是K8S源码研习社第一期第二周学习内容,围绕Informer机制展开。介绍了其架构设计,包括Reflector、DeltaFIFO、Indexer的作用,还分析了相关源码。指出Informer机制初始化从Kubernetes API Server取全量数据,后续用Watch机制接收推送,减少API Server压力,Resync是重试机制。
简介:云原生社区活动---Kubernetes源码剖析第一期第二周

本周是K8S源码研习社第一期第二周,学习内容是学习Informer机制,本文以这个课题进行展开。

本周研习社社长挺忙的,将本次课程推迟到下一周结束,任何事情都是这样,计划总有可能会被其他事情打破,但最终只要能够回归到对应的主线上,就不是什么问题。就像参与开源一样,最开始的开放源代码只是开始,需要的是能够坚持下去,而这一点往往是很重要的。

好了,开始正文。

本文主题:


  1. Informer机制架构设计总览
  2. Reflector理解
  3. DeltaFIFO理解
  4. Indexer理解

如果涉及到资源的内容,本文以Deployment资源进行相关内容讲述。

Informer机制架构设计总览

下面是我根据理解画的一个数据流转图,从全局视角看一下数据的整体走向是怎么样的。

其中虚线的表示的是代码中的方法。

首先讲一个结论:

通过Informer机制获取数据的情况下,在初始化的时候会从Kubernetes API Server获取对应Resource的全部Object,后续只会通过Watch机制接收API Server推送过来的数据,不会再主动从API Server拉取数据,直接使用本地缓存中的数据以减少API Server的压力。

Watch机制基于HTTP的Chunk实现,维护一个长连接,这是一个优化点,减少请求的数据量。第二个优化点是SharedInformer,它可以让同一种资源使用的是同一个Informer,例如v1版本的Deployment和v1beta1版本的Deployment同时存在的时候,共享一个Informer。

上面图中可以看到Informer分为三个部分,可以理解为三大逻辑。

其中Reflector主要是把从API Server数据获取到的数据放到DeltaFIFO队列中,充当生产者角色。

SharedInformer主要是从DeltaFIFIO队列中获取数据并分发数据,充当消费者角色。

最后Indexer是作为本地缓存的存储组件存在。

Reflector理解

Reflector中主要看Run、ListAndWatch、watchHandler三个地方就足够了。

源码位置是 tools/cache/reflector.go

// Ruvn starts a watch and handles watch events. Will restart the watch if it is closed.
// Run will exit when stopCh is closed.
//开始时执行Run,上一层调用的地方是 controller.go中的Run方法
func (r *Reflector) Run(stopCh <-chan struct{}) {
    
    klog.V(3).Infof("Starting reflector %v (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
    wait.Until(func() {
         //启动后执行一次ListAndWatch
        if err := r.ListAndWatch(stopCh); err != nil {
            utilruntime.HandleError(err)
        }
    }, r.period, stopCh)
}

...

// and then use the resource version to watch.
// It returns error if ListAndWatch didn't even try to initialize watch.
func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {

// Attempt to gather list in chunks, if supported by listerWatcher, if not, the first
            // list request will return the full response.
            pager := pager.New(pager.SimplePageFunc(func(opts metav1.ListOptions) (runtime.Object, error) {

//这里是调用了各个资源中的ListFunc函数,例如如果v1版本的Deployment
//则调用的是informers/apps/v1/deployment.go中的ListFunc
                             return r.listerWatcher.List(opts)
            }))
            if r.WatchListPageSize != 0 {
                pager.Pa1geSize = r.WatchListPageSize
            }
            // Pager fal
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值