Kubernetes Beginner’s Guide Part 5: Persistent Storage

In this installment of our Kubernetes blog series, we turn our attention to persistent storage. Unlike ephemeral storage, which is tied to the lifecycle of a pod, persistent storage in Kubernetes allows data to be retained across pod restarts and even node failures. This is crucial for stateful applications like databases. We’ll explore how to implement persistent storage using Persistent Volumes (PVs) and Persistent Volume Claims (PVCs) in a local Kubernetes setup. If you landed here directly, please check out the previous articles in this series:

Understanding Persistent Volumes (PVs) and Persistent Volume Claims (PVCs)

In Kubernetes, a Persistent Volume (PV) is a piece of storage in the cluster that has been provisioned by an administrator or dynamically provisioned using Storage Classes. A Persistent Volume Claim (PVC) is a request for storage by a user. It is similar to a pod in that pods consume node resources and PVCs consume PV resources.

Creating a Persistent Volume

For this example, we’ll create a local Persistent Volume. In a production environment, you would typically use network-attached storage.

Create a Persistent Volume (PV) YAML File (local-pv.yaml):

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    # Use a valid path that exists in your filesystem, below.
    path: /Users/tvaidyan/Development/k8s-explorations/mnt/data 
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - [YourNodeName]

Replace [YourNodeName] with the name of your node. You can get the node name by running kubectl get nodes. Also note the path specification. Replace the path in my configuration to something that exists on your filesystem. Next, create this persistent volume by applying the yaml configuration, above.

kubectl apply -f local-pv.yaml

Creating a Persistent Volume Claim (PVC)

Next, let’s create a Persistent Volume Claim (PVC). Create a new local-pvc.yaml file and copy the following configuration into it.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: local-storage

Apply the PVC configuration:

kubectl apply -f local-pvc.yaml

Utilizing a PVC Within a Pod

Next, let’s create a configuration for creating a pod. We’ll use this new PVC that we created by attaching it to this pod. Create an nginx-pod.yaml file and copy the following contents.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: storage
  volumes:
    - name: storage
      persistentVolumeClaim:
        claimName: local-pvc

Create the pod by applying the above configuration:

kubectl apply -f nginx-pod.yaml

Verify that the Persistent Volume is bound:

kubectl get pv

You should see that the PV local-pv is bound to the PVC local-pvc. Next, verify that the pod is using this PVC.

kubectl describe pod nginx-pod

Inspect the output, and inspect the Volumes and the Mounts sections. Here you can verify that the volume is mounted at the correct path inside the container. This ensures that your pod is utilizing persistent storage as intended.

But does it persist?

The whole objective of this exercise is to create a persistent storage that survives the lifetime of a pod. Pods are ephemeral by nature, susceptible to restarts and deletions. We want to make sure that important data is maintained even in those circumstances.

Let’s experiment by creating a test file in the persistent volume. Exec into the nginx pod:

kubectl exec -it nginx-pod -- /bin/sh

You are now at the bash terminal within your nginx pod. Let’s create a new file, like so:

echo "Hello, persistent storage!" > /usr/share/nginx/html/index.html

Exit the pod:

exit

Simulate a pod failure or deletion:

kubectl delete pod nginx-pod

You can verify that your pod got deleted by issuing the kubectl get pods command. With the pod deleted, navigate to the directory that you specified in the local-pv.yaml file above. In my case it was /Users/tvaidyan/Development/k8s-explorations/mnt/data. You should see an index.html file there. It should have the phrase “Hello, persistent storage!” within it.

Conclusion

Congratulations! You’ve successfully implemented persistent storage in Kubernetes using Persistent Volumes and Persistent Volume Claims. This setup allows your applications to retain data even if the pods are deleted or moved to a different node. In the next article, we’ll dive deeper into securing your Kubernetes cluster. Stay tuned!

Leave a Comment

Your email address will not be published. Required fields are marked *