A hands-on demonstration on how to add Persistent Storage to Deployment
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!