DEV Community

Cover image for How to Create a YAML Manifest Template in Monokle for Deploying Cassandra with StatefulSet
Yash Gangwar
Yash Gangwar

Posted on • Edited on

How to Create a YAML Manifest Template in Monokle for Deploying Cassandra with StatefulSet

➡️ What is Monokle?

Managing and debugging K8s manifests and YAML file with 100 lines of code and soo many K8s objects and resources is quiet difficult sometimes. And here is where Monokle comes into play...

Welcome to Monokle - your friendly desktop UI for managing k8s manifests!

Monokle is an open-source tool developed by Kubeshop that makes it very easy to manage and inspect your Kubernetes Manifests, showing you how your manifests and different objects are connected to each other. You can edit and refractor resources, preview and debug resources, deploy them to our local or cloud K8s cluster and much more!

Apart from all this Monokel also helps you to create manifests both from scratch and from templates. With templates you don't need to write a yaml file from scratch, you can simply select the template and add few necessary info like namespace, image name, no. of replicas and a manifest file is ready for you to deploy.

If you are new to Monokel, check out this Intro to Monokel video by Kunal Kushwaha to get started with the tool.

➡️ What will this Template do?

Cassandra is a database designed to handle big data workloads across multiple nodes without a single point of failure. We will be creating a StatefulSet Template that will help us deploying Cassandra Database to a K8s cluster.

In this blog, I will take you through the steps to create and use your own custom Template for Monokel from Scratch.

🚀Lets get started!!


➡️ Prerequisites

Prior knowledge of working with YAML files, Kubernetes resources and objects like Pods, StatefulSets, Services would be beneficial. You can checkout video tutorials on all these stuff by Kunal Kushwaha in his DevOps Bootcamp playlist.

➡️ Setting up the project

The templates in monokle are installed via a plugin, and that plugin is basically our github repo that contains package.json file in order to be a monokle plugin

✅Step 1: Creating a Github Repository

Create a Github Repository by the name monokle-templates-plugin. After that clone that empty repo into your local machine using the following command.

git clone https://github.com/YOUR_GITHUB_USERNAME/monokle-templates-plugin.git
Enter fullscreen mode Exit fullscreen mode

Now enter into that folder using cd monokle-templates-plugin

✅Step 2: Creating package.json file

Create a file named package.json inside your root folder for our template plugin.

This file should have the following content:

