status value that reflects what the controller observes now. Events answer a related but distinct question: what did the controller just do? In this lesson we keep the existing status behavior and add Kubernetes events whenever the controller creates or updates the child Deployment.
Events are valuable because they appear in places Kubernetes users already inspect when debugging — for example, in kubectl describe output. If a WebApp was accepted by the API server but the controller changed something during reconciliation, an event explains the recent action without requiring users to tail controller logs.
Below we walk through the minimal changes required to emit informative, controller-scoped events from the reconciler.
The manager owns the event broadcaster. Reconciler instances should accept an
EventRecorder from the manager so events show which controller reported the action (don’t create your own recorder directly).Overview — what you will change
- Add the
recordpackage to imports and add aRecorderfield to the reconciler struct. - Obtain a named
EventRecorderfrom the manager incmd/main.goand pass it to the reconciler. - Replace the manual get-or-create
Deploymentflow withcontrollerutil.CreateOrUpdate, using the returned operation to emit events describing created/updated/unchanged state.
Imports and Reconciler fields
Consolidate imports and include the Client-Gorecord package and controller util helpers. The reconciler accepts an EventRecorder so events are linked to the controller that reported them.
Wiring the recorder in cmd/main.go
Obtain anEventRecorder from the manager and pass it into the reconciler when you register it. This makes events annotated with the controller name and ensures they’re visible in standard debugging interfaces.
Reconcile: use controllerutil.CreateOrUpdate and emit events
Usecontrollerutil.CreateOrUpdate to simplify the get-or-create logic for the Deployment. The function reads the live object into your pointer (if present), calls a mutate function to set desired state, and persists any changes. The returned op indicates whether the object was created, updated, or unchanged, which is ideal for emitting human-friendly events.
A concise, clarified Reconcile implementation:
Key points about the mutate function
- controller-runtime performs the read (populate
depfrom the API server) and the write (persist changes) around your mutate function. - The mutate function expresses which fields the operator owns and must maintain. In this example, labels, selector, and replicas are owned and synchronized from the WebApp spec.
- Use
CreationTimestamp.IsZero()to detect initial creation; it’s safe to copy the entire pod template only on first create. On updates, prefer changing only owned fields to avoid overwriting user-managed configuration.
Operation result → Event mapping
These events appear in
kubectl describe webapp <name> and similar tooling, helping users understand recent controller actions without reading logs.
Why events matter here
CreateOrUpdatereturns anopthat precisely indicates whether the Deployment was created, updated, or unchanged. Emitting events based onopprovides concise, human-readable context in the resource history.- Events surface in standard Kubernetes debugging workflows, giving operators immediate insight into controller activity (for example, when a WebApp triggers a Deployment update).
References
- kubectl describe — Documentation
- controller-runtime:
controllerutil.CreateOrUpdateandSetControllerReferencemethods - client-go:
tools/record.EventRecorderfor emitting events
Deployment while leaving other fields stable, and emits events to make those actions visible to cluster users.