Creating a Custom Resource Definition In Kubernetes
Tags: kubernetes, devops, programming, cloud
Published: 2023-07-25 13:38:52

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.

```yaml
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.

```jsx
☁  ~  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.

```jsx
☁  ~  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.

```jsx
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.

```jsx
☁  ~  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.

```jsx
kubectl describe mikeapp mikesapptest
```

The output should be similar to the screenshot below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2uf5rt2gwt1dp4qmts7j.png)