Tell the project team how you are using cert-manager Take this short anonymous survey


cert-manager is a heavy user of Kubernetes Custom Resources. Chances are high that you may need to change something in our Custom Resource Definition. This guide will give you some tips!

Generating updates

We use controller-gen to update our CRDs. This all is handled using Bazel, just run:

$ ./hack/

This will also update the version conversion code if needed.


cert-manager currently has a single v1 API version.

The API types are defined in //pkg/apis/certmanager. ACME related resources are in //pkg/apis/acme.

Code comments on API type fields are being converted into documentation on our website as well as the output of kubectl explain. These comments should be written to be user-facing not developer-facing, they also break the Go standards of code comments on purpose for this reason.

We also have an internal API version, it lives at //pkg/internal/apis. This is a version that is only used for validation and conversion, controllers should not use it as it is not meant to be user-friendly and not stable. However all new fields also have to be added here for the conversion logic to work.

See the official Kubernetes docs for CRD versioning to understand conversion, which versions are stored and served etc.


While cert-manager doesn't fully use Kubebuilder for everything CRDs can make use of special Kubebuilder flags such as validation flags. We recommend reading the Kubebuilder book to learn more about them!

Making changes to API

Please see our API compatibility promise to understand what changes to API are acceptable- the gist of it is that new fields can be added, but not removed. This also means that when a field is added to a version of the API, it can no longer be removed and its name cannot be changed- so we try to be cautious when adding new fields. Same applies to constants and enumerated types.