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

这篇具有很好参考价值的文章主要介绍了深入源码分析kubernetes informer机制(三)Resync。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


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


为什么需要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中的数据变更事件
    深入源码分析kubernetes informer机制(三)Resync,kubernetes,容器,云原生

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

  • 首先api-server与informer中间通过sourceVersion可以保证数据的一致性
    client携带本地的sourceVersion请求api-server,api-server会将最新版本的增量变化通过事件返回给client。
    如图所示,在此期间,如果数据连接发生任何异常,informer会在重新建立watcher连接时,携带上个版本的sourceVersion,并再次更新所有的增量变化。
    深入源码分析kubernetes informer机制(三)Resync,kubernetes,容器,云原生

  • 然后是本地informer与custom之间,通过workqueue来进行事件通知。
    informer的协程将FIFO队列中的事件取出更新至本地后,还会将事件同步回调至custom controller,加入到workqueue队列中。
    但是回看informer的代码,informer在处理回调事件时,并不会关注回调的结果。
    深入源码分析kubernetes informer机制(三)Resync,kubernetes,容器,云原生

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

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

resync做了什么

resync的逻辑非常简单,就是定时将本地缓存中所有的资源对象生成事件重新推送到FIFO中,重新触发controller的回调。
参考《Programming Kubernetes》一书中的概念,其实就是在边缘触发,水平驱动的基础上,附加了定时同步的能力。
深入源码分析kubernetes informer机制(三)Resync,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的信号,内部实现就是一个timer
	defer func() {
		cleanup() // Call the last one written into cleanup
	}()
	for {
		select {
		case <-resyncCh:
		case <-stopCh:
			return
		case <-cancelCh:
			return
		}

        // sharedIndexInformer 中用ShouldResync()来管理各个listener的resync
		if 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文章来源地址https://www.toymoban.com/news/detail-651513.html

到了这里,关于深入源码分析kubernetes informer机制(三)Resync的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • RecyclerView 滑动布局源码分析:带你深入掌握列表滑动机制

    作者:maxcion 现在 RV 已经初始化好了,那当我们进行滑动交互时代码又是如何执行的呢? RV 优秀就优秀在他是动态布局的,与 ScrollView 不同在于: ScrollView 是初始化时将所有child都 inflate 并 add 而 RV 是只 inflate 屏幕展示得下的child. 如果我们有100个child: ScrollView 便会在初始化时就

    2023年04月23日
    浏览(38)
  • 深入分析Spring的IoC容器:从底层源码探索

    前言: 博主在最近的几次面试中,大中小厂都问到了Spring的ioc容器相关问题,这块知识确实是面试中的重点内容,因此结合所看的书籍,在这篇文章中总结下。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读,感谢大佬的关注。 如果文章有什么需要改进的地方欢迎

    2024年02月12日
    浏览(51)
  • 【云原生-深入理解 Kubernetes 系列 3】深入理解容器进程的文件系统

    【云原生-深入理解Kubernetes-1】容器的本质是进程 【云原生-深入理解Kubernetes-2】容器 Linux Cgroups 限制 大家好,我是秋意零。 😈 CSDN作者主页 😎 博客主页 👿 简介 👻 普通本科生在读 在校期间参与众多计算机相关比赛,如:🌟 “省赛”、“国赛” ,斩获多项奖项荣誉证书

    2024年02月06日
    浏览(50)
  • Kubernetes日志查看指南:深入了解容器日志管理技术

    简介: Kubernetes(简称K8s)已成为现代容器化应用程序管理的主要平台之一。了解如何有效地查看和管理Kubernetes集群中的容器日志对于故障排除、性能优化和安全监控至关重要。本文将向您介绍一些基本的技术和工具,帮助您在Kubernetes环境中查看和分析容器日志。 查看单个

    2024年02月12日
    浏览(42)
  • 【云原生-深入理解Kubernetes-1】容器的本质是进程

    大家好,我是秋意零。 😈 CSDN作者主页 😎 博客主页 👿 简介 👻 普通本科生在读 在校期间参与众多计算机相关比赛,如:🌟 “省赛”、“国赛” ,斩获多项奖项荣誉证书 🔥 各个平台, 秋意零/秋意临 账号创作者 🔥 云社区 创建者 点赞、收藏+关注下次不迷路! 欢迎加

    2024年02月02日
    浏览(58)
  • 云原生之深入解析Kubernetes中如何使用临时容器进行故障排查

    容器及其周围的生态系统改变了工程师部署、维护和排查工作负载故障的方式。但是,在 Kubernetes 集群上调试应用程序有时可能会很困难,因为可能在容器中找不到所需的调试工具。许多工程师使用基于精简、发行版构建无发行版的基础镜像,其中甚至没有包管理器或shell,

    2024年02月05日
    浏览(48)
  • 云原生之深入解析如何正确计算Kubernetes容器CPU使用率

    使用 Prometheus 配置 kubernetes 环境中 Container 的 CPU 使用率时,会经常遇到 CPU 使用超出 100%,现在来分析一下: container_spec_cpu_period:当对容器进行 CPU 限制时,CFS 调度的时间窗口,又称容器 CPU 的时钟周期通常是 100000 微秒 container_spec_cpu_quota:是指容器的使用 CPU 时间周期总量

    2024年02月10日
    浏览(71)
  • kubernetes--分析容器系统调用:Sysdig

    目录 Sysdig介绍: sysdig工作流程 安装Sysdig sysdig常用参数: sysdig过滤: sysdig之Chisels(工具箱): 其他常用命令        Sysdig是一个非常强大的系统监控分析和故障排查工具。汇聚strace+tcpdump+iftop+lsof工具功能为一身。        sysdig除了能获取系统资源利用率、进程、网络连

    2024年02月05日
    浏览(43)
  • 源码分析——ArrayList源码+扩容机制分析

    ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。 ArrayList 继承于 AbstractList ,实现了 List , RandomAccess , Cloneable , ja

    2024年02月14日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包