One of the absolutely beautiful things about Kubernetes is the ability to extend it and customize it in the way that you want. The platform was literally designed for that exact purpose. It’s like a house that builders just put up. There are rooms cut out, but no plumbing or light fixtures. It’s entirely up to you to customize it in the way that you want to.
One of those ways is by extending the API.
In this blog post, you’ll learn how to extend the Kubernetes API using Custom Resource Definitions.
A Custom Resource Definition (CRD) gives you the ability to extend the Kubernetes API, but what does this mean exactly?
When you’re working with Kubernetes, you’re constantly interacting with the API Server. If you’re running
kubectl get pods, you’re performing an API request. If you’re deploying a new Kubernetes resource with
kubectl apply -f or
kubectl create -f, you’re performing an API request.
Everything is done at the API level.
What if you want to create and/or deploy a resource that doesn’t currently exist in Kubernetes however? Maybe you want to combine a few different Kubernetes resources that you wish to create at the same time for a specific application stack. Instead of deploying them separately, you can deploy them together with an API that you’ve created.
CRDs are the method of creating an API that doesn’t already exist in a general Kubernetes installation.
One of the ways that you create your very own API is by extending the current Kubernetes API with a Custom Resource Definition.
The way that a CRD is created is by using the
[apiextensions.k8s.io/v1](http://apiextensions.k8s.io/v1) Named API group. Within that API group, there’s a
You can then specify the group that you want to create along with the version and specs within the schema. The typical schema used is from the Open API v3.
Below is an example of a CRD that you can create. It has a group of
[simplyengineering.com](http://simplyengineering.com) and gives you the ability to pass in a container image name and a replica count.
Run the following code example.
kubectl apply -f - <<EOF apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: mikesnginxapps.simplyengineering.com spec: group: simplyengineering.com versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: image: type: string replicas: type: integer scope: Namespaced names: kind: MikesNginxApp plural: mikesnginxapps singular: mikesnginxapp shortNames: - mikeapp EOF
After running the code example, you can ensure that the CRD was successfully installed on your Kubernetes cluster.
☁ ~ kubectl get crd NAME CREATED AT mikesnginxapps.simplyengineering.com 2023-07-16T17:37:24Z
You can also check to see if any resources are deployed via the new CRD. Much like you would run
kubectl get pods to check Pods, you can run
kubectl get mikeapp (because the
shortNames is specified as
mikeapp) to see if any resources are running.
☁ ~ kubectl get mikeapp No resources found in default namespace.
Let’s now learn how to create a resource.
The new resource via the CRD is created by specifying the group name, which is the API Version and the kind/object.
Run the below code example which will use the new CRD to deploy an Nginx container image with two replicas.
kubectl apply -f - <<EOF apiVersion: simplyengineering.com/v1 kind: MikesNginxApp metadata: name: mikesapptest spec: image: nginx:latest replicas: 2 EOF
After running the code above, check the
mikeapp object again.
You’ll see that the new resource is running.
☁ ~ kubectl get mikeapp NAME AGE mikesapptest 41s
If you want to dive a little further into the CRD, you can describe it in the same way that you’d describe a Pod or a deployment.
kubectl describe mikeapp mikesapptest
The output should be similar to the screenshot below.