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/applyit 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 viacontroller-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"¶
- Define a CRD with v1alpha1.
- Add validation, defaults, status conditions, printer columns.
- Add a v1beta1 with renamed fields and a conversion webhook between them.
- Verify round-trip:
kubectl get -o v1alpha1then - 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_objectsper CRD. CRDs that grow unbounded are a frequent platform failure mode.