Chapter 5
Section titled “Chapter 5”We now have a scalable, configurable application. But there’s one last piece of the puzzle we need to solve. Our Nginx Pods are stateless—they don’t need to save any data. If a Pod is deleted, we don’t lose anything important. But what about a database, a blog with user uploads, or a metrics server? The data must survive a Pod restart.
Persistent Storage
Section titled “Persistent Storage”By default, the filesystem inside a container is ephemeral. When a Pod is destroyed, all the data written inside its container is lost forever. For stateful applications, this is a critical problem. We need a way to store data that persists independently of the Pod’s lifecycle.
In Kubernetes, this is achieved through an abstraction layer involving PersistentVolumes (PVs) and PersistentVolumeClaims (PVCs). This system cleverly separates the concerns of the cluster administrator (who manages the storage infrastructure) and the developer (who consumes the storage).
The Core Storage Components
Section titled “The Core Storage Components”- PersistentVolume (PV): A PersistentVolume is a piece of storage in the cluster that has been provisioned by an administrator. It is a resource in the cluster, just like a Node is a resource. A PV is a specific block of storage (like a Google Persistent Disk, an AWS Elastic Block Store volume, or an on-premise NFS share) that is made available to the cluster. The key point is that the PV has a lifecycle independent of any individual Pod.
- PersistentVolumeClaim (PVC): A PersistentVolumeClaim is a request for storage made by a developer. The developer doesn’t need to know the specific details of the underlying storage technology. They simply create a PVC and say, “I need 1 GiB of storage that supports being read and written by a single Pod.”
- The Binding Process: When a developer creates a PVC, Kubernetes looks for an available PV that meets the requirements of the claim (e.g., size, access mode). If it finds a suitable PV, it “binds” the PVC to the PV. The developer’s claim is now fulfilled, and they can use that storage in their Pods.
Analogy: Think of the administrator as a hotel manager who prepares a set of rooms (the PVs). The developer is a guest who makes a reservation (the PVC), requesting a certain type of room. The hotel system (Kubernetes) matches the reservation to an available room and gives the key to the guest.
Dynamic Provisioning with StorageClasses
Section titled “Dynamic Provisioning with StorageClasses”Manually pre-provisioning PVs can be cumbersome. The modern approach is dynamic provisioning using a StorageClass.
A StorageClass provides a way for administrators to define different “classes” of storage they offer (e.g., fast-ssd, slow-hdd, backup-storage). When a developer’s PVC requests a specific StorageClass, Kubernetes automatically triggers a cloud provider or storage plugin to dynamically create a brand new PV just for that claim. Most Kubernetes environments, including Minikube, come with a default StorageClass set up, making this process seamless.
This is the relationship:
+-----------+ +-------------------------+ +-------------------+ +-------------------+| Pod |------>| PersistentVolumeClaim |----->| PersistentVolume |----->| Actual Storage || | uses | (Developer's Request: | binds| (Admin's Resource)| reps.| (GCP Disk, AWS EBS|| | | "I need 1Gi of | to | "Here is 1Gi") | | NFS, etc.) || | | storage") | | | | |+-----------+ +-------------------------+ +-------------------+ +-------------------+-
Create a PersistentVolumeClaim (PVC) We’ll request 1 GiB of storage. Since Minikube has a default
StorageClassnamedstandard, a PV will be automatically created and bound for us.Create a file named
pvc.yaml:pvc.yaml apiVersion: v1kind: PersistentVolumeClaimmetadata:name: my-storage-claimspec:# This requests the default storage classstorageClassName: standard# Defines how the volume can be mounted. ReadWriteOnce means# it can be mounted as read-write by a single Node.accessModes:- ReadWriteOnceresources:requests:# The desired size of the storagestorage: 1GiApply it:
Terminal window kubectl apply -f pvc.yamlCheck the status. You’ll see it’s
Bound, meaning it’s ready to be used.Terminal window kubectl get pvc# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE# my-storage-claim Bound pvc-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d 1Gi RWO standard 10s -
Create a Pod That Uses the PVC Now, create a Pod that mounts this claim into its filesystem.
Create a file named
pod-with-storage.yaml:pod-with-storage.yaml apiVersion: v1kind: Podmetadata:name: stateful-podspec:containers:- name: my-appimage: alpine # A very small linux image# Keep the container running with a long-running commandcommand: ["/bin/sh", "-c", "sleep 3600"]# This is where we mount the volume into the containervolumeMounts:- name: my-persistent-storagemountPath: /data# This section defines the volume source, linking it to our PVCvolumes:- name: my-persistent-storagepersistentVolumeClaim:claimName: my-storage-claimApply it:
kubectl apply -f pod-with-storage.yaml. -
Write Data to the Volume Let’s get a shell inside the running Pod and write a file to our mounted directory
/data.Terminal window # Get a shell inside the podkubectl exec -it stateful-pod -- /bin/sh# Inside the pod's shell, navigate to the mount point and create a file/ # cd /data/data # echo "My data has persisted!" > persistent.txt/data # cat persistent.txtMy data has persisted!/data # exit -
Simulate Pod Failure Now, let’s delete the Pod.
Terminal window kubectl delete pod stateful-podThe Pod is gone. But is our data? No. The PVC and the PV it is bound to are separate objects and are still there:
kubectl get pvc. -
Recreate the Pod and Verify the Data Let’s create a new Pod using the exact same definition. Since it refers to the same PVC, it will mount the same underlying storage.
Terminal window kubectl apply -f pod-with-storage.yamlNow,
execinto this new Pod and check for the file:Terminal window kubectl exec -it stateful-pod -- /bin/sh# Inside the new pod's shell/ # cat /data/persistent.txtMy data has persisted!Success! The data survived the complete destruction and recreation of the Pod.
Key Takeaways for Chapter 5:
Section titled “Key Takeaways for Chapter 5:”- For stateful applications, you need storage that exists beyond the life of a Pod.
- You use a PersistentVolumeClaim (PVC) to request storage for your application.
- The PVC is mounted as a volume inside your Pod’s containers.
- In modern Kubernetes, StorageClasses handle the dynamic provisioning of PersistentVolumes (PVs) to satisfy your claims.
We have now covered all the core Kubernetes objects needed to deploy, configure, expose, and persist a complete application. The final chapter will introduce a tool that makes managing all these YAML files much, much easier.
Let me know when you’re ready for our final chapter: Chapter 6: Packaging Your Application with Helm.