CKA — Volumes & Persistent Volumes

5 minute read

CKA Exam Domain

Storage — 10%

Volumes and PersistentVolumes are the foundation of Kubernetes storage. You need to know the difference between the two, how to create PVs, and which volume type to use in different scenarios.

Volume Types

Kubernetes supports many volume types. Here are the ones you are most likely to encounter on the CKA exam:

Volume Type Lifecycle Use Case
emptyDir Pod lifecycle — deleted when Pod is removed Temp storage, scratch space, sharing data between containers in the same Pod
hostPath Node path — persists on the node filesystem Testing, single-node clusters, accessing node-level files
configMap Tied to the ConfigMap object Injecting configuration files into containers
secret Tied to the Secret object Injecting sensitive data (certs, passwords) into containers
persistentVolumeClaim Independent of Pod lifecycle Production workloads that need persistent storage

emptyDir Example

An emptyDir volume is created when a Pod is assigned to a node and exists as long as the Pod runs:

apiVersion: v1
kind: Pod
metadata:
  name: emptydir-demo
spec:
  containers:
    - name: writer
      image: busybox
      command: ["sh", "-c", "echo hello > /data/message && sleep 3600"]
      volumeMounts:
        - mountPath: /data
          name: shared-data
    - name: reader
      image: busybox
      command: ["sh", "-c", "cat /data/message && sleep 3600"]
      volumeMounts:
        - mountPath: /data
          name: shared-data
  volumes:
    - name: shared-data
      emptyDir: {}

hostPath Example

A hostPath volume mounts a file or directory from the host node’s filesystem into the Pod:

apiVersion: v1
kind: Pod
metadata:
  name: hostpath-demo
spec:
  containers:
    - name: app
      image: busybox
      command: ["sh", "-c", "ls /node-data && sleep 3600"]
      volumeMounts:
        - mountPath: /node-data
          name: host-volume
  volumes:
    - name: host-volume
      hostPath:
        path: /tmp/k8s-data
        type: DirectoryOrCreate

Exam tip: hostPath is great for single-node testing but is not suitable for production multi-node clusters because the data is local to one node.

What Is a PersistentVolume?

A PersistentVolume (PV) is a cluster-level storage resource that has been provisioned by an administrator (or dynamically via a StorageClass). It is an object in the Kubernetes API, just like a Node.

Think of a PV as a “storage pool” that exists independently of any Pod. Pods do not consume PVs directly — they use PersistentVolumeClaims (PVCs) to request a piece of that storage.

Key characteristics:

  • Cluster-scoped — not tied to any namespace
  • Provisioned by admins — or dynamically by StorageClasses
  • Has a lifecycle independent of Pods — data survives Pod restarts and deletions

PersistentVolume Spec

Here is a complete PV definition:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-demo
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /data/pv-demo

Key fields:

Field Description
capacity.storage How much storage this PV provides
accessModes How the volume can be mounted (RWO, ROX, RWX)
persistentVolumeReclaimPolicy What happens when the PVC is deleted (Retain, Delete, Recycle)
storageClassName Links this PV to a StorageClass for matching with PVCs
hostPath.path The actual path on the node (for hostPath type PVs)

Exam tip: You will likely need to write PV YAML from scratch on the exam. Memorize the structure — apiVersion: v1, kind: PersistentVolume, and the key spec fields.

Volume vs PersistentVolume

Understanding the difference is critical:

Aspect Volume PersistentVolume
Lifecycle Tied to the Pod — destroyed when Pod is deleted Independent — survives Pod restarts and deletions
Scope Defined inside the Pod spec Cluster-scoped resource
Managed by Application developer Cluster administrator
Reusability Cannot be reused across Pods (unless you redefine it) Can be bound to different PVCs over time
Dynamic provisioning Not applicable Supported via StorageClasses

PV Lifecycle

A PersistentVolume goes through the following phases:

Available → Bound → Released → Reclaimed/Deleted
  1. Available — PV is created and waiting for a PVC to claim it
  2. Bound — PV is bound to a PVC. One-to-one mapping.
  3. Released — The PVC has been deleted, but the PV has not been reclaimed yet. The data still exists.
  4. Reclaimed/Deleted — Depending on the reclaim policy:
    • Retain: PV stays in Released state until admin manually cleans up
    • Delete: PV and underlying storage are automatically deleted
    • Recycle (deprecated): Data is scrubbed (rm -rf /volume/*)

Exam tip: If a PV shows Released status and you need to reuse it, you must manually remove the spec.claimRef field or delete and recreate the PV.

PV Status

Check the status of PersistentVolumes:

# List all PVs
kubectl get pv

Expected output:

NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   AGE
pv-demo   5Gi        RWO            Retain           Available           manual         10s

Get detailed information:

# Describe a specific PV
kubectl describe pv pv-demo

This shows the full spec, status, events, and any bound claim.

# Check PV with wide output
kubectl get pv -o wide

# Get PV in YAML format (useful for debugging)
kubectl get pv pv-demo -o yaml

Practice Questions

Q1. Create a PersistentVolume named pv-log with 100Mi capacity, ReadWriteMany access mode, hostPath /pv/log, and reclaim policy Retain.

Show Answer
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-log
spec:
  capacity:
    storage: 100Mi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /pv/log
kubectl apply -f pv-log.yaml
kubectl get pv pv-log

Q2. What is the difference between an emptyDir volume and a persistentVolumeClaim volume?

Show Answer
  • emptyDir is tied to the Pod lifecycle — when the Pod is deleted, the data is lost. It is useful for temporary scratch space or sharing data between containers in the same Pod.
  • persistentVolumeClaim references a PVC that binds to a PV. The data persists beyond the Pod lifecycle. It is the standard approach for production workloads.

Q3. A PV has status Released. What does this mean, and how can you make it Available again?

Show Answer

Released means the PVC that was bound to this PV has been deleted, but the PV still retains the data and the reference to the old claim.

To make it Available again:

kubectl edit pv <pv-name>
# Remove the spec.claimRef section entirely

Or delete and recreate the PV.

Q4. Create a Pod that uses an emptyDir volume mounted at /cache.

Show Answer
apiVersion: v1
kind: Pod
metadata:
  name: cache-pod
spec:
  containers:
    - name: app
      image: busybox
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - mountPath: /cache
          name: cache-vol
  volumes:
    - name: cache-vol
      emptyDir: {}

Q5. Which hostPath type should you use if you want Kubernetes to create the directory on the node if it does not exist?

Show Answer

Use type: DirectoryOrCreate. This tells Kubernetes to create the directory at the specified path if it does not already exist on the node.

volumes:
  - name: host-vol
    hostPath:
      path: /data/my-app
      type: DirectoryOrCreate

Updated: