当前位置: 首页 > news >正文

深入源码分析kubernetes informer机制(三)Resync


[阅读指南]
这是该系列第三篇
基于kubernetes 1.27 stage版本
为了方便阅读,后续所有代码均省略了错误处理及与关注逻辑无关的部分。


文章目录

  • 为什么需要resync
  • resync做了什么

为什么需要resync

如果看过上一篇,大概能了解,client数据主要通过reflector 的list/watch进行同步。

回顾一下informer整体的数据同步逻辑。

  1. informer初始化时,调用list接口获取制定类型的全量资源数据,此时的resource version默认为0。假如指定资源类型为pod,那么就是获取所有pod数据
  2. list 获取到数据后,将全量数据同步到本地缓存。首次list完成后,informer后续都将通过watch来同步资源更新
  3. watcher监控到资源更新事件,将接收到的事件放入存储队列中(delta FIFO)
  4. informer 的另一个process会不断取出存储队列中的delta事件进行数据更新
  5. 缓存数据更新成功后,将数据变化通过回调函数同步至custom controller workqueue中
  6. custom controller顺序处理workqueue中的数据变更事件
    在这里插入图片描述

流程包括了三端的数据同步。

  • 首先api-server与informer中间通过sourceVersion可以保证数据的一致性
    client携带本地的sourceVersion请求api-server,api-server会将最新版本的增量变化通过事件返回给client。
    如图所示,在此期间,如果数据连接发生任何异常,informer会在重新建立watcher连接时,携带上个版本的sourceVersion,并再次更新所有的增量变化。
    在这里插入图片描述

  • 然后是本地informer与custom之间,通过workqueue来进行事件通知。
    informer的协程将FIFO队列中的事件取出更新至本地后,还会将事件同步回调至custom controller,加入到workqueue队列中。
    但是回看informer的代码,informer在处理回调事件时,并不会关注回调的结果。
    在这里插入图片描述

也就是说,如果custom controller侧的消费出现异常导致数据同步失败,informer是不知情的。

所以还需要引入别的机制来保障custom数据与本地缓存的一致性,以维持体的可靠性,也就是resync。
(当然如果controller本身也存在对比sourceVersion的逻辑,其实不需要这一机制也是可以确保数据一致的,resync相当于从框架层增加了一层保护,这篇博客有对相关的问题进行探讨)

resync做了什么

resync的逻辑非常简单,就是定时将本地缓存中所有的资源对象生成事件重新推送到FIFO中,重新触发controller的回调。
参考《Programming Kubernetes》一书中的概念,其实就是在边缘触发,水平驱动的基础上,附加了定时同步的能力。
在这里插入图片描述

具体来看下resync的代码实现。

informer在初始化时指定了resync执行间隔。

// informer创建方法
func NewIndexerInformer(lw ListerWatcher,objType runtime.Object,resyncPeriod time.Duration, // Resync执行周期h ResourceEventHandler,indexers Indexers,
) (Indexer, Controller) {}// workqueue调用示例
// 0 代表不重复执行
indexer, informer := cache.NewIndexerInformer(podListWatcher, &v1.Pod{}, 0, cache.ResourceEventHandlerFuncs{...})

在informer初始化完成后,拉起一个协程进行定时resync

func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {...go r.startResync(stopCh, cancelCh, resyncerrc)return r.watch(w, stopCh, resyncerrc)
}

该协程会按照informer配置的时间间隔定时调用存储对象的resync方法。
比较特殊的是,sharedIndexInformer类型的informer会另外有ShouldResync方法来轮询每个监听了当前资源对象的listener的是否需要进行resync操作。

func (r *Reflector) startResync(stopCh <-chan struct{}, cancelCh <-chan struct{}, resyncerrc chan error) {resyncCh, cleanup := r.resyncChan() // 返回一个触发resync的信号,内部实现就是一个timerdefer func() {cleanup() // Call the last one written into cleanup}()for {select {case <-resyncCh:case <-stopCh:returncase <-cancelCh:return}// sharedIndexInformer 中用ShouldResync()来管理各个listener的resyncif r.ShouldResync == nil || r.ShouldResync() {if err := r.store.Resync(); err != nil { resyncerrc <- err return}}cleanup()resyncCh, cleanup = r.resyncChan()}
}

resync只做一件事,将本地缓存里的资源对象全部重新添加到FIFO队列中,再触发contronller处理一次。
不过,为了避免与最新的变更发生冲突,FIFO队列中已有delta且还没有处理的资源对象,不会被重新添加。

func (f *DeltaFIFO) Resync() error {f.lock.Lock()defer f.lock.Unlock()if f.knownObjects == nil {return nil}// f.knownObjects 可以获取到本地缓存中所有资源对象的列表keys := f.knownObjects.ListKeys()for _, k := range keys {// 过滤掉已经有新的事件在队列中等待处理的资源对象// 把所有资源对象以resync类型添加到队列中if err := f.syncKeyLocked(k); err != nil {return err}}return nil
}

参考:
https://www.kubernetes.org.cn/2693.html
https://github.com/cloudnativeto/sig-kubernetes/issues/11
https://www.cnblogs.com/WisWang/p/13897782.html

http://www.lryc.cn/news/126214.html

相关文章:

  • FL Studio 21最新for Windows-21.1.0.3267中文解锁版安装激活教程及更新日志
  • HTML详解连载(4)
  • STM32 LL库+STM32CubeMX--点亮板载LED
  • 【HBZ分享】ES的评分score机制的原理
  • 函数递归专题(案例超详解一篇讲通透)
  • leetcode-413. 等差数列划分(java)
  • 从零开始学习 Java:简单易懂的入门指南之MAth、System(十二)
  • 人工智能原理概述 - ChatGPT 背后的故事
  • 【Linux】以太网协议——数据链路层
  • Neo4j之MATCH基础
  • Python实验代码合集
  • Less和Sass的原理和用法
  • c# List<T>.Aggregate
  • 软件测试常用工具总结(测试管理、单元测试、接口测试、自动化测试、性能测试、负载测试等)
  • Hadoop组件
  • jeecg-boot批量导入问题注意事项
  • Django图书商城系统实战开发 - 实现会员管理
  • Kafka如何解决消息丢失的问题
  • 我只记得512天在CSDN的日子
  • pycharm,VSCode 几个好用的插件
  • springboot 使用zookeeper实现分布式ID
  • git cherry-pick
  • 转行软件测试四个月学习,第一次面试经过分享
  • ECS服务器安装docker
  • 高等数学教材啃书汇总重难点(三)微分中值定理与导数的应用
  • 域名列表是什么?
  • 数据库操作不再困难,MyBatis动态Sql标签解析
  • Android 网络编程-网络请求
  • Mac下全选,使用pynput,怎样调用command键?
  • 21款美规奔驰GLS450更换中规高配主机,汉化操作更简单