In this lesson, you will learn how to write the core Reconcile function that empowers your custom controller to bridge the gap between a user's declared intent and the actual state of your cluster.
The Heart of the Controller
In Kubernetes, a controller operates on a control loop pattern: Observe, Diff, Act. The Reconcile function is the engine room of this loop. When a custom resource is created, updated, or deleted, the Kubernetes API server places an event in a work queue, triggering your Reconcile function to run.
Your goal is to write logic that is idempotent—meaning it can be run multiple times safely without unintended side effects.
Anatomy of the Reconciliation Loop
Inside your Reconcile function, you typically follow these three steps:
- Fetch the Resource: Retrieve the Custom Resource (CR) from the cluster using its name and namespace. If it’s not found, assume it was deleted and perform cleanup.
- Observe Current State: Inspect the environment (e.g., check if a Deployment or Service associated with your CR already exists).
- Sync State: Compare the "desired state" (defined in your CR spec) with the "actual state" of the cluster. If they don’t match, execute the necessary calls to
Create,Update, orDeleteresources.
func (r *MyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// 1. Fetch the CR
myCR := &v1alpha1.MyCustomResource{}
err := r.Get(ctx, req.NamespacedName, myCR)
if err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// 2. Observe & 3. Sync
// Ensure a Deployment exists matching the spec
deployment := &appsv1.Deployment{}
err = r.Get(ctx, types.NamespacedName{Name: myCR.Name, Namespace: myCR.Namespace}, deployment)
if errors.IsNotFound(err) {
// Create the resource if it's missing
return ctrl.Result{}, r.Create(ctx, desiredDeployment(myCR))
}
// Update logic goes here if the spec changed...
return ctrl.Result{}, nil
}
Handling Returns
Note that Reconcile returns a ctrl.Result and an error. Returning nil for the error tells Kubernetes the resource is synchronized. If you return an error, the controller will automatically requeue the event to try again later, ensuring your system remains self-healing even if an API call temporarily fails.
Key Takeaway: The Reconcile function must be idempotent, focusing on bringing the cluster's state into alignment with the resource spec regardless of how many times it is executed.