3

I have been trying to watch some resources in my K8s cluster and after reading some blogs about watch vs informers, i've decided to go with Informers.

I came across this example of how to use one: https://github.com/Netflix-Skunkworks/kubernetes-client-java/blob/master/examples/src/main/java/io/kubernetes/client/examples/InformerExample.java

In the example, I see that the SharedIndexInformer is defined as such:

        factory.sharedIndexInformerFor(
            (CallGeneratorParams params) -> {
              return coreV1Api.listNodeCall(
                  null,
                  null,
                  null,
                  null,
                  null,
                  params.resourceVersion,
                  params.timeoutSeconds,
                  params.watch,
                  null,
                  null);
            },
            V1Node.class,
            V1NodeList.class);

Based on my understanding of how lambdas are written, this basically says that we're creating a sharedIndexInformer from the factory by passing it a param Call (returned by coreV1Api.listNodeCall).

The Call object is created by this dynamic method which takes in a CallGeneratorParams argument.

I do not seem to understand how and where this argument is passed in from in the case of a SharedInformerFactory. It's very evident that some fields within the params variable is being used in building the listNodeCall but where and how is this object constructed ?

kambamsu
  • 561
  • 2
  • 9
  • 21

2 Answers2

2

Well it's a ride down a rabbit hole.

I suggest to keep the diagrams from the official docs open in separate tab/window in order to appreciate the whole picture better.

In order to understand this, you would have to look at the implementation of the SharedInformerFactory, especially the sharedIndexInformerFor call.

Notice how the lambda is just passed further down to construct a new ListWatcher instance (method at line 194), which is then passed into a new DefaultSharedIndexInformer instance (statement at line 144).

So now we have an instance of a SharedIndexInformer that passes the ListerWatcher yet further down to its Controller (constructor line 99). Now the Controller is started when the Informer itself runs (see the run() method).

To make it even more complex, the Controller uses a Reflector for .. stuff. A Reflector according to the reflector.go

Reflector watches a specified resource and causes all changes to be reflected in the given store.

So its job is to call list and watch until it is told to stop. So when the Controller starts, it also schedules its Reflector to run periodically

At last. When the Reflector runs, it calls the list method, which .. drum roll .. executes the lambda you were asking about. And the param variable in the lambda is .. another drum roll .. created in the Reflector here

Pretty neat, wouldn't you say?

Let me know, if you need further help/clarification.

Cheers

iska
  • 2,208
  • 1
  • 18
  • 37
1

Welcome to the world of functional style where a piece of code is declared/passed at one place but it's execution happens somewhere else. Easily a debugging nightmare.

I do not seem to understand how and where this argument is passed in from in the case of a SharedInformerFactory. It's very evident that some fields within the params variable is being used in building the listNodeCall but where and how is this object constructed ?

In an IDE (Eclipse) - I simply tried finding where the public constructor of CallGeneratorParams is being called and it directly points me to ReflectorRunnable run method which in-turn is being called from the Controller. From there on you can follow the rabbit-hole ( as very well put by @isika)

ReflectorRunnable

ReflectorRunnable

Controller

enter image description here

SharedInformerFactory - the actual code which takes these params and does the work is below. However it's just place of definition - the time of execution is when the ReflectorRunner run method executes ( in the first image).

enter image description here

Shailendra
  • 8,874
  • 2
  • 28
  • 37