<p>I'm developing a Kubernetes controller. The desired state for this controller is captured in CRD-A and then it creates a deployment and statefulset to achieve the actual state. Currently I'm using server side apply to create/update these deployment and statefulsets.</p>
<p>The controller establishes watch on both CRD-A as well as deployments, statefulset. This to ensure that if there is a change in the deployment/statefulset, the reconcile() is notified and takes action to fix it. Currently the reconcile() always calls server side apply to create/update and this leads another watch event (resource version changes on every server side apply) resulting in repeated/infinite calls to reconcile()</p>
<p>One approach I've been thinking about is to leverage 'generation' on deployment/statefulset i.e. the controller will maintain a in-memory map of (k8s object -&gt; generation) and on reconcile() compare the value in this map to what is present in the indexed informer cache; do you see any concerns with this approach? And are there better alternatives to prevent repeated/infinite reconcile() calls?</p>

<p>Ideally, if the object you provide in the server side apply is not changed, the generation and the resourceVersion of the object should BOTH NOT be changed.</p>
<p>But sometimes that's not the case, see this github issue:<a href="https://github.com/kubernetes/kubernetes/issues/95460" rel="nofollow noreferrer">https://github.com/kubernetes/kubernetes/issues/95460</a></p>
<p>Fortunately, the generation always stays the same, so yes, you can leverage this field to avoid the reconcile dead loop, by adding a <code>GenerationChangedPredicate</code> filter to your controller, which will skip reconciling if the generation does not change, and it's often used in conjuction with the <code>LabelChangedPredicate</code>, which filters events when the object's labels does not change.</p>
<p>Here's how you will set up your controller with these two predicates:</p>
<pre><code>ctrl.NewControllerManagedBy(mgr).
    For(&amp;Object{}).
    Owns(&amp;appsv1.StatefulSet{}).
    Owns(&amp;appsv1.Deployment{}).
    // together with Server Side Apply
    // this predicates prevents meaningless reconcilations from being triggered
    WithEventFilter(predicate.Or(predicate.GenerationChangedPredicate{}, predicate.LabelChangedPredicate{})).
    Complete(r)
</code></pre>
