In this article, we will explore Custom Resource Definitions (CRDs) in Kubernetes (K8S), explain what they are, possible use cases, and how to get started creating your own CRDs.
Kubernetes (K8S) has a set of objects ready for use out of the box. But what if you wanted K8S to manage other things other than Kubernetes itself and the containers it manages? This is where creating your own objects using Custom Resource Definitions (CRDs) comes in.
The use of CRDs makes the possibilities of Kubernetes management almost limitless. You can extend the base Kubernetes API with any object you like using CRDs.
For example, using
kubectl to interact with my cluster, I type:
kubectl get MyRouter
I get an error:
error: the server doesn't have a resource type "MyRouter"
This is obviously fully expected,
MyRouter is not a valid resource name that comes out of the box in the K8S API.
I first need to add the
MyRouterobject to my K8S API using a CRD.
Using CRDs can commonly enable K8S to be able to manage other parts of your infrastructure, such as network devices like routers and switches. This might help you avoid having to replace old devices by using K8S modern and streamlined management capabilities.
Many tools that you install on your K8S cluster will include the creation of some CRD objects. This is to enable them to provide functionality that is not provided in vanilla K8S.
For example, if you have the monitoring tool Prometheus installed on your cluster, it will include the installation of prometheusrules.monitoring.coreos.com CRDs. CRDs are listed in the format
<object>.<group>. With these installed, I can run the command
kubectl get prometheusrules -n prometheus — before the installation of Prometheus on my cluster, these commands would return an error:
error: the server doesn't have a resource type "prometheusrules"
With it installed, the command shows me a list of Prometheus rules.
Because CRDs are created with most tool installations, you will likely have some CRDs already installed on your cluster.
You can view a list using the command:
kubectl get crd
To create a CRD, we need to create a new YAML file. The example below defines a resource definition for switches that I have in my datacenter that I will manage using K8S. Before you jump in, be aware that most scenarios do not need a new CRD created from scratch, they already have a solution out there on the internet.
apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: switches.datacenter.com # name must match the spec fields below, and be in the form: <plural>.<group> spec: group: datacenter.com # group name to use for REST API: /apis/<group>/<version> versions: - name: v1 served: true # Each version can be enabled/disabled by Served flag. storage: true # One and only one version must be marked as the storage version. schema: openAPIV3Schema: type: object properties: spec: type: object properties: dataCenter: type: string rack: type: integer type: type: string scope: Cluster # either Namespaced or Cluster names: plural: switches # plural name to be used in the URL: /apis/<group>/<version>/<plural> singular: switch # singular name to be used as an alias on the CLI and for display kind: Switch # kind is normally the CamelCased singular type. Your resource manifests use this. shortNames: # shortNames allow shorter string to match your resource on the CLI - sw
I can apply it using:
kubectl apply -f switchcrd.yaml
I can see it added to the list of my CRDs by using the command:
kubectl get crd
Now I can run the command:
kubectl get switches
This is because we have defined only the definition, not the actual switch device I want to manage.
I’ll create a device called Switch1. Create a new file called switch1.yaml:
apiVersion: datacenter.com/v1 kind: Switch metadata: name: switch1 spec: dataCenter: uksouth rack: 280 type: physical
Apply it using the command:
kubectl apply -f .\switch1.yaml
Now we can list our switches:
kubectl get switches
This object is now a part of the K8S API. As it stands, it is just a list with some specs, which doesn’t actually do anything other than serve as a data record.
To make use of the custom object we created, we can create a CustomController object to configure our switches, for example. Custom controllers are applications or scripts. They’re deployed on the cluster as pods, and their job is to listen to the Kubernetes API and perform some actions based on defined logic.
The CustomController object could be configured to listen to the K8S API for any changes in our switch objects and make appropriate changes based on those, effectively introducing fully custom automation!
Custom resource definitions (CRDs) enables Kubernetes to be hugely flexible when it comes to deciding what you want it to manage. CRDs are considered a fairly advanced K8S topic. You should understand the basics before diving in!
Additionally, Spacelift can help you manage the complexities and compliance challenges of using Kubernetes. Anything that can be run via kubectl can be run within a Spacelift stack. Read more about how Spacelift works with Kubernetes.
The Most Flexible CI/CD Automation Tool
Spacelift is an alternative to using homegrown solutions on top of a generic CI. It helps overcome common state management issues and adds several must-have capabilities for infrastructure management.