Skip to content

Kubebuilder + Timoni + Bazel Kubernetes Operator

Published:

Description

A simple Kubernetes Operator (built with Kubebuilder) that reconciles a CronJob custom resource (batch.martishin.com/v1, Kind=CronJob).
For each CronJob, the controller ensures Kubernetes Jobs are created and executed on schedule, similar to the built-in CronJob controller.

The project is built with Bazel and packaged/deployed with Timoni.
Kubebuilder’s kustomize manifests remain for development/CI, but Timoni is authoritative for installs and upgrades.

Source code is available on GitHub.

Table of contents

Open Table of contents

Description

Goal of the controller
The controller watches CronJob resources and reconciles the desired state:

This demonstrates a production-like operator pattern.

Prerequisites

Optional:

Build & Release (Bazel + Timoni)

The Timoni bundle lives at:

timoni/bundles/operator-stack.cue

It includes three instances:

  1. crds – the CronJob CRD
  2. operator – controller (RBAC, SA, Deployment, metrics)
  3. sample – a sample CronJob resource

Quick start on Kind (local)

# 1) (Optional) Create a Kind cluster
kind create cluster --name mycluster

# 2) Build controller image with Bazel
bazel build //:controller_image

# 3) Load the image into Kind
bazel run //:controller_image_load
docker tag kubebuilder/cronjob-controller:dev controller:dev
kind load docker-image controller:dev --name mycluster

# 4) Point Timoni bundle to that image
make bundle-set-image IMG=controller:dev

# 5) Apply with Timoni
make bundle-apply

Preview, apply, status

# Preview manifests
make bundle-build | less

# Diff vs live cluster
make bundle-diff

# Apply & wait
make bundle-apply

# Status
make bundle-status
kubectl -n cronjob-operator-system get deploy,pods

Test reconciliation

# Inspect the sample CronJob
kubectl -n default get cronjob.batch.martishin.com cronjob-sample -o yaml

# Watch Jobs being created
kubectl -n default get jobs -w

# Inspect sample pod logs
kubectl -n default get pods

Uninstall

make bundle-delete

Local development

Run the controller locally

make run

Unit/Envtest & e2e

make test
make test-e2e

Project structure

bazel-kubebuilder-timoni-k8s-cronjob-operator/
β”œβ”€β”€ api/v1/                        # CRD Go types
β”œβ”€β”€ cmd/main.go                    # Controller entrypoint
β”œβ”€β”€ internal/controller/           # Reconciler logic
β”œβ”€β”€ timoni/
β”‚   β”œβ”€β”€ bundles/operator-stack.cue
β”‚   └── modules/
β”‚       β”œβ”€β”€ cronjob-operator-crds/ # CRD instance
β”‚       β”œβ”€β”€ cronjob-operator/      # Operator instance
β”‚       └── cronjob-sample/        # Sample CronJob
β”œβ”€β”€ BUILD.bazel, MODULE.bazel      # Bazel build files
└── config/                        # Kubebuilder kustomize (dev only)