How it works
The explanation, with examples you can run.
Step 1: a new type
apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: name: backups.example.comspec: group: example.com scope: Namespaced names: kind: Backup plural: backups singular: backup versions: - name: v1 served: true storage: true subresources: status: {} schema: openAPIV3Schema: type: object properties: spec: type: object required: [database, schedule] properties: database: { type: string } schedule: { type: string } keep: { type: integer, minimum: 1 } status: type: object properties: lastSuccess: { type: string, format: date-time }Once the CRD is applied, the API server serves /apis/example.com/v1/namespaces/*/backups. Objects are validated against the schema, stored in etcd, can be listed and watched, and are covered by RBAC like everything else:
apiVersion: example.com/v1kind: Backupmetadata: name: shop-nightlyspec: database: db schedule: "0 2 * * *" keep: 7kubectl get backupsStep 2: a controller
So far nothing happens: a custom resource is just data. The behaviour lives in a controller, usually a Deployment in the cluster built with a framework such as Kubebuilder or controller-runtime (Go), the Operator SDK, or kopf (Python). Its core is a reconcile function, called whenever a watched object changes and periodically:
reconcile(backup): desired = backup.spec # what the user asked for actual = look at the CronJob, the bucket, recent runs if the CronJob is missing or differs: create or update it delete backups beyond spec.keep write backup.status.lastSuccess # report what was observedGood reconcilers are idempotent (running twice changes nothing more), level-triggered (they act on the current state, not on a sequence of events), and set owner references on what they create, so deleting the Backup garbage-collects its CronJob. Finalizers let a controller clean up external resources, such as a cloud bucket, before the object disappears.
Operators you will meet
- cert-manager:
Certificateobjects become TLS secrets that renew themselves. - Database operators such as CloudNativePG or the operators for MySQL, Kafka (Strimzi) and Redis: a
Clusterobject becomes StatefulSets, Services, replication, failover and backups. - Argo CD and Flux:
ApplicationorKustomizationobjects keep the cluster in sync with git. - Prometheus Operator:
ServiceMonitorobjects become scrape configuration. - Gateway API itself ships as CRDs with controllers from each implementation.
Judging an operator
An operator is privileged automation running inside your cluster, often with cluster-wide rights. Before adopting one, check that it is maintained and widely used, what RBAC it requests, how it upgrades its own CRDs, and what happens to your data if you uninstall it. When writing one, keep the scope small: if a Helm chart or a CronJob does the job, you may not need a controller at all.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.