In our journey so far, we've deployed an application, configured it with ConfigMaps
and Secrets
, and exposed it to the world. Our application is configurable and accessible. But it has a fatal flaw: it is stateless.
The Nginx container we're running doesn't need to save any data. But what if we were running a database, a blog, or a user profile service?
By default, the filesystem inside a container is ephemeral. When a Pod crashes or is restarted, it's replaced with a brand new one with a fresh, empty filesystem. Any data saved in the old Pod is gone forever. This is a dealbreaker for almost any real-world application.
To solve this, Kubernetes has a powerful storage model that allows data to live independently from the lifecycle of a Pod.
The Kubernetes Storage Abstraction
To untangle the complexities of storage, Kubernetes provides a clear separation of concerns between the cluster administrator who provisions storage and the developer who consumes it. This is managed by three key objects.
Let's use an analogy: The Cloud Vending Machine.
-
PersistentVolume (PV):
- What it is: A
PersistentVolume
is a piece of storage in the cluster that has been provisioned by an administrator. It is a cluster resource, just like a Node is a CPU/memory resource. - Analogy: The PVs are the actual items stocked inside the vending machine (e.g., a "10GB Fast SSD" bar, a "100GB Slow HDD" coil). They are the real supply of storage.
- What it is: A
-
PersistentVolumeClaim (PVC):
- What it is: A
PersistentVolumeClaim
is a request for storage by a user. It's like a Pod consuming Node resources; a PVC consumes PV resources. - Analogy: The PVC is you making a selection on the vending machine. You press the button for "B4," which corresponds to the "10GB Fast SSD." You don't care which specific bar it is, just that it meets your request.
- What it is: A
-
StorageClass:
- What it is: A
StorageClass
provides a way for administrators to describe the "classes" of storage they offer. This allows for the dynamic provisioning of volumes. - Analogy: The
StorageClass
is the catalog on the front of the vending machine that says, "All items in row 'B' are Fast SSDs" and "All items in row 'D' are Slow HDDs." When you request a "Fast SSD," it knows where to look.
- What it is: A
The workflow is simple:
- As a user, you create a PVC manifest asking for a certain size and type of storage.
- Kubernetes reads your claim and finds a PV that can satisfy it.
- It then "binds" the PV to your PVC, reserving it for you.
- You can then mount this claim into your Pod as a volume.
Hands-On: Giving Our Pod a Memory
Let's give our Nginx Pod a persistent place to store its website files.
Step 1: Create the PersistentVolumeClaim
First, we need to request the storage. Create a file named pvc.yaml
.
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
-
accessModes
: This defines how the volume can be mounted.ReadWriteOnce
means it can be mounted as read-write by a single Node. This is the most common mode. -
resources.requests.storage
: We are requesting 1 Gibibyte of storage.
Step 2: Update the Deployment to Use the Claim
Now we need to tell our Pod to mount and use this claimed volume. We do this by adding two sections to our deployment.yaml
: a volumes
list for the Pod and a volumeMounts
list for the container.
Here is the complete, updated deployment.yaml
:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
# This section defines a volume named 'nginx-storage' that comes from our PVC
volumes:
- name: nginx-storage
persistentVolumeClaim:
claimName: nginx-pvc
containers:
- name: nginx-web-server
image: nginx
# This section mounts the volume into the container at a specific path
volumeMounts:
- name: nginx-storage
mountPath: /usr/share/nginx/html
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secret
-
spec.volumes
: This creates a named volume for our Pod callednginx-storage
and specifies that its source is the PVC namednginx-pvc
. -
spec.containers.volumeMounts
: This tells thenginx-web-server
container to take the volume namednginx-storage
and mount it at the path/usr/share/nginx/html
. This is the directory where Nginx serves its default files.
Step 3: Apply and Verify
Let's apply our changes.
# Create the claim first
kubectl apply -f pvc.yaml
# Update the deployment
kubectl apply -f deployment.yaml
Check the status of your claim:
kubectl get pvc
You should see that its STATUS
is Bound
. This means Kubernetes has successfully provisioned a PV and attached it to our claim.
The Proof of Persistence
Now for the magic trick. We will write a file to our mounted volume, delete the Pod, and see if the file survives.
- Get your Pod's name:
kubectl get pods
# Find the name of your running 'hello-nginx' pod
- Write a file inside the Pod's mounted volume:
(Replace
<your-pod-name>
with the correct name)
kubectl exec <your-pod-name> -- bash -c 'echo "Persistence Works!" > /usr/share/nginx/html/index.html'
We just overwrote the default Nginx welcome page with our own message.
- Delete the Pod to simulate a crash:
kubectl delete pod <your-pod-name>
Wait for the new Pod to be created:
Runkubectl get pods
again. You'll see the old PodTerminating
and a new oneRunning
. Get the name of this new Pod.Check for the file in the new Pod:
kubectl exec <new-pod-name> -- cat /usr/share/nginx/html/index.html
The output should be:
Persistence Works!
It worked! The Deployment created a completely new Pod, but because our PersistentVolumeClaim
was mounted, the data survived the "crash." Our application is now stateful.
What's Next
Our application is now running, configured, exposed, and stateful. But is it healthy?
Right now, Kubernetes knows if a Pod's container is Running
, but it has no idea if the application inside the container has crashed or is stuck in a loop. It might be running, but unable to serve traffic.
In the next part, we'll learn how to give Kubernetes deeper insight into our application's health using Health Probes. We'll teach it how to know the difference between "alive" and "ready to receive traffic."
Top comments (0)