CKAD — CRDs & Operators Lab

3 minute read

Lab 1: Create a CRD and Custom Resources

# Create a CRD for a "Website" resource
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: websites.apps.example.com
spec:
  group: apps.example.com
  versions:
  - name: v1
    served: true
    storage: true
    additionalPrinterColumns:
    - name: URL
      type: string
      jsonPath: .spec.url
    - name: Replicas
      type: integer
      jsonPath: .spec.replicas
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              url:
                type: string
              replicas:
                type: integer
                minimum: 1
                maximum: 5
              image:
                type: string
            required:
            - url
            - replicas
  scope: Namespaced
  names:
    plural: websites
    singular: website
    kind: Website
    shortNames:
    - ws
EOF

# Verify the CRD
kubectl get crd websites.apps.example.com
# Expected: CRD exists

# Create a Website resource
cat <<EOF | kubectl apply -f -
apiVersion: apps.example.com/v1
kind: Website
metadata:
  name: my-blog
spec:
  url: https://example.com
  replicas: 3
  image: nginx:1.27
EOF

# List websites
kubectl get websites
# Expected:
# NAME      URL                    REPLICAS   AGE
# my-blog   https://example.com   3          5s

# Use the short name
kubectl get ws

# Try creating an invalid resource (replicas > 5)
cat <<EOF | kubectl apply -f -
apiVersion: apps.example.com/v1
kind: Website
metadata:
  name: invalid-site
spec:
  url: https://bad.com
  replicas: 100
EOF
# Expected: Error — spec.replicas must be <= 5

Lab 2: Explore Existing CRDs

# List all CRDs in the cluster
kubectl get crd

# Pick a CRD and explore it
kubectl describe crd <crd-name>

# List instances of that custom resource
kubectl get <resource-plural-name>

# Check the schema
kubectl explain <resource-kind>

Practice Questions

Q1: What is a CRD and how does it differ from a built-in resource?

Show Answer A Custom Resource Definition (CRD) extends the Kubernetes API with a new resource type. After creating a CRD, you can use kubectl to create, get, update, and delete instances of that resource just like built-in resources. The difference is that built-in resources (Pods, Deployments, Services) come with Kubernetes and have built-in controllers. CRDs define only the data structure — they need a separate controller (Operator) to act on the resources.

Q2: Create a CRD for a resource called “Database” in the group db.example.com with fields: engine (string, required), version (string), and replicas (integer, minimum 1).

Show Answer ```yaml apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: databases.db.example.com spec: group: db.example.com versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: engine: type: string version: type: string replicas: type: integer minimum: 1 required: - engine scope: Namespaced names: plural: databases singular: database kind: Database shortNames: - db ```

Q3: What happens when you delete a CRD?

Show Answer When you delete a CRD, **all custom resources of that type are also deleted**. This is a cascading delete. For example, if you delete the `backups.stable.example.com` CRD, all Backup resources are permanently removed from the cluster. Always be careful when deleting CRDs in production.

Q4: What is the difference between an Operator and a CRD?

Show Answer A **CRD** defines a new resource type — it is just the data schema. It tells the API server "this kind of object exists and its fields look like this." An **Operator** is a controller that watches CRDs and takes action. It contains the business logic — creating Pods, Services, or other resources based on the custom resource spec. Together: CRD = the "what" (desired state), Operator = the "how" (reconciliation logic).

Q5: How do you check if a custom resource type exists in the cluster and list its instances?

Show Answer ```bash # List all CRDs kubectl get crd # Search for a specific CRD kubectl get crd | grep backup # See the CRD details and schema kubectl describe crd backups.stable.example.com # List instances kubectl get backups kubectl get backups -A # across all namespaces # Get details of a specific instance kubectl describe backup daily-db-backup kubectl get backup daily-db-backup -o yaml ```

← Previous: CRD vs ConfigMap Next: Services & Networking →

Updated: