Persistent Volumes.

What is Kubernetes Volume? Kubernetes volume is a directory that is bound to the pod. Kubernetes volume dies along with the pod. So we can not store any data which we need after the pod’s lifecycle.

What is Kubernetes Persistent Volume?

Kubernetes Persistent volume is the solution to the issues we faced in the Kubernetes volume. Kubernetes persistent volume remains after the pod lifecycle. So it can be bound to another pod and use the data.

Different Types of Kubernetes Volumes.

PersistentVolume types are implemented as plugins. Kubernetes currently supports the following plugins: Please refer to this link to have a detailed view on this topic, there are many varieties of persistent volume which is supported by Kubernetes

  • awsElasticBlockStore - AWS Elastic Block Store (EBS)
  • azureDisk - Azure Disk
  • azureFile - Azure File
  • cephfs - CephFS volume
  • cinder - Cinder (OpenStack block storage) (deprecated)
  • csi - Container Storage Interface (CSI)
  • fc - Fibre Channel (FC) storage
  • flexVolume - FlexVolume
  • flocker - Flocker storage
  • gcePersistentDisk - GCE Persistent Disk
  • glusterfs - Glusterfs volume
  • hostPath - HostPath volume (for single node testing only; WILL NOT WORK in a multi-node cluster; consider using local volume instead)
  • iscsi - iSCSI (SCSI over IP) storage
  • local - local storage devices mounted on nodes.
  • nfs - Network File System (NFS) storage
  • photonPersistentDisk - Photon controller persistent disk. (This volume type no longer works since the removal of the corresponding cloud provider.)
  • portworxVolume - Portworx volume
  • quobyte - Quobyte volume
  • rbd - Rados Block Device (RBD) volume
  • scaleIO - ScaleIO volume (deprecated)
  • storageos - StorageOS volume
  • vsphereVolume - vSphere VMDK volume

Volume Demo.

Create a pod to test data persistency.

rajith@k8s-master:~$ kubectl run test-data --image=busybox --command sleep "5000" 
pod/test-data created
rajith@k8s-master:~$
  • Pod name is test-data.
  • The image used to create the Pod is busybox.
  • Pod lifecycle end if there is no running process available.
  • The busybox image does not have any process in the startup.
  • We are executing a sleep command to make it alive till the completion of our test.
rajith@k8s-master:~$ kubectl get pods 
NAME        READY   STATUS    RESTARTS   AGE
test-data   1/1     Running   0          10s
rajith@k8s-master:~$ 

The pod got created and it started.

Connect to the pod in the Kubernetes cluster

To connect to the pod in the Kubernetes cluster we use the command “ kubectl exec”.

rajith@k8s-master:~$ kubectl exec -it test-data -- sh 
/ # 
/ # uname -a
Linux test-data 5.4.0-73-generic #82-Ubuntu SMP Wed Apr 14 17:39:42 UTC 2021 x86_64 GNU/Linux
/ # hostname 
test-data
/ # 

We connected to the pod. The hostname of the pod is ‘test-data’

Place data to test.

We will create a directory and place some data on it.

/ # mkdir /data
/ # cd /data
/data # touch testfile1
/data # echo "My data to Test the Persistency" > MyDataFile.txt
/data # cat MyDataFile.txt
My data to Test the Persistency
/data # 
command terminated with exit code 130

Placed the data in the pod and disconnected from it.

rajith@k8s-master:~$ kubectl get pods 
NAME        READY   STATUS    RESTARTS   AGE
test-data   1/1     Running   0          2m56s
rajith@k8s-master:~$ 

Delete and recreate the pod.

The pod ‘test-data’ is still running.Delete and recreate it.

rajith@k8s-master:~$ kubectl delete pod test-data
pod "test-data" deleted
rajith@k8s-master:~$ kubectl run test-data --image=busybox --command sleep "5000"
pod/test-data created

The pod ‘test-data’ is recreated, we will see the data in it.

rajith@k8s-master:~$ kubectl exec -it test-data -- sh
/ # ls -ld /data
ls: /data: No such file or directory
/ # ls -l /data
ls: /data: No such file or directory
/ # 
command terminated with exit code 1
rajith@k8s-master:~$ 

The data directory itself is not available.

create the pod with volume.

We will create the pod ‘test-data’ with the pod definition file given below.

rajith@k8s-master:~$ cat TestData.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-data
spec:
  containers:
  - image: busybox
    name: busybox
    command: [ "sleep" , "4800" ]
    volumeMounts:
    - mountPath: /data
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /mnt/data
      # this field is optional
      type: DirectoryOrCreate
rajith@k8s-master:~$

In addition to the ‘sleep’ command. We have added the volume entry also in this pod definition file. Here, The volume type is hostPath.

  • If the directory ‘ /mnt/data’ is not present in the host ( worker node) it will create.
  • The volume name is ‘test-volume’.
  • On the pod, the host directory ‘/mnt/data’ is mounted under ‘/data’.

We will go ahead and create the pod.

rajith@k8s-master:~$ kubectl create -f TestData.yaml 
Error from server (AlreadyExists): error when creating "TestData.yaml": pods "test-data" already exists
rajith@k8s-master:~$ 

What happened? 🤔 Yes, we did not delete the pod ‘test-data’.

We can not run two pods with the same name under the same namespace.

Delete the pod and recreate it.

