A controller is a loop that watches Kubernetes objects and reconciles their desired state (the spec) with the actual state (the cluster).
An Operator is a controller with operational knowledge baked in: it knows how to install, configure, scale, back up and upgrade an application — the jobs a human admin used to do by hand.
1desired state (CR) ──► reconcile loop ──► actual state (cluster)
Classic examples: etcd-operator, prometheus-operator.
Writing that reconcile loop by hand means a lot of boilerplate: CRDs, client code, RBAC, controller scaffolding, watch wiring. Operator SDK (from the Operator Framework) automates it:
operator-sdk init — scaffold the Go module, Makefile, Dockerfile and
config/ (CRDs, RBAC, manager, samples).operator-sdk create api — generate the CRD type + the controller that
watches it.Operators have 3 kinds: Go, Ansible, Helm.
| Kind | How the logic is written | Best when |
|---|---|---|
| Go | reconcile loop in Go (client-go) | complex, performant, custom logic |
| Ansible | roles/playbooks via ansible-runner | existing Ansible automation |
| Helm | wraps a Helm chart | deploy a known chart declaratively |
watches.yaml maps a given CR to the Ansible role/playbook that must run when
an object of that kind appears.
1# Init an Ansible project
2operator-sdk init --plugins=ansible --domain example.org --owner "Your name"
The command creates the following structure:
1netbox-operator
2├── Dockerfile
3├── Makefile
4├── PROJECT
5├── config
6│ ├── crd
7│ ├── default
8│ ├── manager
9│ ├── manifests
10│ ├── prometheus
11│ ├── rbac
12│ ├── samples
13│ ├── scorecard
14│ └── testing
15├── molecule
16│ ├── default
17│ └── kind
18├── playbooks
19│ └── install.yml
20├── requirements.yml
21├── roles
22│ └── deployment
23└── watches.yaml
1# Create the first API and generate the role
2operator-sdk create api --group app --version v1alpha1 --kind Deployment --generate-role