You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Dec 13, 2023. It is now read-only.
// k8s.io/client-go/informers/factory.go// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.funcNewSharedInformerFactory(client kubernetes.Interface, defaultResync time.Duration) SharedInformerFactory {
returnNewSharedInformerFactoryWithOptions(client, defaultResync)
}
Activity
abhty822 commentedon Aug 6, 2020
因为这些操作都是异步的 合理的sync可以提高事件消费的容错性
lianghao208 commentedon Aug 6, 2020
感谢回答~ 能举个例子说说什么情况下会出现事件消费异常吗?
abhty822 commentedon Aug 6, 2020
嗯 ... 作为一个分布式的系统 排除代码之外 网络,基础设施等都有可能导致消费的异常,resync是一个很常规的操作(简单来说比如你的mq消费失败你会怎么做)
lianghao208 commentedon Aug 6, 2020
这里的消费者指的是从 FIFODelta 队列中取 event 的 workQueue 和从 workQueue 取 key 的 control loop 吗?在我看来虽然是异步的操作,但是这里面消费者和消息队列是同一个服务,好像不会有网络之类的消费异常问题
abhty822 commentedon Aug 6, 2020
以前看过的一篇文章 https://www.kubernetes.org.cn/2693.html ,可能这篇文章比我在这码字回答的更有效,实际上你说的relist也是一种resync的做法
[-]Informer 中为什么需要引入 Resync 机制?[/-][+][提问]Informer 中为什么需要引入 Resync 机制?[/+]lianghao208 commentedon Aug 9, 2020
一、Client-go 中的 Informer 工作流程图
Informer 中的 Reflector 通过 List/watch 从 apiserver 中获取到集群中所有资源对象的变化事件(event),将其放入 Delta FIFO 队列中(以 Key、Value 的形式保存),触发 onAdd、onUpdate、onDelete 回调将 Key 放入 WorkQueue 中。同时将 Key 更新 Indexer 本地缓存。Control Loop 从 WorkQueue 中取到 Key,从 Indexer 中获取到该 Key 的 Value,进行相应的处理。
二、Resync 机制的引入
我们在使用 SharedInformerFactory 去创建 SharedInformer 时,需要填一个 ResyncDuration 的参数
这个参数指的是,多久从 Indexer 缓存中同步一次数据到 Delta FIFO 队列,重新走一遍流程
为什么需要 Resync 机制呢?因为在处理 SharedInformer 事件回调时,可能存在处理失败的情况,定时的 Resync 让这些处理失败的事件有了重新 onUpdate 处理的机会。
那么经过 Resync 重新放入 Delta FIFO 队列的事件,和直接从 apiserver 中 watch 得到的事件处理起来有什么不一样呢?
从上面对 Delta FIFO 的队列处理源码可看出,如果是从 Resync 重新同步到 Delta FIFO 队列的事件,会分发到 updateNotification 中触发 onUpdate 的回调
三、总结
Resync 机制的引入,定时将 Indexer 缓存事件重新同步到 Delta FIFO 队列中,在处理 SharedInformer 事件回调时,让处理失败的事件得到重新处理。并且通过入队前判断 FIFO 队列中是否已经有了更新版本的 event,来决定是否丢弃 Indexer 缓存不进行 Resync 入队。在处理 Delta FIFO 队列中的 Resync 的事件数据时,触发 onUpdate 回调来让事件重新处理。
luffyao commentedon Aug 9, 2020
@lianghao208 Hi "在处理 SharedInformer 事件回调时,让处理失败的事件得到重新处理"。 这里应该会将处理过的事件也进行了一次update处理吧?
lianghao208 commentedon Aug 9, 2020
是的,准确的说时update处理,我改一下表述,感谢指正~
gasxia commentedon Aug 9, 2020
这个问题在《Programming Kubernetes》的第一章详细解释了一遍,我搬运一下。
主要的目的是为了不丢数据,处理
resync
机制还有边缘触发与水平获取的设计,一起来保证不丢事件、数据同步并能及时响应事件。以下内容都摘抄自《Programming Kubernetes》
lianghao208 commentedon Aug 9, 2020
学习了~ 感谢~
fighterhit commentedon Mar 6, 2021
gaorong commentedon Mar 7, 2021
fighterhit commentedon Mar 7, 2021
@gaorong 感谢解惑。对第2点的回答还有两个疑问:
从这句话字面上我理解的意思是说:如果网络只是短暂波动的话,watch 长连接会存在某种重试机制吗?那么这种重试机制是informer 自身实现的吗?或者还是借助http自身就有的某种机制?
这句话指的是对于informer来说,整体也存在重试机制?也就是再重新执行一开始的list+watch的完整过程:先执行一次list,后面都还走watch跟原来一样,跟重启了一样吗?
4 remaining items
PlatformLC commentedon Oct 12, 2021
谢谢@gasxia 和 @yutian2011 的解释帮助了理解。
小弟拙见:因为informer(或者说reflector)本身是通过边缘进行同步触发的,而后真正的controller(非informer内部的controller)通过水平驱动进行协调同步。而加入resync机制就是保证的协调的最终一致性,单次触发的同步协调失败没关系,会有定时的resync心跳机制让controller去到达最终的期望状态。
Yarollingstone commentedon Dec 4, 2021
shikingram commentedon Dec 8, 2021
我想问下,如何让他不list,或者我只关心我需要的数据,不需要全量数据,毕竟数据量太大,全量list占用cpu和内存会较高
zhangzerui20 commentedon Feb 23, 2022
我理解 reSync 机制有两个作用。
关于推荐怎么配置这个时间,我理解就是看你是用来保证第一点,还是第二点。如果是第一点,可以把时间配置的长一些,比如几个小时。如果是第二点,就是看你的系统要求,比如一分钟,几十秒,都是可以的,这里也要考虑 controller 的协调里做的是什么,会不会对外部系统造成很大压力。
loheagn commentedon Feb 26, 2023
关于第2点谈一下个人愚见哈。
我觉得楼主讨论的 resync 机制针对的应该是“系统内部”“错过”事件的情况,即,一个资源的变动事件没有被informer接收到,自然也就会被controller错过。resync的存在可以定期让用户自己实现的controller整个过一遍所有资源,从而弥补之前“错过”的事件(因为本质上我们并不是特别关心“发生了什么事件”,而更关心“现在资源的期望状态到底是啥”,而事件的接收更多的起到一个通知的作用,而每次执行controller的reconcile逻辑时都要获取一下资源的最新状态)。
而你这里第2点说的情况,应该是“系统外部”导致的不一致情况。这种应该在用户自定义的controller中的reconcile函数中处理,比如返回值指定requeue参数等。
虽然上述两种情况的结果是相同的(即,本质上都是定期重新reconcile一下资源),但动机不太一样。
callmevincent commentedon Feb 26, 2023
lightnine commentedon Mar 7, 2023
我看了client-go 1.26版本代码,代码如下(tools/cache/Reflector.go/Run):
这里的BackoffUntil应该会定期的执行ListAndWatch方法,看起来list函数会定期的从kube-apiserver获取数据
fighterhit commentedon Mar 7, 2023
多久一次?可能默认为了保证数据一致性?
novahe commentedon Apr 1, 2023
@lightnine
不会一直backoff,
r.ListAndWatch(stopCh)
函数是一个阻塞方法(里面是一个for循环),只会在由于错误导致函数退出for循环后才会重新执行callmevincent commentedon Apr 1, 2023
callmevincent commentedon May 2, 2023
ScXin commentedon Jun 30, 2023
I find the author's answer from the book-programming Kubernetes
callmevincent commentedon Jun 30, 2023
KingsonKai commentedon Oct 16, 2023
“让 Indexer 周期性地将缓存同步到队列中”,请问一下这里的意思是把local store的事件列表重新和DeltaFIFO中的事件进行对比吗?本地缓存是对象的值,而DeltaFIFO存储的是事件。我不太明白为什么二者存储的东西不一样,但是能同步?
callmevincent commentedon Oct 16, 2023