TeeTee
TeeTee

Reputation: 147

Create infinite Reconciliation loop for a deployment with Kubebuilder

I am creating a controller that will watch a dpeloyment and its pods on a cluster. The watched deployment is not a custom resource. I have built out the controller with kubebuilder. For the purpose of this, the deployment is called "foo" in the namespace "bar" I have set up the SetupWithManager function to look like this

func (r *DeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error {
    namespace := "foo"
    deployment:= "bar"
    return ctrl.NewControllerManagedBy(mgr).
        Owns(&appsv1.Deployment{}).
        For(&appsv1.Deployment{}, builder.WithPredicates(predicate.Funcs{
            CreateFunc: func(e event.CreateEvent) bool {
                //fmt.Println(e)
                return e.Object.GetNamespace() == namespace && e.Object.GetName() == deployment
            },
            UpdateFunc: func(e event.UpdateEvent) bool {
                //fmt.Println(e)
                return e.ObjectNew.GetNamespace() == namespace && e.ObjectNew.GetName() == deployment
            },
            DeleteFunc: func(e event.DeleteEvent) bool {
                //fmt.Println(e)
                return e.Object.GetNamespace() == namespace && e.Object.GetName() == deployment
            },
            GenericFunc: func(e event.GenericEvent) bool {
                return e.Object.GetNamespace() == namespace && e.Object.GetName() == deployment
            },
        })).
        Complete(r)

This causes the reconcile loop to only work when events occur on "foo" and "bar". If my reconcile loop doesn't update anything within the deployment object, the loop stops running. I want the loop to run forever even if the controller considers the state to be "reconciled". Right now I've found a way around this problem by adding the following code to my reconcile loop.

...
    if val, ok := testdeploy.Labels["foo"]; ok && val == "bar" {
        testdeploy.Labels["foo"] = "blah"
    } else {
        testdeploy.Labels["foo"] = "bar"
    }

    err = r.Update(ctx, testdeploy)
    if err != nil {
        return ctrl.Result{}, err
    }

This causes the reconcile loop to loop infinitely because the deployment is always updating.

I need the reconcile loop to constantly loop without stopping. Is there a better way to get around this issue or does this go against the design of what a controller should be?

Upvotes: 0

Views: 533

Answers (1)

Kubus
Kubus

Reputation: 777

To schedule periodic re-queuing, use the RequeueAfter attribute within the ctrl.Result object that you're returning from your reconcile method:

return ctrl.Result{RequeueAfter: 5 * time.Minute}, nil

It will requeue the request after the specified delay. This approach is appropriate for actions that depend on external conditions that may change over time.

Upvotes: 0

Related Questions