Example Controller
A ReplicaSet controller built with controller-runtime v0.25.1. Run commands from the repository root with a kubeconfig and permissions to read ReplicaSets/Pods and patch ReplicaSets.
Example
-
Run example controller.
go run ./contents/kubernetes-operator/controller-runtime/example-controllerWhat this controller does:
- Read the ReplicaSet
- Read the Pods
- Set a Label on the ReplicaSet with the Pod count.
-
Create Deployment
kubectl create deploy test --replicas=3 --image=nginxThe controller counts Pods that both match the ReplicaSet selector and have its controller owner UID. It supports matchExpressions, initializes missing labels, and patches only when pod-count changes. A merge patch avoids overwriting unrelated fields; other API errors still trigger retries.
-
Check
pod-count=3labels added to the ReplicaSetkubectl get rs -o jsonpath='{.items[].metadata.labels}' {"app":"test","pod-count":"3","pod-template-hash":"8499f4f74"} -
Clean up
kubectl delete deploy test
Implementation and event flow
For(&appsv1.ReplicaSet{}) maps ReplicaSet events to its own key. Owns(&corev1.Pod{}) maps Pod ownerReferences to the controlling ReplicaSet. Manager supplies a cache-backed Client explicitly to ReplicaSetReconciler.
On each request:
- Get the ReplicaSet; ignore NotFound because deletion leaves nothing to label.
- Convert Spec.Selector with LabelSelectorAsSelector, including matchExpressions.
- List matching Pods in the request namespace.
- Count only Pods whose controller owner UID matches this ReplicaSet. Labels alone do not prove ownership.
- Return immediately if pod-count already matches.
- DeepCopy the original, allocate Labels if nil, and patch with client.MergeFrom(original).
The write produces another watch event; the no-op check makes that subsequent reconciliation settle. Reads can lag writes because the Client reads from the cache. This sample counts existing owned Pods, not only Ready Pods, and does not create or delete Pods itself.
Tests
go test ./contents/kubernetes-operator/controller-runtime/example-controller
The fake-client regression tests cover missing ReplicaSets, nil labels, selector expressions, owner filtering, namespace filtering, and avoiding unchanged writes. They do not substitute for a running-cluster check of informer delivery or API-server admission.