Persistence in Kubernetes may seem complicated at first, but it is essential for ensuring that your data remains safe and available even when containers restart or move to different nodes. In this guide, I will explain step by step how to configure persistence in Kubernetes using clear and detailed examples.
What Is Persistence in Kubernetes?
In Kubernetes, persistence refers to the ability to keep data through container restarts and move that data between different nodes in the cluster. Without persistence, data stored in a container would be lost when the container shuts down or restarts.
Volumes in Kubernetes
A Kubernetes volume is similar to a Docker volume: it is a way to mount a directory, from the host or an external storage system, inside a container. However, Kubernetes provides more volume types and configuration options.
Simple Volume Example
apiVersion: v1
kind: Pod
metadata:
name: simple-pod
spec:
containers:
- name: mycontainer
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html-volume
volumes:
- name: html-volume
emptyDir: {}
In this example, we defined a Pod with a container that uses the nginx image. We mounted an empty volume, emptyDir, at /usr/share/nginx/html. emptyDir means that the volume is created when the Pod is assigned to a node and deleted when the Pod is deleted.
HostPath: The Equivalent of Docker Bind Mounts
For those familiar with Docker bind mounts, Kubernetes provides a similar option called hostPath. This lets you mount a directory or file from the file system of the node where the Pod is running.
hostPath Example
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: mycontainer
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html-volume
volumes:
- name: html-volume
hostPath:
path: /data/html
type: Directory
Here, the hostPath volume mounts the host directory /data/html at /usr/share/nginx/html in the container. This can be useful for accessing specific host files, but it must be used carefully because of possible security and portability implications.
Persistent Volumes (PV) and Persistent Volume Claims (PVC)
For more robust and flexible persistence, Kubernetes uses Persistent Volumes (PV) and Persistent Volume Claims (PVC).
What Is a Persistent Volume (PV)?
A PV is a storage resource in the cluster that exists independently of Pods. Cluster administrators create PVs, and users consume them through Persistent Volume Claims (PVCs).
Persistent Volume Example
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-example
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data/pv-example"
In this example, we defined a PV called pv-example with a capacity of 10GiB. accessModes is set to ReadWriteOnce, which means that only one node can mount the volume in read/write mode at a time. The volume is backed by the /mnt/data/pv-example directory on the host.
What Is a Persistent Volume Claim (PVC)?
A PVC is a storage request made by a user. Similar to how Pods consume resources from a node, PVCs consume available PVs.
Persistent Volume Claim Example
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-example
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
In this example, we defined a PVC called pvc-example that requests 10GiB of storage with ReadWriteOnce access.
Using PVCs in Pods
To use a PVC in a Pod, simply reference it in the Pod’s volume configuration.
Pod Using a PVC Example
apiVersion: v1
kind: Pod
metadata:
name: pvc-pod
spec:
containers:
- name: mycontainer
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html-volume
volumes:
- name: html-volume
persistentVolumeClaim:
claimName: pvc-example
Here, the pvc-pod Pod mounts the pvc-example PVC at /usr/share/nginx/html inside the nginx container.
Configuring a Database with Persistence
For applications such as WordPress, you need storage not only for application files but also for the database.
Complete MySQL Deployment and PVC Example
MySQL Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.7
name: mysql
env:
- name: MYSQL_DATABASE
value: exampledb
- name: MYSQL_USER
value: exampleuser
- name: MYSQL_PASSWORD
value: examplepass
- name: MYSQL_ROOT_PASSWORD
value: somewordpress
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pvc
MySQL Service
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
Persistent Volume and Persistent Volume Claim for MySQL
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data/mysql-pv"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Conclusion
Persistence in Kubernetes is crucial for ensuring that your application data is durable and always available. Whether you use simple volumes, hostPath, Persistent Volumes (PV), or Persistent Volume Claims (PVC), Kubernetes gives you great flexibility and control. With this guide, you now have the knowledge needed to implement an effective persistence strategy in your Kubernetes cluster and ensure that your applications can properly manage and protect their data.

