Database or TenantEnvironment—to simplify user workflows. CustomResourceDefinitions (CRDs) let you extend the Kubernetes API with these custom types and enforce server-side validation using openAPIV3Schema.
This guide walks through creating a namespaced Database CRD that:
- Serves a single API version:
v1. - Requires
spec.engineandspec.size. - Validates
engineandsizeusing enums. - Allows optional
versionandstoragefields.
Only one version entry in
spec.versions may have storage: true. This version is used as the persisted storage version in etcd.CRD structure — key fields and meaning
Below are the important CRD fields you will set. Use the links for more details:- Kubernetes CRD docs: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
Notes:
- The string
<plural>.<group>is used as an example for CRD names; when writing docs, wrap such placeholders in backticks:<plural>.<group>. - Use
openAPIV3Schemainsidespec.versions[*]to perform server-side validation for fields, types, required keys, and enums.
Example CRD YAML: Database
Below is a complete CRD definition for a namespacedDatabase custom resource. Save this as database-crd.yaml and apply it to your cluster.
- The
specobject is validated usingopenAPIV3Schema. engineandsizeare required and constrained to specific enum values.versionandstorageare optional string fields.
Apply the CRD
Create thedatabase-crd.yaml file (shown above), then apply it:
Database custom resources. The API server will validate them according to the schema.
Creating Custom Resources (CRs) — examples and validation behaviour
The examples below show common validation errors and a final valid CR. Save each YAML to the noted filename and apply withkubectl apply -f <file>.
- Missing
metadata.name(invalid)
cr-invalid-name.yaml:
metadata.name is required for any Kubernetes resource.
- Unsupported
engine(invalid)
cr-invalid-engine.yaml:
spec.engine must match one of the allowed enum values from the CRD (postgresql, mysql, mariadb).
- Missing required
size(invalid)
cr-missing-size.yaml:
spec.size is required by the CRD schema.
- Valid CR (successful)
cr-valid.yaml:
- The API server enforces schema validation.
- The custom resource behaves like native Kubernetes resources with
kubectl get,kubectl describe, etc.
Troubleshooting tips
If you don’t see your CRD listed after applying, check the API server logs and
kubectl get crd output. Also ensure metadata.name in the CRD follows the required <plural>.<group> naming convention and that spec.versions[*].storage is set on only one version.kubectl get crd databases.platform.example.com -o yaml— inspect what was created.kubectl api-resources | grep platform— confirm the API resource is registered.- Ensure your cluster version supports
apiextensions.k8s.io/v1(Kubernetes 1.16+).
Summary and best practices
- CRDs extend the Kubernetes API to introduce domain-specific object types for your platform.
- Use
openAPIV3Schemainsidespec.versionsto enable server-side validation (required fields, enums, types). - Ensure
metadata.nameof the CRD follows the<plural>.<group>pattern. - Only one
spec.versions[*]entry may havestorage: true; it determines the persisted version stored in etcd. - After creating a CRD,
kubectland the API server will validate and accept/reject CRs according to the schema you define.