Kubernetes Custom Resource Definitions (CRDs)

What are CRDs?

In Kubernetes, a CRD allows users to define their own custom resources, extending the Kubernetes API. Once you’ve defined a CRD, you can manage it using kubectl just like built-in resources (like Pods, Services).

Why use CRDs?

If you have a specific configuration or application-related specification that doesn’t fit into existing Kubernetes objects, CRDs can help. For instance, if you’ve developed a specific operator to manage a database, you might use a CRD to represent each database instance.

Key Components

  1. Custom Resources: These are the instances of your CRD. If you define a CRD for Database, then each individual database you create would be a custom resource.

  2. Custom Controllers: Often used in conjunction with CRDs. A custom controller watches your custom resource and takes actions based on changes.

Together, a CRD and a custom controller make up an operator.

Creating a CRD

A CRD is defined using a YAML file. Here’s a basic outline:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
  name: databases.yourdomain.com
  group: yourdomain.com
    - name: v1
      served: true
      storage: true
  scope: Namespaced  # or "Cluster"
    plural: databases
    singular: database
    kind: Database
    - db
  • group: The API group.
  • versions: Supported versions.
  • scope: Namespaced if it should exist inside namespaces. Cluster for cluster-wide.
  • names: Specify the naming details.

Working with CRDs

  1. Create a CRD: kubectl apply -f your-crd-definition.yaml
  2. List CRDs: kubectl get crds
  3. Use the CRD: Once the CRD is created, you can create custom objects just like built-in objects.
apiVersion: yourdomain.com/v1
kind: Database
  name: mydb-instance
# followed by the spec of your custom resource

Deleting CRDs

  • Remember, deleting a CRD will delete all the custom resources of that type!
  • kubectl delete crd databases.yourdomain.com

Kubernetes CKAD Practice Exercises with Solutions

Pre-Setup and Exercises

This Markdown document provides initial setups for each exercise and the exercises themselves to help you practice Custom Resource Definitions (CRDs), troubleshooting, and imperative commands. Additionally, solutions are also provided for each exercise.

Pre-Setup for Exercise 1

No initial setup required. The exercise starts with creating the CRD.

Exercise 1: Create a Custom Resource Definition (CRD)

  1. Define a CRD for WebApps which has the following specifications:

    • API Group: example.com
    • Version: v1
    • Namespaced
    • Ensure the CRD supports both singular (webapp) and plural (webapps) forms.
  2. Create an instance of WebApp with the name frontend-app that has specifications like image: nginx:latest.

Solution for Exercise 1

kubectl create crd webapps.example.com \
  --group=example.com \
  --version=v1 \
  --scope=Namespaced \

kubectl apply -f - <<EOF
apiVersion: example.com/v1
kind: WebApp
  name: frontend-app
  image: nginx:latest

Pre-Setup for Exercise 2

Create a namespace called debug-namespace and deploy a faulty pod named trouble-pod in it.

kubectl create ns debug-namespace
kubectl run trouble-pod --namespace=debug-namespace --image=nginx:broken --command -- /bin/sh -c "exit 1"

Exercise 2: Troubleshooting a Pod

A Pod named trouble-pod in the debug-namespace is failing to start.

  1. Use an imperative command to fetch logs of this Pod.
  2. Describe the Pod to identify any events or issues.
  3. Get the details of all the resources in debug-namespace using a single command.

Solution for Exercise 2

kubectl logs trouble-pod -n debug-namespace
kubectl describe pod trouble-pod -n debug-namespace
kubectl get all -n debug-namespace

Pre-Setup for Exercise 3

No initial setup is required. You’ll be working with an empty namespace.

Exercise 3: Imperative Commands Practice

  1. Create a new namespace called exercise-ns using an imperative command.
  2. Run an nginx Pod named web-server in the exercise-ns namespace.
  3. Expose the web-server Pod on port 8080 using a Service named web-service in the same namespace. Do this using an imperative command.

Solution for Exercise 3

kubectl create ns exercise-ns
kubectl run web-server --image=nginx --namespace=exercise-ns
kubectl expose pod web-server --port=8080 --name=web-service --namespace=exercise-ns

Pre-Setup for Exercise 4

Create the WebApp CRD and deploy a custom controller (dummy nginx pod for this exercise).

kubectl create crd webapps.example.com \
  --group=example.com \
  --version=v1 \
  --scope=Namespaced \

kubectl run webapp-controller --image=nginx
  1. Deploy a WebApp resource:
kubectl apply -f - <<EOF
apiVersion: example.com/v1
kind: WebApp
  name: sample-app
  image: nginx:latest

Exercise 4: CRD Troubleshooting

You realize that instances of the WebApp CRD are not behaving as expected. Some WebApps are not accessible via their services.

  1. Describe an instance of the WebApp to understand its current state.
  2. Check if any custom controllers are responsible for managing WebApp instances.
  3. Fetch logs of such controllers to understand if they are encountering any errors.

Solution for Exercise 4

kubectl describe webapp sample-app
kubectl get pods -l run=webapp-controller
kubectl logs -l run=webapp-controller

Pre-Setup for Exercise 5

Deploy two deployments named frontend-deployment and backend-deployment.

kubectl create deployment frontend-deployment --image=nginx
kubectl create deployment backend-deployment --image=redis:3.0

Exercise 5: Imperative Commands with Configurations

  1. Create a busybox Pod named config-pod which has an environment variable APP_MODE set to production.
  2. Scale a deployment named frontend-deployment to 5 replicas using an imperative command.
  3. Set an image redis:4.0 for a deployment named backend-deployment without changing any other configuration.

Solution for Exercise 5

kubectl run config-pod --image=busybox --env=APP_MODE=production
kubectl scale deployment frontend-deployment --replicas=5
kubectl set image deployment/backend-deployment *=redis:4.0


  1. Understand CRD basics: How to define, apply, and manage them.
  2. CRD Lifecycle: Be comfortable with creating, listing, and deleting CRDs.
  3. Interaction: Understand how custom controllers might interact with these custom resources.

For CKAD, the direct manipulation of CRDs might not be heavily emphasized, but having an understanding is beneficial. Instead, focus on how to interact with custom resources provided by any given CRD, which might be more relevant to application development and deployment.