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


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.
Subscribe to my newsletter
Read articles from Jaakko Leskinen directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
