Custom Resource Definitions (CRDs): Extending Kubernetes Like a Boss

Jaakko LeskinenJaakko Leskinen
3 min read

Kubernetes is a magnificent beast—so long as you stay within its predefined rules. It happily schedules pods, orchestrates services, and ensures your microservices don’t eat each other. But the moment you ask it to handle something outside its comfort zone, it stares at you like a confused robot, waiting for more YAML sacrifices.

Try managing feature flags, application configs, or, say, a fire-breathing dragon, and Kubernetes simply shrugs. "Not my problem." It was never designed to understand dragons, chaos monkeys, or sentient serverless applications plotting their escape. But what if it could?

That’s where Custom Resource Definitions (CRDs) come in. Think of them as a way to reprogram Kubernetes' brain—expanding its API to recognize and manage entirely new types of objects. Want a Dragon resource with attributes like fireBreathing and wingSpan? You got it. Need a ChaosMonkey to randomly terminate pods in the name of resilience testing? Kubernetes will now happily facilitate its own destruction—all because you taught it how.

With CRDs, you’re not just using Kubernetes—you’re rewriting its reality.

How CRDs Work

A CRD is, at its core, just another API object in Kubernetes. When you create one, Kubernetes automatically generates a new API endpoint for it. Suddenly, your cluster understands a brand-new type of resource, and you can kubectl get it just like built-in objects like pods or deployments.

For example, if you install a CRD for ClusterIssuer (used by cert-manager for handling TLS certificates), you immediately get:

kubectl get clusterissuers

Just like kubectl get pods, but for something Kubernetes didn’t natively support before.

Finding What’s Installed

If you’re working with a Kubernetes cluster that’s had CRDs installed, you might want to see what’s available. List all installed CRDs with:

kubectl get crds

This will return a list of all the custom resources available on the cluster. If you want to dig into a specific one, say clusterissuers, you can check its details:

kubectl describe crd clusterissuers

This provides information on what fields the CRD supports, its API group, and validation rules.

Creating a Custom Resource Definition

Let’s say we want Kubernetes to manage a collection of dragons. We need to define a CRD that tells Kubernetes what a "dragon" is.

Here’s a simple YAML definition for a Dragon resource:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: dragons.example.com
spec:
  group: example.com
  names:
    kind: Dragon
    listKind: DragonList
    plural: dragons
    singular: dragon
  scope: Namespaced
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              fireBreathing:
                type: boolean
              wingSpan:
                type: integer

Applying this CRD tells Kubernetes, “Hey, from now on, you should recognize something called a ‘Dragon’ and expect it to have attributes like ‘fireBreathing’ and ‘wingSpan’.”

kubectl apply -f dragon-crd.yaml

Now, Kubernetes knows what a Dragon is, and we can create our first one:

apiVersion: example.com/v1
kind: Dragon
metadata:
  name: smaug
spec:
  fireBreathing: true
  wingSpan: 30
kubectl apply -f smaug.yaml

And just like that, your cluster officially recognizes Smaug, the fire-breathing dragon.

Why CRDs Are Powerful

The magic of CRDs is that they allow you to extend Kubernetes without modifying its core. Combined with custom controllers and operators, you can build self-healing, auto-scaling infrastructure that’s tailor-made for your specific use cases.

For example:

  • ArgoCD’s CRDs let you manage GitOps-driven deployments.

  • Cert-manager’s CRDs automate certificate management.

  • KEDA’s CRDs enable event-driven auto-scaling.

With a bit of work, you can build your own fully automated Kubernetes-native applications that respond to changes in custom resources just like built-in objects.

CRDs are how you teach Kubernetes new tricks. They let you stop fighting the system and start making it work for you. So next time you find yourself duct-taping YAML files together to handle a missing Kubernetes feature, ask yourself: Should I just create a CRD instead?

The answer is probably yes.

0
Subscribe to my newsletter

Read articles from Jaakko Leskinen directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jaakko Leskinen
Jaakko Leskinen