Kubernetes Informer基本原理(4)
Kubernetes
(2)listener pop 方法里会监听 p.addCh,通过 nextCh = p.nextCh 将 addCh 将事件传递给 p.nextCh
(3)listener run 方法里会监听 p.nextCh,收到信号之后,判断是属于什么类型的方法,并且执行前面注册的 Handler
所以后面需要关注当资源对象发生变更时,是如何将变更信号给 p.addCh,进一步触发回调函数的
3.4、Start all informers
通过 sharedInformers.Start(stopCh)启动所有的 informer,代码如下:
// Start initializes all requested informers.
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
for informerType, informer := range f.informers {
if !f.startedInformers[informerType] {
go informer.Run(stopCh)
f.startedInformers[informerType] = true
}
}
}
我们的例子中其实就只启动了 PodInformer,接下来看到 podInformer 的 Run 方法做了什么
### go informer.Run(stopCh):
func (s *sharedIndexInformer) Run(stopCh <-chan struct{}){
defer utilruntime.HandleCrash()
fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{ // Deltafifo
KnownObjects: s.indexer,
EmitDeltaTypeReplaced: true,
})
cfg := &Config{
Queue: fifo, // Deltafifo
ListerWatcher: s.listerWatcher, // listerWatcher
ObjectType: s.objectType,
FullResyncPeriod: s.resyncCheckPeriod,
RetryOnError: false,
ShouldResync: s.processor.shouldResync,
// HandleDeltas, added to process, and done in processloop
Process: s.HandleDeltas,
WatchErrorHandler: s.watchErrorHandler,
}
func() {
...
s.controller = New(cfg)
...
}
s.controller.Run(stopCh)
}
### s.controller.Run(stopCh)
func (c *controller) Run(stopCh <-chan struct{}) {
r := NewReflector(
c.config.ListerWatcher,
c.config.ObjectType,
c.config.Queue,
c.config.FullResyncPeriod,
)
c.reflector = r
// Run reflector
wg.StartWithChannel(stopCh, r.Run)
// Run processLoop, pop from deltafifo and do ProcessFunc,
// ProcessFunc is the s.HandleDeltas before
wait.Until(c.processLoop, time.Second, stopCh)
}
可以看到上面的逻辑首先生成一个 DeltaFifo,然后接下来的逻辑分为两块,生产和消费:
(1)生产—r.Run:
主要的逻辑就是利用 list and watch 将资源对象包括操作类型压入队列 DeltaFifo
#### r.Run:
func (r *Reflector) Run(stopCh <-chan struct{}) {
// 执行listAndWatch
if err := r.ListAndWatch(stopCh);
}
// 执行ListAndWatch流程
func (r *Reflector)ListAndWatch(stopCh <-chan struct{}) error{
// 1、list:
// (1)、list pods, 实际调用的是podInformer里的ListFunc方法,
// client.CoreV1().Pods(namespace).List(context.TODO(), options)
r.listerWatcher.List(opts)
// (2)、获取资源版本号,用于watch
resourceVersion = listMetaInterface.GetResourceVersion()
// (3)、数据转换,转换成列表
items, err := meta.ExtractList(list)
// (4)、将资源列表中的资源对象和版本号存储到DeltaFifo中
r.syncWith(items, resourceVersion);
// 2、watch,无限循环去watch apiserver,当watch到事件的时候,执行watchHandler将event事件压入fifo
for {
// (1)、watch pods, 实际调用的是podInformer里的WatchFunc方法,
// client.CoreV1().Pods(namespace).Watch(context.TODO(), options)
w, err := r.listerWatcher.Watch(options)
// (2)、watchHandler
// watchHandler watches pod,更新DeltaFifo信息,并且更新resourceVersion
if err := r.watchHandler(start, w, &resourceVersion, resyncerrc, stopCh);
}
}
### r.watchHandler
// watchHandler watches w and keeps *resourceVersion up to date.
func (r *Reflector) watchHandler(start time.Time, w watch.Interface, resourceVersion *string, errc chan error, stopCh <-chan struct{}) error {
...
loop:
for {
select {
case event, ok := <-w.ResultChan():
newResourceVersion := meta.GetResourceVersion()
switch event.Type {
case watch.Added:
err := r.store.Add(event.Object) // Add event to srore, store的具体方法在fifo中
if err != nil {
utilruntime.HandleError(fmt.Errorf("%s: unable to add watch event object (%#v) to store: %v", r.name, event.Object, err))
}
...
}
*resourceVersion = newResourceVersion
r.setLastSyncResourceVersion(newResourceVersion)
eventCount++
}
}
...
}
### r.store.Add:
## 即为deltaFifo的add方法:
func (f *DeltaFIFO) Add(obj interface{}) error {
...
return f.queueActionLocked(Added, obj)
...
}
func (f *DeltaFIFO) queueActionLocked(actionType DeltaType, obj interface{}) error {
id, err := f.KeyOf(obj)
if err != nil {
return KeyError{obj, err}
}
newDeltas := append(f.items[id], Delta{actionType, obj})
newDeltas = dedupDeltas(newDeltas)
if len(newDeltas) > 0 {
if _, exists := f.items[id]; !exists {
f.queue = append(f.queue, id)
}
f.items[id] = newDeltas
f.cond.Broadcast() // 通知所有阻塞住的消费者
}
...
return nil
}
相关阅读
-
redis哈希槽为什么是16384
您可能不了解redis哈希槽为什么是16384的IT知识,具体内容如下: 我们知道一致性哈希算法是对2的32次方取模,而哈希槽是对2的14次方取模 ✏️ Redis作者认为这样做不太值得;并且一般情况下一
-
怎样免费ppt模板制作 免费的ppt模板网站推荐
小编带来的是怎样免费ppt模板制作和免费的ppt模板网站推荐的内容,接下来一起来看看吧。 年末了,又是一个做年终总结的时候,你的年终报告需要用到PPT吗?最近我的同事一直在问我:你的
-
宣传网站怎么做才好 宣传网页制作的方法
文章摘要:宣传网站怎么做才好和宣传网页制作的方法的方法内容,接下来IT袋带大家一起了解。 企业网站是企业进行网络推广的关键所在,那么如何才能让网站获取更大流量,从而提高品牌
-
CSS简介及其作用—样式表的基础知识解析 CSS是什么
如果想了解CSS简介及其作用—样式表的基础知识解析的相关介绍,接下来就是全面介绍。 1. CSS概述 CSS,全称Cascading Style Sheets(层叠样式表),是一种用于描述HTML或XML文档呈现样式的样式表语


