k8s-operator-node icon indicating copy to clipboard operation
k8s-operator-node copied to clipboard

[Info/Feature] Watcher vs Informer

Open thejasbabu opened this issue 4 years ago • 4 comments

Hi,

I have noticed that the watchResource does not contain any cache which helps while re-listing and re-watching k8s resources. This functionality already exists in the underlying kubernetes@client-node but was surprised to see not being used in this project.

Any idea as to why?

thejasbabu avatar Dec 14 '20 07:12 thejasbabu

Was simply not aware of the informer existing 😉 I see it uses an internal cache, so it might indeed be interesting to switch to this instead.

dot-i avatar Dec 14 '20 07:12 dot-i

@thejasbabu Can you point me to a working example that uses Informer to watch custom resources?

I'm getting this error:

[DEBUG] Reconciler - init: Watching group 'mk8.farberg.de', version 'v1', plural 'microkeights'
./node_modules/@kubernetes/client-node/dist/cache.js:77
            const list = result.body;
                                ^

TypeError: Cannot read property 'body' of undefined
    at ListWatch.<anonymous> (./node_modules/@kubernetes/client-node/dist/cache.js:77:33)
    at Generator.next (<anonymous>)
    at fulfilled (./node_modules/tslib/tslib.js:112:62)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)

when using this code:

async init() {
  //Create K8s Client
  this.logger.debug(`init: Creating kubeconfig`)
  this.kubeConfig = new k8s.KubeConfig();
  this.kubeConfig.loadFromDefault();
  this.k8sApi = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
  this.customObjectsApi = this.kubeConfig.makeApiClient(k8s.CustomObjectsApi)
  
  // Register custom resource definition
  // registerCustomResourceDefinition @ https://github.com/dot-i/k8s-operator-node/blob/master/src/operator.ts
  this.logger.debug(`init: Registering CRD from file ${this.options.crdFile}`)
  const { group, versions, plural } = await this.registerCustomResourceDefinition(this.options.crdFile);
  this.crdGroup = group;
  this.crdVersions = versions;
  this.crdPlural = plural;
  
  console.log("XXX", await this.customObjectsApi.listClusterCustomObject(this.crdGroup, versions[0].name, this.crdPlural))
  
  this.logger.debug(`init: Watching group '${this.crdGroup}', version '${this.crdVersions[0].name}', plural '${this.crdPlural}'`)
  
  const informer = k8s.makeInformer(this.kubeConfig, `/apis/${this.crdGroup}/${versions[0].name}/${this.crdPlural}`, () => {
     console.log("Called")
  })
}

pfisterer avatar Mar 05 '21 11:03 pfisterer

@pfisterer A sample informer code for a CRD Foo

const kubeConfig = new k8s.KubeConfig();
const credentials = fs.readFileSync(path.join(__dirname, 'kubeconfig'), 'utf8');
kubeConfig.loadFromString(credentials);
const k8sApi = kubeConfig.makeApiClient(k8s.CustomObjectsApi);

const apiGroup = 'samplecontroller.k8s.io';
const apiVersion = 'v1alpha1';
const namespace = 'foo-namespace';
const plural = 'foos';

async function start() {
  let apiPaths = `/apis/${apiGroup}/${apiVersion}/namespaces/${namespace}/${plural}`;
  const listFn = () => {
    return k8sApi.listNamespacedCustomObject(
      apiGroup,
      apiVersion,
      namespace,
      plural
    );
  }
  const informer = k8s.makeInformer(kubeConfig, apiPaths, listFn);
  return informer.start()
}

thejasbabu avatar Apr 02 '21 07:04 thejasbabu

@thejasbabu Great, thanks a lot!

pfisterer avatar Apr 14 '21 07:04 pfisterer