✦ For everyone, free.

Practical knowledge for real and everyday life

Home

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.

storage: true across versions = 1

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.

CustomResourceDefinition.spec group / names scope versions[] schema / subresources