September 7, 2024| 0 minute read

A hands-on demonstration on how to add Persistent Storage to Deployment

Tutorial Image

Source: cajieh.com

Introduction

In this tutorial, we’ll demonstrate how to add persistent storage to Kubernetes deployment using Persistent Volume (PV) and Persistent Volume Claim (PVC). A Pod, which is the lowest level resource in Kubernetes, provides an environment for running containers along with their application and dependencies, is ephemeral in nature. This means any data stored in the pod will be lost when the pod terminates, crashes, or restarts. Therefore, there is a need to persist the application data in such cases to prevent the loss of meaningful data. Kubernetes addresses this issue by using persistent volumes to keep the data stored when the pod terminates, crashes, or restarts.

For demonstration purposes, we’ll first create a Deployment with one replica(Pod) using the nginx image and write to its ephemeral volume, which is the default storage for every pod but is non-persistent. We will then experiment to see that the data is lost when the pod terminates, crashes, or restarts. Next, we’ll add persistent storage using PV and PVC to the Deployment and experiment with it to see that the data is persisted when the pod terminates, crashes, or restarts. Let’s get started

Pre-requisite:

  • Basic knowledge of Container technology and kubernetes are required
  • Proficient in the use of command line tools i.e. Bash terminal
  • Access to a Kubernetes cluster if you want to experiment with the example in this tutorial

What is Persistent Volume (PV)?

The Persistent Volume is a Kubernetes storage resource in a cluster provisioned by an adminstrator or StorageClass dynamally, and it is use to store application data persistently when the pod terminates, crashes, or restarts.

What is Persistent Volume Claim (PVC)?

The Persistent Volume Claim is a Kubernetes resource for requesting a given amount of storage reserved by the PV. The PVC can request a specific size of storage and access modes such as ReadWriteOnce and ReadWriteOncePod.

Demonstration of Kubernetes Persistent Storage using PV and PVC

Let’s start by creating a Deployment without associating it with persistent storage using the following imperative command as shown below.

kubectl create deploy nginx-deploy --image=nginx
deployment.apps/nginx-deploy created

View the deployment and pod

kubectl get deploy,pod
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deploy   1/1     1            1           54s
NAME                                READY   STATUS    RESTARTS   AGE
pod/nginx-deploy-854b9d5bdb-lrglt   1/1     Running   0          54s

Exec into the pod and write a text message in the volume.

kubectl exec -it nginx-deploy-854b9d5bdb-lrglt  -- sh 

Note your pod name would be different since this is auto-generated.

View the default nginx image "index.html" page. Note: The output is shortened for brevity.

# cat  /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<body>
<h1>Welcome to nginx!</h1>
---
</body>
</html>

Overwrite the default nginx image page

echo "This message will be lost on pod terminates, restart or crash" > /usr/share/nginx/html/index.html

View the message using the cat command

cat  /usr/share/nginx/html/index.html
This message will be lost on pod terminates, restart or crash

Exit the pod

exit

Delete the pod

kubectl delete po nginx-deploy-854b9d5bdb-lrglt
pod "nginx-deploy-854b9d5bdb-lrglt" deleted

Run the kubctl get po command again to retrieve the newly created pod name after the previous pod was delete.

kubectl get po
NAME                                READY   STATUS    RESTARTS   AGE
pod/nginx-deploy-854b9d5bdb-vh9tl   1/1     Running   0          67s

You can see that the name is different from the previous pod name because every time a new pod is created from a Pod controller resource such as deployment a new name is auto-generated.

Exec into the pod again and try to view the message. Note: The output is shortened for brevity.

kubectl exec -it nginx-deploy-854b9d5bdb-vh9tl  -- sh

cat /usr/share/nginx/html/index.html

<!DOCTYPE html>
<html>
<body>
<h1>Welcome to nginx!</h1>
---
</body>
</html>

The message is lost and it returns default nginx message we overwrote previously because the default volume of the pod is ephemeral and the data gets lost on pod terminates, restart or crash.

