Building blocks of Custom Kubernetes Operators and Controllers

Sitesh Pattanaik

2026/10/04

what is controller-runtime?

controller-runtime is official set of Go libraries used to build custom operators and controllers in kubernetes.

How does a sample custom controller looks like in kubernetes

# main.go

package main

import(
 "context"
 "sigs.k8s.io/controller-runtime/pkg/client"
 ctrl "sigs.k8s.io/controller-runtime/pkg/manager"
)

func main() {
  cfg := ctrl.GetConfigOrDie()
  mgr, err := ctrl.NewManager(cfg, ctrl.Options{})
  handleErr(err)
  
  r := &PodCounter{Client: mgr.GetClient()}
  
  err = r.SetupWithManager(mgr)
  handleErr(err)
  
  err = mgr.Start(ctrl.SetupSignalHandler())
  handleErr(err)
  
}

func (r *PodCounter) SetupWithManager(mgr ctrl.Manager) error {
  return ctrl.NewControllerManagedBy(&mgr).
           For(&corev1.Pod{}).
           Complete(r)
}

func (r *PodCounter) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
  podList := &corev1.PodList{}
  if err := r.List(ctx, podList); err != nil {
    return ctrl.Result{}, err
  }
  log.Printf("Number of pods: %d", len(podList.Items))
  return ctrl.Result{}, nil
}

there are way too many information hidden in here and for us to distill this completely, lets understand each and everything in a bit more details.

config

It’s a *rest.Config from k8s.io/client-go/rest. It holds everything that is needed to talk to the kube api-server.

This part gets the config in the following order

client.Client

The PodCounter{} struct is just a holder which if needs to be a reconciler has to implement the Reconcile(ctx, Request) as part of the interface contract.

Embedding client.Client into the struct is an approach where we inject a reference to the client of the manager that we create as part ctrl.NewManager.

things NewManager creates

NewManager builds a cluster object that wires several pieces from the rest.Config

What is an Informer?

Informer is a local cache kept in sync with the kube api-server, plus an event notification system on top.

It has these following components

How does SetupWithManager works?

func (r *PodCounter) SetupWithManager(mgr ctrl.Manager) error {
  return ctrl.NewControllerManagedBy(&mgr).
           For(&corev1.Pod{}).
           Complete(r)
}

How we can watch multiple things?