Timoni allows defining Kubernetes Custom Resources (CRs) in modules and can ensure
that these are validated against their Kubernetes Custom Resource Definitions (CRDs).
For waiting on custom resources that don’t follow the kstatus conventions,
see custom health checks.
To enable validation for custom resources, you have to generate the CUE schemas from
the Kubernetes CRDs OpenAPI validation spec with the timoni mod vendor crds command.
Example
To demonstrate this feature, we’ll use the
Prometheus Operator CRDs,
and we’ll add a ServiceMonitor custom resource to a Timoni module.
Vendor Prometheus Operator CRDs
From the root dir of your module, run the timoni mod vendor crds command, and pass the URL
to the YAML file which contains the Prometheus Operator CRDs:
The above command will generate the CUE schemas corresponding to the Kubernetes CRDs
inside the cue.mod/gen directory:
CEL validation rulesThe generated files embed the original CRD in a hidden _crd field.
This lets timoni mod vet enforce the CEL rules set with x-kubernetes-validations,
such as mutually exclusive fields or constraints across field values,
applying the same strict validation as the Kubernetes API server.
Select kinds and versions
By default, all the CRDs and all their versions found in the YAML file are vendored.
To vendor only the custom resources used by the module, select them with the
--kind and --version flags:
The --kind flag accepts the kind name or the fully qualified Kind.group name. The qualified form selects a single CRD when the same
kind is defined in multiple API groups, e.g. --kind ProviderConfig.aws.upbound.io.
The --version flag applies to all the selected kinds and matches the version names
declared in the CRDs, e.g. --version v1,v1beta1. Both flags match case-insensitively.
The command fails when a selected kind or version is not found in the YAML file,
listing the kinds and versions available.
To list the kinds and versions found in a YAML file without vendoring them,
use the --list flag:
Prune vendored schemas
The command never removes the previously vendored schemas, so narrowing the selection
or vendoring a new release of the CRDs leaves the stale definitions in cue.mod/gen.
To remove them, use the --prune flag:
Pruning is scoped to the API groups found in the YAML file: every vendored definition
under those groups that was not generated by the current run is removed, while the
definitions of other API groups, such as the ones vendored with timoni mod vendor k8s
or from another CRD file, are left untouched. Only the files generated by Timoni are removed,
hand-written CUE files placed under the same API group are kept.
Create the ServiceMonitor template
In the templates directory, create a servicemonitor.cue file with the following content:
Make sure to replace the port and path values with the ones used by your app.
The port name must match one of the ports exposed in the Kubernetes Service template.
API Version and KindNote that for Kubernetes custom resources, you don’t need to specify the
apiVersion and kind, these fields are set by Timoni in the generated schema.
Add the monitoring configuration
In the templates/config.cue file, add the monitoring configuration:
Add the ServiceMonitor to the instance
In the templates/config.cue file, add the ServiceMonitor resource to the instance objects:
Document the monitoring configuration
Finally, document the monitoring configuration in the README.md file, so that users
know how to enable monitoring if they have Prometheus Operator installed.
Custom resource validation
The timoni mod vet command validates the custom resources rendered by the module
against their CRD schemas with the same checks as the Kubernetes API server:
- OpenAPI schema validation
- embedded resource metadata validation
- uniqueness of
x-kubernetes-list-type: map and set items
- CEL validation rules set by x-kubernetes-validations
The CRD schemas are taken from:
- the CUE packages imported by the module, generated with
timoni mod vendor crds
- the CRDs included in the module’s output
When both sources define the same kind and version, the CRD included in the module takes precedence.
Custom resources that pass all checks are reported as valid custom resource.
Any violation is reported with the field path and the message, and the command fails: