How To Write a Reconciler Using k8s Controller-Runtime!

  • By Scott Rigby
  • Last update: Nov 23, 2022
  • Comments: 5

Tutorial: How To Write a Reconciler Using K8s Controller-Runtime!

Open in Gitpod

Git repo for talk at KubeCon NA 2022. Scott Rigby, Somtochi Onyekwere, Niki Manoledaki & Soulé Ba, Weaveworks; Amine Hilaly, Amazon Web Services.

This tutorial walks you through building your own controller using controller runtime, the set of common libraries on which core controllers are built. We'll use Kubebuilder, a framework for building APIs using custom resource definitions (CRDs). We'll also explain lesser-documented best practices and conventions for writing controllers that the community has developed through trial and error learning, through projects such as Flux and Cluster API.

How this repo is organized

Since we'll be building a controller with reconcilers, we'll need something to reconcile.

For this, we've built a simple API for submitting KubeCon CFP proposals, using CRDs.

Local Dev

Fork this repository, then clone it:

git clone [email protected]:<your username>/how-to-write-a-reconciler-using-k8s-controller-runtime.git


For the local dev setup, there are a few options:

  1. GitPod. GitPod is the preferred method, to ensure all users are running in the same environment regardless of their local machine OS. Please click on the button "Open in Gitpod" at the top of this README. Click through the default settings until you arrive at a page that looks like VSCode. Then, wait while the dependencies load (approximately ~6 minutes).

  2. Vagrant. As a backup, there is a Vagrantfile with instructions here.

  3. DIY. If you have all the required dependencies, you can go ahead and spinup a dev environment:

cd cfp
make docker-build
make setup-kind
make dev-deploy
export KUBECONFIG=/tmp/cfp-api-test-kubeconfig

Step-By-Step Guide

Once the dev env setup is ready, each step will use a git tag.

There are 7 steps, which match to 7 tags:

Screen Shot 2022-10-26 at 4 07 05 PM

To move from one tag to another, checkout the tag and create a new branch from it.

For example, move to the first step:

git checkout tags/s1 -b s1

Then, run the tests:

make test

And so on for each step!



  • 1

    Initialise CRUD Speaker and Proposal endpoints for `cfp` API

    Initial idea for a simple Go cfp API with CRUD Speaker and Proposal endpoints.

    Created a HTTP Mux server so that it's simpler to use than gRPC :)

    I wanted to check with you all that this setup is ok before adding logic/validation to the endpoints.

    Do you agree with writing the Speakers to data/speakers/[speaker-id].json and Proposals to data/proposals/[proposal-id].json? Ideas for better ways to do it are very welcome :D

  • 2

    Add the proposal reconciler

    Also updating the cfp-api proposal types to match the CRD api.

    @nikimanoledaki please push the last cfp-api to docker 🥺

    We would need a quick review here please, because have to test on a live cluster and prepare all step-by-step commits and slides/demo video

    Signed-off-by: Soule BA [email protected]

  • 3

    Speaker reconciler create test

    This sets up the speaker reconciler and the full create/update/delete cycle.

    We have done some manual testing with @somtochiama, and added the recipes to install a kind cluster and the speaker controller.

  • 4

    Add Speaker CRUD endpoint logic

    This PR adds logic for the Speaker CRUD endpoints.

    The Proposal ones should be very similar. :) I will add them after this has been approved to avoid double-work.

    Feel free to test things manually by following the instructions in the Readme!

  • 5

    cfp-app: Check if speaker is referenced by one or more proposals before allowing delete?

    Right now, you can delete the speaker without warning that it's currently referenced by one or more proposals. Should we allow that? If it doesn't matter for our workshop then let's leave it as is. But would validating this help us show something valuable in our controller behavior?

    (PS, I think this only matters for delete, not update. Users should continue to be able to update speaker details even when referenced in one or more proposals. I don't think it really matters that much for our workshop, but since we don't validate this now we may as well continue to allow that).