rajith@k8s-master:~$ kubectl delete pod test-data 
pod "test-data" deleted
rajith@k8s-master:~$ kubectl create -f TestData.yaml 
pod/test-data created
rajith@k8s-master:~$ kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
test-data   1/1     Running   0          8s
rajith@k8s-master:~$

Place the data under the volume.

Connect to the pod ‘test-data’.

rajith@k8s-master:~$ kubectl exec -it test-data -- sh
/ # ls -l 
total 40
drwxr-xr-x    2 root     root         12288 Jun  7 17:34 bin
drwxr-xr-x    2 root     root          4096 Jun 27 03:41 data
drwxr-xr-x    5 root     root           360 Jun 27 03:42 dev
drwxr-xr-x    1 root     root          4096 Jun 27 03:42 etc
drwxr-xr-x    2 nobody   nobody        4096 Jun  7 17:34 home
dr-xr-xr-x  171 root     root             0 Jun 27 03:42 proc
drwx------    1 root     root          4096 Jun 27 03:43 root
dr-xr-xr-x   13 root     root             0 Jun 27 03:42 sys
drwxrwxrwt    2 root     root          4096 Jun  7 17:34 tmp
drwxr-xr-x    3 root     root          4096 Jun  7 17:34 usr
drwxr-xr-x    1 root     root          4096 Jun 27 03:42 var
/ # 

You could see the directory “/data” is already present in the pod.

/ # df -Ph /data
Filesystem                Size      Used Available Capacity Mounted on
/dev/mapper/vgvagrant-root           61.3G      3.5G     54.7G   6% /data
/ # 

Note: - The ‘/data’ mounted from the worker node.

We will place some files under the ‘/data’ directory.

/ # cd /data/
/data # ls -l 
total 0
/data # touch testfile1
/data # echo "My data to Test the Persistency" > MyDataFile.txt
/data # ls -l 
total 4
-rw-r--r--    1 root     root            32 Jun 27 03:41 MyDataFile.txt
-rw-r--r--    1 root     root             0 Jun 27 03:40 testfile1
/data # cat MyDataFile.txt 
My data to Test the Persistency
/data # 

Recreate the pod with the volume.

Now the files are placed under the pod ‘test-data’. We will recreate the pod.

rajith@k8s-master:~$ kubectl delete pod test-data 
pod "test-data" deleted
rajith@k8s-master:~$ 
rajith@k8s-master:~$ kubectl create -f TestData.yaml 
pod/test-data created
rajith@k8s-master:~$ kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
test-data   1/1     Running   0          8s
rajith@k8s-master:~$

Connect to the pod and verify the data

The pod ‘test-data’ is recreated. We will connect to it and verify the data.

rajith@k8s-master:~$ kubectl exec -it test-data -- sh
/ # df -Ph /data
Filesystem                Size      Used Available Capacity Mounted on
/dev/mapper/vgvagrant-root           61.3G      3.5G     54.7G   6% /data
/ #

The directory is present and it is mounted. We will verify the data.

/ # cd /data
/data # ls -l 
total 4
-rw-r--r--    1 root     root            32 Jun 27 03:41 MyDataFile.txt
-rw-r--r--    1 root     root             0 Jun 27 03:40 testfile1
/data # cat MyDataFile.txt 
My data to Test the Persistency
/data # 

Yes, it is there.This is how we will preserve the data.

But the volume ‘hostPath’ is bounded to the worker node which the pod is running. If the pod is recreated/relocated to another node then the data will be lost. To avoid such a situation during our demo I made the other two nodes unschedulable.

rajith@k8s-master:~$ kubectl get node
NAME         STATUS                     ROLES                  AGE   VERSION
k8s-master   Ready                      control-plane,master   25d   v1.21.1
node-1       Ready,SchedulingDisabled   <none>                 25d   v1.21.1
node-2       Ready,SchedulingDisabled   <none>                 25d   v1.21.1
node-3       Ready                      <none>                 25d   v1.21.1
rajith@k8s-master:~$ kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP          NODE     NOMINATED NODE   READINESS GATES
test-data   1/1     Running   1          85m   10.32.0.2   node-3   <none>           <none>
rajith@k8s-master:~$ 

Our demo was happening under node-3, you can see the status of the other nodes. Those are not schedulable.

If you need relocatable pods then you need to choose the other solutions which support that.

Persistent Volume definition file

We will have a look at the persistent volume definition file.

rajith@k8s-master:~$ cat PersistentVolume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-vol
spec:
  capacity:
    storage: 10Mi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
rajith@k8s-master:~$ 

This defenition file is self explnatory.

  • The name of the volume is ‘my-vol’.
  • The capacity is 10Mi.
  • The host path is “/mnt/data”.

Create the Persistent Volume

We will create the Persistent volume.

rajith@k8s-master:~$ kubectl create -f PersistentVolume.yaml
persistentvolume/my-vol created
rajith@k8s-master:~$ kubectl get persistentvolume
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
my-vol   10Mi       RWO            Retain           Available                                   4s
rajith@k8s-master:~$ 

A persistent volume looks like this. If we need to utilize it, we need to create a ‘persistent volume claims’ and mount it to the corresponding pod as we have done in our demo. We will look into those details in our upcoming series.

With this, we completed our introductory series. Thanks for joining me. We will meet again in the series for Pod .. – Need to replace the name.