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.