Add persistent storage resources to persist the data on Pod restart.

Let's add persistent storage resources to the cluster and update the Deployment to utilize them.

Create a PV and PVC using manifest files below: pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

Apply the pv.yaml and pvc.yaml manifests

kubectl create -f pv.yaml
persistentvolumeclaim/pv-claim created
kubectl create -f pvc.yaml 
persistentvolume/pv-volume created

View the pv and pvc

k get pv,pvc
NAME                         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pv-volume   5Gi        RWO            Retain           Bound    default/pv-claim   manual         <unset>                          72s

NAME                             STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/pv-claim   Bound    pv-volume   5Gi        RWO            manual         <unset>                 79s

From the output, the PVC is correctly Bound to the PV we created. Next, let's update the nginx-deploy to use the PVC bound to the PV to persist data.

Update the nginx-deploy Deployment

kubectl edit deploy nginx-deploy 

This command will open the nginx-deploy Deployment in the configured editor, i.e., vim. Let’s update the nginx-deploy to include PVC specification properties. See the nginx-deploy Deployment specification section relevant to our purpose, with the PVC additions below:

template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-deploy
    spec:
      volumes:                # PVC 'volume' changes start
      - name: data-pvc-store
        persistentVolumeClaim:
          claimName: pv-claim   # PVC 'volume' changes end
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: nginx
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:               # PVC 'volumeMounts' changes start
        - mountPath: "/usr/share/nginx/html"
          name: data-pvc-store       # PVC 'volumeMounts' changes end

Thenginx-deploy Deployment resource now include the PVC volumes and volumeMounts specifications for configuring a Pod to use PV for storage.

Save and exit

Caveat: You may encounter the following error, which is expected.

error: deployments.apps "nginx-deploy" is invalid
A copy of your changes has been stored to "/tmp/kubectl-edit-905151300.yaml"
error: Edit cancelled, no valid changes were saved.

Use the replace and --force commands to re-apply the change as shown below:

k create -f /tmp/kubectl-edit-905151300.yaml    
deployment.apps/nginx-deploy deleteted
deployment.apps/nginx-deploy created

View and exec into the pod

k get po
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-574f47d89b-npzdd   1/1     Running   0          103s
k exec -it nginx-deploy-574f47d89b-npzdd -- sh

Write a message to the pod container

echo "This message will be persisted on pod terminates, restart or crash" > /usr/share/nginx/html/index.html

View the message using the cat command

cat  /usr/share/nginx/html/index.html
This message will be persisted on pod terminates, restart or crash

Exit the pod

exit

Delete the pod

k delete po nginx-deploy-574f47d89b-npzdd
pod "nginx-deploy-574f47d89b-npzdd" deleted

Run the kubectl get po command again to retrieve the newly created pod name after the previous pod was delete.

kubectl get po
k get po
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-574f47d89b-h5f4r   1/1     Running   0          27s

Exec into the pod again and confirm that the the message is persisted and not lost like in the previous scenario without PV/PVC attached to the Deployment Pod

k exec -it nginx-deploy-574f47d89b-h5f4r -- sh
cat /usr/share/nginx/html/index.html
This message will be pesisted on pod terminates, restart or crash

Awesome! The message “This message will be pesisted on pod terminates, restart or crash” is persisted, and displayed and is it is not lost after the Pod was deleted, and recreated.

Conclusion:

The tutorial demonstrates how to use Kubernetes Persistent Volume (PV) and Persistent Volume Claim (PVC) to persist data in a Kubernetes deployment. It starts by creating a deployment with ephemeral storage, showing that data is lost when the pod restarts. Then, it adds persistent storage using PV and PVC, updates the deployment to use this storage, and verifies that data persists across pod restarts.

I hope this helps! Go to the contact page and let me know if you have any further questions.

Happy learning!

Additional resources:

Want more tutorials?

Subscribe and get notified whenever new tutorials get added to the collection.

By submitting this form, I agree to cajieh.com Privacy Policy.