CKAD — Creating CRDs

1 minute read

Custom Resource Definitions (CRDs)

A CRD tells the Kubernetes API server about a new resource type. Once you create a CRD, you can create instances of that resource using kubectl.

Creating a Basic CRD

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: backups.stable.example.com
spec:
  group: stable.example.com
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              database:
                type: string
              schedule:
                type: string
              retentionDays:
                type: integer
            required:
            - database
            - schedule
  scope: Namespaced
  names:
    plural: backups
    singular: backup
    kind: Backup
    shortNames:
    - bk
kubectl apply -f backup-crd.yaml
# Expected: customresourcedefinition.apiextensions.k8s.io/backups.stable.example.com created

# Verify the CRD exists
kubectl get crd backups.stable.example.com

CRD Field Reference

Field Description
spec.group API group (e.g., stable.example.com)
spec.versions List of versions with schemas
spec.versions[].served Whether this version is served by the API
spec.versions[].storage Which version is used for storage (only one)
spec.scope Namespaced or Cluster
spec.names.plural Plural name for the URL (e.g., /apis/group/v1/backups)
spec.names.singular Singular name for display
spec.names.kind Resource kind in YAML
spec.names.shortNames Short aliases for kubectl

Schema Validation

The openAPIV3Schema section validates custom resources. If someone creates a resource that does not match the schema, the API server rejects it.

schema:
  openAPIV3Schema:
    type: object
    properties:
      spec:
        type: object
        properties:
          replicas:
            type: integer
            minimum: 1
            maximum: 10
          image:
            type: string
            pattern: '^[\w.-]+/[\w.-]+:[\w.-]+$'
          environment:
            type: string
            enum:
            - development
            - staging
            - production
        required:
        - replicas
        - image

Supported validations:

  • type — string, integer, boolean, array, object
  • required — list of required fields
  • minimum / maximum — numeric ranges
  • minLength / maxLength — string lengths
  • enum — allowed values
  • pattern — regex pattern

Adding Printer Columns

By default kubectl get only shows name and age. Add columns using additionalPrinterColumns:

versions:
- name: v1
  served: true
  storage: true
  additionalPrinterColumns:
  - name: Database
    type: string
    jsonPath: .spec.database
  - name: Schedule
    type: string
    jsonPath: .spec.schedule
  - name: Retention
    type: integer
    jsonPath: .spec.retentionDays
  - name: Age
    type: date
    jsonPath: .metadata.creationTimestamp
  schema:
    openAPIV3Schema:
      # ... schema here
kubectl get backups
# Expected:
# NAME              DATABASE        SCHEDULE    RETENTION   AGE
# daily-db-backup   postgres-main   0 2 * * *   30          1m

Next: Custom Resources →

Updated: