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 ?
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