Kubernetes CRD Spec Structure
Kubernetes CRD Spec Structure defines custom resources, enabling API extension and lifecycle management for custom objects in Kubernetes.
Kubernetes CRD Spec Structure is the anatomy of a CustomResourceDefinition object itself: the specific set of fields under its own spec that determine how the new resource type is named, grouped, versioned, scoped, validated, and presented to clients, distinct from the schema of the custom resources that the CRD subsequently allows users to create.
Group, Names, and Scope
API Group and Names Block
Every CRD declares the API group it registers under and a names block that defines every identifier clients will use to refer to the new kind.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: cronbackups.batch.example.com
spec:
group: batch.example.com
names:
kind: CronBackup
listKind: CronBackupList
plural: cronbackups
singular: cronbackup
shortNames: ["cb"]
categories: ["all"]
The metadata.name of the CRD object itself must equal <plural>.<group>, a naming convention enforced by the API server rather than a stylistic choice, and shortNames enables abbreviated kubectl usage such as kubectl get cb.
Scope
spec:
scope: Namespaced
scope is fixed at Namespaced or Cluster for the lifetime of the CRD and cannot be changed after creation; it determines whether instances of the custom resource are isolated per namespace (and subject to namespace-scoped RBAC) or exist once, globally, across the entire cluster.
The Versions Array
Per-Version Configuration
Each entry in spec.versions is independently configurable, allowing served versions to differ in schema, subresource support, and additional printer columns simultaneously.
spec:
versions:
- name: v1
served: true
storage: true
deprecated: false
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
status:
type: object
subresources:
status: {}
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.readyReplicas
additionalPrinterColumns:
- name: Ready
type: string
jsonPath: .status.conditions[?(@.type=="Available")].status
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
served, storage, and deprecated Flags
Exactly one version across the array must set storage: true; served controls whether the API server accepts requests for that specific version at all, independently of storage; and deprecated: true combined with deprecationWarning surfaces a warning header to clients using that version without yet removing it.
Subresources
Status Subresource
subresources:
status: {}
Declaring the status subresource splits /spec updates from /status updates into separate API endpoints, each governed by its own RBAC verb, and disables the default behavior where any update to the object silently overwrites status.
Scale Subresource
subresources:
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.readyReplicas
labelSelectorPath: .status.labelSelector
The scale subresource maps a custom resource's replica-like fields onto the standard /scale endpoint contract, which is what allows a Horizontal Pod Autoscaler to target a custom resource exactly as it would target a Deployment, without the HPA needing any custom-resource-specific logic.
Presentation and Discovery Fields
Additional Printer Columns
additionalPrinterColumns defines which fields kubectl get displays by default for the custom resource, letting operationally relevant status fields (replica readiness, phase, age) surface directly in a listing rather than requiring -o yaml to inspect.
kubectl get cronbackups
NAME READY AGE
nightly-db True 3d
Validation Rules Beyond Type Schema
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
x-kubernetes-validations:
- rule: "self.retention <= 365"
message: "retention must not exceed 365 days"
Common Expression Language validation rules embedded directly in the schema (x-kubernetes-validations) express cross-field or business-rule constraints that a plain type schema cannot, evaluated at admission time without requiring a separate validating webhook.
Preservation and Pruning Behavior
Structural Schema and Field Pruning
spec:
preserveUnknownFields: false
With a structural schema in place, fields submitted on a custom resource that are not declared in the schema are silently pruned by the API server rather than stored, protecting the resource's shape from accidental or malicious injection of undeclared data.
Relationship to CRD Management and the Extension Model
The spec structure of a CRD is the concrete configuration surface that CRD management practices — versioning, conversion, deprecation — operate on, and it is the mechanism through which the broader Kubernetes extension model's reconciliation and status-reporting conventions become expressible for a specific custom resource: the versions, subresources, and validation fields described here are what give a custom kind the same API-level behavior guarantees that built-in resources have by default.