Skip to content

Week 11 - CRDs: Schema, Versioning, Validation

11.1 Conceptual Core

  • A CRD (CustomResourceDefinition) registers a new resource kind with the apiserver. Once registered, you can kubectl get/apply it like any built-in.
  • The CRD includes an OpenAPI v3 schema that the apiserver uses for validation. Get this right or you'll ship buggy custom resources.
  • Multiple versions can coexist; conversion webhooks translate between them. The pattern that allows v1alpha1 → v1beta1 → v1 evolution.

11.2 Mechanical Detail

  • Marker comments (+kubebuilder:...) on Go types generate the CRD YAML via controller-gen. Examples:
  • +kubebuilder:validation:Required
  • +kubebuilder:validation:MinLength=3
  • +kubebuilder:validation:Enum=foo;bar;baz
  • +kubebuilder:subresource:status
  • +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=.status.phase``
  • Status conditions: array of {type, status, reason, message, lastTransitionTime}. The standard pattern for surfacing controller state. Use the Kubernetes types directly (metav1.Condition).
  • Server-side apply: with SSA, multiple controllers can own different fields of the same object via fieldManager. Replaces hand-rolled patches for many use cases.
  • Conversion webhooks: invoked when apiserver needs to translate between stored and requested versions. Implement carefully-round-trip stability is essential.

11.3 Lab-"A Well-Versioned CRD"

  1. Define a CRD with v1alpha1.
  2. Add validation, defaults, status conditions, printer columns.
  3. Add a v1beta1 with renamed fields and a conversion webhook between them.
  4. Verify round-trip: kubectl get -o v1alpha1 then - o v1beta1` returns identical content.

11.4 Hardening Drill

  • Validation only at the schema level is not enough. Add admission webhooks for cross-field validation (e.g., "if mode=X then field Y is required").

11.5 Operations Slice

  • Track apiserver_storage_objects per CRD. CRDs that grow unbounded are a frequent platform failure mode.

Comments