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.
What Is A CRD?
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.
Creating a CRD
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 CustomResourceDefinition
kind/object.
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.
Creating 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
Describing The CRD
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.