{
  "name": "Template Plugins",
  "description": "Custom templates plugin",
  "version": "1.0.0",
  "author": "YOUR_NAME",
  "repository": "https://github.com/YOUR_GITHUB_USERNAME/monokle-templates-plugin",
  "monoklePlugin": {
    "id": "com.github.YOUR_GITHUB_USERNAME.plugin.templates.cassandra-statefulset-template",
    "helpUrl": "https://github.com/YOUR_GITHUB_USERNAME/monokle-templates-plugin",
    "modules": [
      {
        "type": "template",
        "path": "cassandra-statefulset-template"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

⚠️ REMEMBER: Replace your name and Github username wherever mentioned.


➡️ Creating the Template

In previous step you created a package.json file and inside modules you set some path. So now create a folder named cassandra-statefulset-template inside your root folder that has package.json.

This folder will actually contain all the files required to create your custom template. It will have following four parts/files:

  1. Monokle template configuration
  2. Defining Form Schema
  3. Defining Form UI
  4. Kubernetes YAML manifest with placeholders

📄File 1: Monokle template configuration

This file is Monokle-specific and defines what type of template you are creating. There are two types of templates in Monokle for now: vanilla and helm-charts; we will be creating a simple vanilla type template.

Create the file monokle-template.json with following content:

{
    "name": "Deploy Cassandra with StatefulSet",
    "id": "com.github.YOUR_GITHUB_USERNAME.plugin.templates.cassandra-statefulset-template",
    "author": "YOUR_NAME",
    "version": "1.0.0",
    "description": "Creates a Deployemnt, Service and Storage Class for Cassandra database using Statefulsets",
    "repository" : "",
    "type": "vanilla",
    "forms": [
      {
        "name": "Deployment Settings",
        "description": "Specify the no. of replicas, namespace, cluster name and related settings of database",
        "schema": "form-schema.json",
        "uiSchema": "form-ui-schema.json"
      }
    ],
    "manifests": [
      {
        "filePath": "template.yaml"  
      }
    ],
    "resultMessage": "Cassandra database deployed successfully",
    "helpUrl": "https://github.com/YOUR_GITHUB_USERNAME/monokle-templates-plugin"
}
Enter fullscreen mode Exit fullscreen mode

⚠️ REMEMBER: Replace your name and Github username wherever mentioned.

📄File 2: Defining Form Schema

In the code above, we have defined the fields forms.schema, this will contain the form fields that we will request the user to input and are necessary to create the manifest file.

Create the file form-schema.json with the following content:

{
    "type": "object",
    "required": [
      "name",
      "replicas"
    ],
    "properties": {
      "name": {
        "type": "string",
        "default": "cassandra" 
      },
      "namespace": {
        "type": "string"
      },
      "replicas": {
        "type": "number"
      },
      "cluster_name": {
        "type": "string",
        "default": "K8Demo"
      },
      "datacenter_name": {
        "type": "string",
        "default": "datacenter1-K8Demo"
      },
      "rack_name": {
        "type": "string",
        "default": "rack1-K8Demo"
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode

📌 NOTE: required refers to the compulsary input fields, type describes the data type of input field, default is the default value of the input field.

📄File 3: Defining Form UI

Monokle uses the react-json-schema-form frontend component to render the forms for these templates. It takes the form fields definition which we just created, and a UI form definition, which we will build next.

Create a file named form-ui-schema.json, this will basically defines how the form is going to appear (titles for the fields, descriptions, etc).

{
    "name": {
      "ui:title": "Name",
      "ui:help": "The name of the generated service and deployment"
    },
    "namespace": {
      "ui:title": "Namespace",
      "ui:help": "The target namespace for the generated service and deployment",
      "ui:widget": "namespaceSelection"
    },
    "replicas": {
      "ui:title": "Replicas",
      "ui:help": "Number of pod replicas"
    },
    "cluster_name": {
      "ui:title": "Cassandra Cluster Name",
      "ui:help": "Name of the cluster"
    },
    "datacenter_name": {
      "ui:title": "Cassandra DataCenter Name",
      "ui:help": "Name of the Datacenter where data will be stored. It can be anything, for example datacenter1"
    },
    "rack_name": {
      "ui:title": "Cassandra Rack Name",
      "ui:help": "Name of the Rack where datacenter will be created. It can be anything, for example rack1"
    }
  }
Enter fullscreen mode Exit fullscreen mode

📌 NOTE: title refers to name of the input field, help describes the field, widget creates the dropdown menu.

📄File 4: Kubernetes YAML manifest template

Finally, this is where we will actually define our Cassandra StatefulSet manifest template with the placeholders that we will update with the form data. This manifest YAML file will contain the following K8s objects and resources to deploy cassandra pods:

  1. StatefulSet - to create cassandra pods
  2. StorageClass - for dynamic provisioning of Persistent Volumes
  3. Service - for connecting pods to each other and client

Create the template.yaml file with the following config:

# This is your StatefulSet to create pods
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: [[forms[0].name]]
  labels:
    app: [[forms[0].name]]
[[ forms[0].namespace ? "  namespace: " + forms[0].namespace + "\n" : ""]]
spec:
  serviceName: [[forms[0].name]]
  replicas: [[forms[0].replicas]]
  selector:
    matchLabels:
      app: [[forms[0].name]]
  template:
    metadata:
      labels:
        app: [[forms[0].name]]
    spec:
      terminationGracePeriodSeconds: 1800
      containers:
      - name: [[forms[0].name]]
        image: gcr.io/google-samples/cassandra:v13
        imagePullPolicy: Always
        ports:
        - containerPort: 7000
          name: intra-node
        - containerPort: 7001
          name: tls-intra-node
        - containerPort: 7199
          name: jmx
        - containerPort: 9042
          name: cql
        resources:
          limits:
            cpu: "500m"
            memory: 1Gi
          requests:
            cpu: "500m"
            memory: 1Gi
        securityContext:
          capabilities:
            add:
              - IPC_LOCK
        lifecycle:
          preStop:
            exec:
              command: 
              - /bin/sh
              - -c
              - nodetool drain
        env:
          - name: MAX_HEAP_SIZE
            value: 512M
          - name: HEAP_NEWSIZE
            value: 100M
          - name: CASSANDRA_SEEDS
            value: "cassandra-0.cassandra.default.svc.cluster.local"
          - name: CASSANDRA_CLUSTER_NAME
            value: [[forms[0].cluster_name]]
          - name: CASSANDRA_DC
            value: [[forms[0].datacenter_name]]
          - name: CASSANDRA_RACK
            value: [[forms[0].rack_name]]
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        readinessProbe:
          exec:
            command:
            - /bin/bash
            - -c
            - /ready-probe.sh
          initialDelaySeconds: 15
          timeoutSeconds: 5
        # These volume mounts are persistent. They are like inline claims,
        # but not exactly because the names need to match exactly one of
        # the stateful pod volumes.
        volumeMounts:
        - name: cassandra-data
          mountPath: /cassandra_data
  # These are converted to volume claims by the controller
  # and mounted at the paths mentioned above.
  # do not use these in production until ssd GCEPersistentDisk or other ssd pd
  volumeClaimTemplates:
  - metadata:
      name: cassandra-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: fast
      resources:
        requests:
          storage: 1Gi
---
# StorageClass for Persistent Volume Claim
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: k8s.io/minikube-hostpath
parameters:
  type: pd-ssd
---
# This is your Service for the pods
apiVersion: v1
kind: Service
metadata:
  labels:
    app: [[forms[0].name]]
  name: [[forms[0].name]]
[[ forms[0].namespace ? "  namespace: " + forms[0].namespace + "\n" : ""]]
spec:
  clusterIP: None
  ports:
  - port: 9042
  selector:
    app: [[forms[0].name]]
Enter fullscreen mode Exit fullscreen mode

📌 NOTE: As you can see, for placeholders we are using format [[forms[0].name]] where form[0] is used to access the form defined in monokle-template.json, and .name refers to one of our input field defined in the form schema.

👏🏻Awesome, with this step we have finally created our Monokle Template.


➡️ Uploading the Template to Github Repo

Now that we have defined our template configuration, the form definition and our manifest with its placeholders, it's time to push them to our Github Repo we made and cloned in the first step, so that we can import our template in Monokle in the later step.

Before proceeding, verify if you are in your root folder i.e monokle-templates-plugin

git add .
git commit -m "cassandra monokle template"
git push origin main
Enter fullscreen mode Exit fullscreen mode

➡️ Importing your Template in Monokle

We need to import the template form our Github repo to Monokle in our configured project.

✅Step 1:

Download Monokle from here, Open the Monokle Interface and you can find Open Pugins Manager button on the top-right corner.
Image description

✅Step 2:

Click on install pulgin. Copy the url of your template Github repo and paste it here.
Image description

Click on Download and install pulgin.

✅Step 3:

To verify if your template is successfully imported, it should appear in Plugins Manager with the name Template Pulgins
Image description

👏🏻Awesome, we have successfully imported our template. It's time to test out our custom cassandra template.

➡️ Trying out your Template

Lets use our template to create the resources required to deploy the Cassandra pods by filling up the template form.

✅Step 1:

Start a new project in monokle by selecting Start from a template
Image description

✅Step 2:

Assign the project name, I named it Awesome Monokle because it is actually amazing.
Image description

Now proceed further to Select a Template

✅Step 3:

You can find your custom template that you just imported with the name Deploy Cassandra with StatefulSet. Use this template and proceed futher to fill up the template form.
Image description

✅Step 4:

Fill up all the fields in the deployment settings or keep them to default options as required.
Image description

Click on Submit button and you can see that following resources have been created successfully.
Image description

✅Step 5:

Go back to your project. Have a look at your navigator and you can find StatefulSets, Services, and StorageClass created with the name my-cassandra, by your cassandra template.
Image description

To deploy cassandra pods to your K8s cluster, click on the Deploy button on the top-right corner in Editor.

🥳Congratulations!!🥳 Now sit back, relax and give yourself some time to appreciate that you have created your own custom template and used it on Monokel.

🚀 Feel free to contact me on my socials if you get stuck anywhere LinkedIn, Github, Twitter

🧑‍💻Happy Learning !!👩‍💻


📚 Some more resources...

1) All the files and code mentioned above can be found on my Github Repo.
2) Want to create a basic pod template? Checkout tutorial by Kunal Kushwaha and blog by Kubeshop.
3) Learn more about Monokel? Checkout their official documentation.

Top comments (0)