Kubernetes: A Complete Guide - Chapter 5

In the previous chapter, we read about how to create a Sample Node.js Application on EKS. In this chapter, we are gonna find out how to handle applications such as MySQL or Cassandra or Redis since they have storage involved.

Suppose, we are trying to provision, say for example a MySQL Service on Kubernetes, what happens to the data if the MySQL Pod goes down momentarily? Does the data get lost as well? We are gonna learn how to handle such kinds of services.

So these type of services are called StatefulSets which have a persistent storage attached to them. Basically, we create a volume when the Pod gets created and it gets allocated to the Pod. If the MySQL Service Pod accidentally goes down, the volume gets detached and when the new MySQL Pod spawns up, the existing volume gets attached. Let's see how we can make it work.

Considering our EKS cluster with node(s) are running, we are gonna create a file called mysql-pv.yml In this example, we are gonna create volumes and map it to MySQL Service.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 15Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/src"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 15Gi

In the above code, we can modify the storage to be allocated based on our use case. Also, there are 3 types of Access Modes. They are:-

  • ReadWriteOnce: The volume can be mounted as read-write by a single node
  • ReadOnlyMany: The volume can be mounted read-only by many nodes
  • ReadWriteMany: The volume can be mounted as read-write by many nodes

What is the difference between Persistent Volume and Persistent Volume Claim ?
A Persistent Volume (PV) is the "physical" volume on the host machine( in our case the node running on AWS) that stores our persistent data. A Persistent Volume Claim (PVC) is a request for the platform to create a PV for us, and then we can attach PV(s) to our pods via a PVC.

Now, let us create the PV and the PVC. We use the following command:-

kubectl create -f mysql-pv.yml

Next, we create MySQL Deployment file. Create a file called mysql-deployment.yml and add the following code:-

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:8.0
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "qwertyuiop"
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

The above code will pull a mysql8.0 from Docker hub and create a deployment for the same. It'll configure the default mysql password as "qwertyuiop" which is the value we have mentioned for the key MYSQL_ROOT_PASSWORD .

Note: In production use case, we need to make use of secrets which we will discuss in later chapters.

Also, it'll map the Pod to the mysql-pv-claim PVC, which we created earlier.

Let's run the above Deployment file by running the command:-

kubectl apply -f mysql-deployment.yaml

Next, let's create a mysql-service.yml file which will create the MySQL Service.

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
  clusterIP: None

If we mention clusterIP as none, the service will not loadbalance the request amongst all replicas of the Deployment. In such a case, we have to manually fetch the IP address of the Pod in order to connect to the MySQL Pod.

To run this, we can run the following command:-

kubectl apply -f mysql-service.yml

To access the MySQL instance, access the pod created by the deployment.

kubectl get pods

This will give us the name of the currently running MySql pod.

kubectl exec -it <mysql_pod_name> /bin/sh

You'll be able to enter the MySQL Pod, now let us run the MySQL cli command to login to our database:-

mysql -pqwertyuiop

where qwertyuiop is the password which we defined in the deployment file.

Voila, now we can create databases, tables, users etc.

Note: Even if the pod is deleted the data will still remain as long as the volume is not deleted.

Similarly, this is how we will handle Services which are StatefulSets like Cassandra, Redis etc.

In the next chapter, we are gonna learn how to handle Secrets i.e. sensitive information like Passwords in Kubernetes. Cheers!

Abhishek Roy

Abhishek Roy

DevOps Engineer who aims to automate and simplify stuff related to infra and CI/CD.
Kolkata, India