Skip to main content
A CRD without an OpenAPI schema will accept any YAML you send it. Typos in field names, a string where you expected an integer, or replicas set to negative seven — all of these will be accepted unless you validate the shape. Example of a malformed spec that a controller might receive:
The OpenAPI v3 schema (see: https://spec.openapis.org/oas/v3.0.3) is your first line of defense: the Kubernetes API server enforces it before your controller ever sees the object. Think of the OpenAPI schema as the printed rules on a form — it defines which boxes are required, which values are allowed, and which entries the API server should reject before persistence. On a CRD, the schema lives under spec.versions.schema.openAPIV3Schema and follows the standard OpenAPI v3 structural schema. At the top level you describe a tree of type, properties, and required fields. For example:
Set type: object at the root, then walk down into spec and status the same way. Each field in the schema supports constraints; these common constraints let you validate names, sizes, ranges, and structural rules before your controller needs to handle invalid input. Callouts
Use an OpenAPI structural schema to reject invalid CRs early — this simplifies controller logic and prevents reconciliation loops caused by malformed objects.
Common constraints by data type Strings
  • minLength, maxLength
  • pattern (regular expression)
  • enum for closed sets
Example:
Numbers
  • minimum, maximum, exclusiveMinimum (boolean)
Arrays
  • minItems, maxItems, uniqueItems
Required
  • The required list on any object enumerates which child properties must be present. If a required field is missing, writes will be rejected.
Defaults
  • You can set default in the schema. When a user omits that field, the API server fills it on write so your controller doesn’t have to handle the empty case.
Example:
Pruning (automatic removal of undeclared fields)
  • Structural schemas cause automatic pruning. In Kubernetes, a structural schema is a fully typed template: anything not declared on that template is stripped before storage. Pruning prevents users from stashing arbitrary data inside your CR.
Example interaction:
If you need a free-form blob in a subtree, opt out of pruning with the x-kubernetes-preserve-unknown-fields extension:
Useful Kubernetes schema extensions
  • x-kubernetes-int-or-string — accepts either integer or string (used by core Kubernetes APIs for ports and quantities).
  • x-kubernetes-validations — where expression-based validation rules live. These use CEL (Common Expression Language, https://github.com/google/cel-spec) and run in the API server (no admission webhook required). CEL is ideal for cross-field checks that OpenAPI cannot express.
Examples:
If a user submits an object violating a CEL rule, the API server returns a descriptive error:
Operational notes and versioning
  • When you change a schema on an existing CRD, already stored objects are not revalidated; only new writes are checked. Tightening constraints can fail new writes even though old objects remain stored. Version your API and plan schema migrations carefully.
When you tighten a schema, existing stored objects are not automatically revalidated. Plan schema migrations and API versioning carefully.
Next steps
  • You will write a CRD by hand for the webapp resource and observe these validators rejecting bad input before it reaches your controller.
The image is a slide introducing a topic about writing a Custom Resource Definition (CRD) by hand, highlighting the role of validators in rejecting bad input before it reaches the controller. It includes a blue-green gradient design with a gear icon.
References and further reading

Watch Video