Skip to main content

Kubernetes Operator

KubernetesOperator reconciles models stored in a Kubernetes store, like a Kubernetes controller: when an object's spec changes, it calls its reconcile() method and reports the result in its status.

Model​

import { UuidModel } from "@webda/models";
import type { Reconcilable } from "@webda/kubernetes";

export class Tenant extends UuidModel implements Reconcilable {
name!: string;
ready?: boolean;

async reconcile() {
// e.g. provision a database, a namespace...
await this.patch({ ready: true });
// optional: reconcile again later
return { requeueAfter: 60_000 };
}

async finalize() {
// clean up before the object is deleted (needs the finalizer parameter)
}
}

The CustomResourceDefinition of a model with a reconcile method gets a status subresource holding observedGeneration and conditions.

Configuration​

webda.config.json
{
"services": {
"tenantStore": {
"type": "Webda/KubernetesStore",
"group": "myapp.example.com",
"models": ["MyApp/Tenant"],
"statusFields": { "MyApp/Tenant": ["ready"] }
},
"tenantOperator": {
"type": "Webda/KubernetesOperator",
"models": ["MyApp/Tenant"],
"finalizer": "myapp.example.com/finalizer"
}
}
}

Run it with webda kubernetes operator, or set autoStart: true to start it with the application.

ParameterDefaultDescription
modelsrequiredModels to reconcile, stored in a KubernetesStore
concurrency1Objects of a model reconciled at the same time
resyncPeriod300000Milliseconds between two reconciliations of every object
maxBackoff300000Maximum milliseconds before retrying a failed object
finalizernoneFinalizer added to the objects: finalize() runs before deletion
leaderElectiontrueOnly the replica holding the Lease reconciles
leaseNamewebda-operator-<service name>Name of the coordination.k8s.io Lease
leaseNamespacenamespace of the first storeNamespace of the Lease
leaseDuration, leaseRetryPeriod15000, 5000Validity of the Lease and period of its renewal
autoStartfalseStart at init
maxRetries5Attempts of a status or finalizer write on conflicts

Behavior​

  • reconcile() runs when an object is added or its spec changes (metadata.generation), on resync, after a failure (exponential backoff from one second to maxBackoff) and after the requeueAfter it returned.
  • Status-only changes, the operator's own status writes included, are not reconciled: a reconcile() updating the status fields of its object does not loop. A spec change made by reconcile() is reconciled again.
  • The status gets observedGeneration and a Ready condition: True with reason Reconciled, or False with reason ReconcileError and the error message. After a restart, objects reconciled successfully at their generation are not reconciled again until the next resync.
  • With leader election, a replica that cannot renew the Lease stops reconciling at once; the Lease is released on stop so another replica takes over without waiting for its expiry.
  • Metrics: reconcile_total{model,result}, reconcile_duration_seconds{model}, queue_depth{model}.

webda kubernetes rbac export writes the rights it needs: on the resources and their status (from the stores) and on the Lease.