Skip to content

Custom Resource Definitions

There are lots of resources predefined in k8s, like Pod, Service, Deployment, etc.

Still, you can define your own resources. This tutorial, we will go through how to define an nginx resource.

1. Preparation

Make sure you have a k8s environment to play with. You can choose microk8s or minikube to setup a testing environment

2. Custom Resource Definitions

We will use the Custom Resource Definitions to define our new resource. Below is the yaml of the CRD.

nginx

Save the following content into nginx-crd.yaml

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: nginx.stable.underneathall.com
spec:
  group: stable.underneathall.com
  scope: Namespaced
  names:
    plural: nginx
    singular: nginx
    kind: Nginx
    shortNames:
    - ngx
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                replicas:
                  type: integer

Now lets explain the parts step by step.

Version, kind, metadata

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: nginx.stable.underneathall.com
Field Details
apiVersion Refers to the k8s' apiextensions version. For now (2021-Jan), it is v1
kind Must be CustomResourceDefinition
metadata.name The value is the plural name of the resource with the group name, in the form: {plural name}.{group name}

Spec: group, scope and name

spec:
  group: stable.underneathall.com

Group name is a way to group all the resources and REST APIs. It's a similar concept to a library name. When the name is set, your apis can be accessed through /apis/<group>

scope: Namespaced

Indicate if this resource is namespace-wide or cluster-wide.

names:
  kind: Nginx
  singular: nginx
  plural: nginx
  kind: Nginx
  shortNames:
  - ngx
Field Details
kind The kind name used to create the resource
singular Singular name of the resource to use in kubectl
plural Plural name of the resource to use in kubectl and API
shortNames Short name of the resource to use in kubectl

Spec: versions

versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              replicas:
                type: integer

Versions contain all the available versions.

Field Details
name Name of the version
served If the version is enabled
storage Mark true to let k8s store objects using this version. Only one version can be marked true.
schema.openAPIV3Schema.type The type of the schema
schema.openAPIV3Schema.properties.spec.type The type of the spec body
schema.openAPIV3Schema.properties.spec.properties.replicas The customized field we set

Now let's create the CRD

Create the CRD

Run:

kubectl apply -f nginx-crd.yaml

Output:

customresourcedefinition.apiextensions.k8s.io/nginx.stable.underneathall.com created

Run:

kubectl get crd nginx.stable.underneathall.com

Output:

NAME                             CREATED AT
nginx.stable.underneathall.com   2021-01-15T07:10:20Z

3. Create a Nginx Resource

New Nginx

Run the following command to save the yaml into nginx.yaml

cat <<NGINX> nginx.yaml
apiVersion: "stable.underneathall.com/v1"
kind: Nginx
metadata:
  name: underneathall-nginx
  namespace: default
spec:
  replicas: 2
NGINX

Run:

kubectl create -f nginx.yaml

Output:

nginx.stable.underneathall.com/underneathall-nginx created

Run:

kubectl get nginx
or use the short name
kubectl get ngx

Output:

NAME                  AGE
underneathall-nginx   77s

4. Summary

In this tutorial, we learnt what a CRD is composed of, how to create a CRD, and how to create a customized resource.

However, simply adding a CMD is not enough. In the Operator tutorial, we will use the CRD created here and an operator built from scratch to really create a deployment of nginx pods for each Nginx resource.