<p>I recently got started with building a <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/" rel="noreferrer">Kubernetes operator</a>. I'm using the <a href="https://github.com/fabric8io/kubernetes-client" rel="noreferrer">Fabric8 Java Kubernetes Client</a> but I think my question is more general and also applies to other programming languages and libraries.</p>
<p>When reading through blog posts, documentation or textbooks explaining the operator pattern, I found there seem to be two options to design an operator:</p>
<ol>
<li>Using an infinite reconcile loop, in which all corresponding Kubernetes objects are retrieved from the API and then some action is performed.</li>
<li>Using <a href="https://github.com/fabric8io/kubernetes-client/blob/master/doc/CHEATSHEET.md#sharedinformers" rel="noreferrer">informers</a>, which are called whenever an observed Kubernetes resource changes.</li>
</ol>
<p>However, I don't find any source discussion which option should be used in which case. Are there any best practices?</p>

<p>You should use both.</p>
<p>When using informers, it's possible that the handler gets the events out of order or even not at all. The former means the handler needs to define and reconcile state - this approach is referred to as <a href="http://venkateshabbarapu.blogspot.com/2013/03/edge-triggered-vs-level-triggered.html" rel="nofollow noreferrer">level-based, as opposed to edge-based</a>. The latter means reconciliation needs to be triggered on a regular interval to account for that possibility.</p>
<p>The way <a href="https://github.com/kubernetes-sigs/controller-runtime" rel="nofollow noreferrer">controller-runtime</a> does things, reconciliation is triggered by cluster events (using informers behind the scenes) related to the resources watched by the controller and on a timer. Also, by design, the event is not passed to the reconciler so that it is forced to define and act on a state.</p>
