Kubernetes client-go: watch.Interface vs. cache.NewInformer vs. cache.NewSharedIndexInformer?

12/31/2019

I need my Go app to monitor some resources in a Kubernetes cluster and react to their changes. Based on numerous articles and examples, I seem to have found a few ways to do it; however, I'm relatively new to Kubernetes, and they're described in terms much too complex to me, such that I'm still unable to grasp the difference between them — and thus, to know which one to use, so that I don't get some unexpected behaviors... Specifically:

  1. watch.Interface.ResultChan() — (acquired through e.g. rest.Request.Watch()) — this already seems to let me react to changes happening to a resource, by providing Added/Modified/Deleted events;
  2. cache.NewInformer() — when I implement a cache.ResourceEventHandler, I can pass it as last argument in:

    cache.NewInformer(
            cache.NewListWatchFromClient(clientset.Batch().RESTClient(), "jobs", ...),
            &batchv1.Job{},
            0,
            myHandler)
    

    — then, the myHandler object will receive OnAdd()/OnUpdate()/OnDelete() calls.

    To me, this seems more or less equivalent to the ResultChan I got in (1.) above; one difference is that apparently now I get the "before" state of the resource as a bonus, whereas with ResultChan I would only get its "after" state.

    Also, IIUC, this is actually somehow built on the watch.Interface mentioned above (through NewListWatchFromClient) — so I guess it brings some value over it, and/or fixes some (what?) deficiencies of a raw watch.Interface?

  3. cache.NewSharedInformer() and cache.NewSharedIndexInformer() — (uh wow, now those are a mouthful...) I tried to dig through the godocs, but I feel completely overloaded with terminology I don't understand, such that I don't seem to be able to grasp the subtle (?) differences between a "regular" NewInformer vs. NewSharedInformer vs. NewSharedIndexInformer...

Could someone please help me understand the differences between above APIs in the Kubernetes client-go package?

-- akavel
kubernetes
kubernetes-go-client

1 Answer

12/31/2019

These methods differ in the level of abstraction. If a higher level abstraction fits your need, you should use it, as many lower level problems is solved for you.

Informers is a higher level of abstraction than watch that also include listers. In most use cases you should use any kind of Informer instead of lower level abstraction. An Informer internally consists of a watcher, a lister and an in-memory cache.

SharedInformers share the connection with the API server and other resources between your informers.

SharedIndexInformers add an index to your data cache, in case you work with a larger dataset.

It is recommended to use SharedInformers instead of the lower level abstractions. Instantiate new SharedInformes from the same SharedInformerFactory. Theres is an example in Kubernetes Handbook example

informerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)

podInformer := informerFactory.Core().V1().Pods()
serviceInformer := informerFactory.Core().V1().Services()

podInformer.Informer().AddEventHandler(
    // add your event handling 
)

// add event handling for serviceInformer

informerFactory.Start(wait.NeverStop)
informerFactory.WaitForCacheSync(wait.NeverStop)
-- Jonas
Source: StackOverflow