0

下面是我的片段

factory := informers.NewFilteredSharedInformerFactory(clientset, 0, "", func(o *metaV1.ListOptions) {
    o.LabelSelector = "node-role.kubernetes.io/master="
})

nodeInformer := factory.Core().V1().Nodes().Informer()

i.lister = factory.Core().V1().Nodes().Lister()

nodeInformer.AddEventHandler(
    cache.ResourceEventHandlerFuncs{
        AddFunc: func(obj interface{}) {
            i.updateIPs()
        },
        UpdateFunc: func(oldobj, newObj interface{}) {
            i.updateIPs()
        },
        DeleteFunc: func(obj interface{}) {
            i.updateIPs()
        },
    })

factory.Start(ctx.Done())

if !cache.WaitForCacheSync(ctx.Done(), nodeInformer.HasSynced) {
    runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync"))
    return
}

完整代码位于:https ://github.com/tweakmy/fotofona/blob/master/nodeinformer.go

这是我运行单元测试时的结果:

   $ go test -v -run TestInformer
   === RUN   TestInformer
   Update ip host [10.0.0.1]
   cache is synced
   --- PASS: TestInformer (3.10s)

这是预期的行为吗?如何在缓存同步后将其列出并在缓存同步后对事件处理程序做出反应。

4

1 回答 1

0

您所看到的是标准行为。当您等待同步发生时,会收到通知并执行相应的通知处理程序。

您的代码与大多数使用通知 API 的代码不同,因为处理直接在通知处理程序中进行。这听起来像是基于边缘的行为,而 Kubernetes 鼓励基于级别的行为。

编写 Kubernetes 控制器时的典型模式(这是你应该做的)是让通知处理程序什么都不做,只是将一个对工作队列中通知对象的引用(通常是命名空间的名称)排入队列,并拥有一个工作池(如果您正在使用 go) 提取此类引用,使用它们从 Informer 的缓存中检索整个对象,然后进行实际处理。所以通常做的是在启动工作人员之前同步 Informers 的缓存,这样工作人员在缓存同步之前不会开始处理。明确地说,updateIPs()不应在通知处理程序代码中执行,而应在工人主体中执行。

此页面上,有一个常用模式的独立示例。更准确地说,请参阅此代码以获取典型通知处理程序的示例,以及此代码以获取有关如何在启动工作人员时完成同步的示例。

于 2019-04-10T12:53:50.120 回答