• CRD: extends K8s API with custom resource types
  • Custom resource: instance of a CRD (like Pod is instance of core API)
  • Operator: controller that watches Custom Resources and acts on them
  • Building operators/controllers: not tested; know how to consume existing CRDs

CRD schema

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: widgets.example.com    # <plural>.<group>
spec:
  group: example.com
  scope: Namespaced
  names:
    plural: widgets
    singular: widget
    kind: Widget
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              size:
                type: string

Custom resource instance

apiVersion: example.com/v1
kind: Widget
metadata:
  name: my-widget
spec:
  size: large

kubectl

TaskCommand
List all CRDskubectl get crd
Describe a CRDkubectl describe crd <name>
List instanceskubectl get <kind> -A
Install CRDkubectl apply -f crd.yaml
Explain custom resourcekubectl explain <kind>
kubectl api-resources --api-group=example.com

Exam workflow: create a custom resource from existing CRD

CRD is pre-installed. Task: create an instance.

# 1. Find the CRD
kubectl get crd | grep -i <keyword>
# e.g. → animes.animes.k8s.io

# 2. Inspect schema for valid field names
kubectl get crd <crd-name> -o json \
  | jq '.spec.versions[].schema.openAPIV3Schema.properties.spec.properties'
# or without jq:
kubectl describe crd <crd-name>   # look for Validation section

# 3. Find apiVersion and short name
kubectl api-resources | grep -i <keyword>
# → animes    an    animes.k8s.io/v1alpha1    true    Anime

# 4. Create the custom resource
cat <<EOF | kubectl apply -f -
apiVersion: animes.k8s.io/v1alpha1
kind: Anime
metadata:
  name: my-anime
spec:
  animeName: "Death Note"
  episodeCount: 37
EOF

# 5. Verify
kubectl get an my-anime

Field validation gotcha

CRDs can have minimum, maximum, enum, pattern constraints. API server rejects violations immediately:

The Anime "my-anime" is invalid: spec.episodeCount: Invalid value: 10:
  spec.episodeCount in body should be greater than or equal to 24

Check schema first with jq or describe crd.

Exam gotchas

  • CRD metadata.name must be <plural>.<group>
  • apiVersion on custom resource = <group>/<version>
  • kubectl api-resources | grep <kind> faster than memorising apiVersions
  • Scope (true = Namespaced, false = Cluster): whether to add -n <ns>
  • Without jq: kubectl get crd <name> -o yaml | grep -A 30 'openAPIV3Schema'