In this lesson, you will learn how to use predicates to filter incoming cluster events, preventing your controller from performing unnecessary work and significantly improving operator performance.
The Problem with Constant Reconciliation
When you build an operator, the Reconcile loop is triggered by events on your watched resources. By default, every change—updating a label, modifying a status field, or changing a spec annotation—triggers your reconciliation logic. In large clusters, this results in "reconciliation storms," where your controller wakes up to process objects that haven’t actually changed in a way that requires action, wasting CPU and memory.
Introducing Predicates
Predicates act as a traffic filter for your controller’s event queue. Instead of reacting to every single Update, Create, or Delete event, you define logic that evaluates the event before it is added to the reconcile queue. If the event does not meet your criteria, it is dropped silently, and your controller remains idle.
For example, if your controller only cares about changes to the spec of your Custom Resource, you can use the ResourceVersionChangedPredicate or a custom predicate to ignore updates where only the metadata or status changed.
Implementing a Basic Predicate
In your controller setup (typically found in your main.go or controller.go), you attach a WithEventFilter to your Watches configuration:
err = ctrl.NewControllerManagedBy(mgr).
For(&myv1.MyResource{}).
WithEventFilter(predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
// Only reconcile if the Spec has actually changed
return e.ObjectOld.GetGeneration() != e.ObjectNew.GetGeneration()
},
}).
Complete(r)
In this example, the controller checks GetGeneration(). Kubernetes automatically increments the generation number when the spec is modified, but not when the status or labels change. By using this predicate, you ensure your expensive reconciliation logic only runs when the user-defined configuration changes.
By filtering at the source, you reduce the load on your API server and ensure your controller’s resources are reserved for meaningful state changes.
Key Takeaway: Predicates allow you to filter cluster events before they trigger your reconcile loop, ensuring your operator only executes when it is truly necessary.