This page documents the version combinations the framework is tested against, the Go minimum requirement, the support policy for tested combinations, and how compatibility is verified.
The framework requires Go 1.26 or later (declared in go.mod). Consumer projects must use Go 1.26 or later to build
against this framework. Go's toolchain version selection ensures the consumer project picks up the same minimum.
This minimum is inherited from controller-runtime v0.24, which itself declares go 1.26.0. It applies to every
combination in the matrix below, including the ones that pin older controller-runtime and k8s.io/* versions: pinning
those dependencies down does not lower the framework's own Go requirement.
The framework is tested against the following version combinations:
| Framework | controller-runtime | k8s.io/* | Kubernetes | Go | Status |
|---|---|---|---|---|---|
| main | v0.24.x | v0.36.x | 1.36 | 1.26 | Primary |
| main | v0.23.x | v0.35.x | 1.35 | 1.26 | Tested |
| main | v0.22.x | v0.34.x | 1.34 | 1.26 | Tested |
Primary is the version combination used in go.mod and in the main CI pipeline.
!!! note "Obtaining an event recorder on controller-runtime v0.22"
`ReconcileContext.EventRecorder` takes a `k8s.io/client-go/tools/events.EventRecorder`, which is a client-go type
available in every `k8s.io/*` version in the matrix. The manager accessor that returns one,
`manager.GetEventRecorder(name)`, was added in controller-runtime v0.23. On v0.22.x, build the recorder from
client-go directly instead:
```go
broadcaster := events.NewEventBroadcasterAdapter(clientset)
recorder := broadcaster.NewRecorder("webapp-controller")
```
The framework compiles and tests unchanged against v0.22.x; only the way a consumer obtains the recorder differs.
Tested combinations are verified weekly by the compatibility CI workflow. They are fully supported: bugs reported against a Tested combination are treated as bugs in the framework, not as unsupported configurations. The distinction from Primary is operational only (Primary is tested on every commit; Tested combinations run on a weekly schedule).
The framework targets the latest stable controller-runtime release as its primary dependency. Compatibility is tested against prior controller-runtime minor versions where transitive dependencies remain compatible. When a new Kubernetes minor version is released and controller-runtime publishes a matching release, the matrix is updated accordingly.
As new Kubernetes minor versions are added to the matrix, the oldest Tested entry may be dropped. Dropping a combination is announced in the release notes for the framework version that removes it. No combination is dropped without being replaced by a newer one in the same release.
Versions v0.21.x and below are not supported. Multiple transitive dependency module path migrations in the Kubernetes ecosystem make those combinations irresolvable.
The
compatibility workflow
runs weekly on a schedule, on manual dispatch, and on pull requests labeled compatibility. For each version
combination in the matrix, it:
- Swaps the
controller-runtimeandk8s.io/*dependencies to the target versions usinggo get, then runsgo mod tidyto resolve transitive dependencies. This step is skipped for the primary (currentgo.mod) entry, which is tested as-is. - Verifies that the entire module compiles (
go build ./...). - Builds all examples (
make build-examples). - Runs the full unit and envtest test suite (
make test).
The Makefile automatically detects the correct envtest binary version from the k8s.io/api module version, so no manual
configuration is needed when testing against different Kubernetes versions.
When you go get this framework, Go's Minimum Version Selection
(MVS) will pull your controller-runtime and k8s.io/* dependencies up to at least the versions declared in the
framework's go.mod. If you are already on newer versions, Go will keep yours. But if you are on older versions, MVS
will bump them.
To prevent this, add replace directives to your go.mod that pin the versions you need:
// go.mod
replace (
sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.22.0
k8s.io/api => k8s.io/api v0.34.0
k8s.io/apimachinery => k8s.io/apimachinery v0.34.0
k8s.io/client-go => k8s.io/client-go v0.34.0
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.34.0
)replace directives override MVS regardless of what the framework's go.mod declares. After adding the directives, run
go mod tidy to update the dependency graph.
This works because the framework's public API surface uses abstract interfaces (client.Object, client.Client) that
remain stable across controller-runtime minor versions. The compatibility CI verifies that this downgrade path compiles
and passes tests.