javakubernetesjava-8java-client

Kubernetes SharedInformer usage and definition


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 ?


Solution

  • 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