E-NO
Kubernetes Volumes local lab 7 Min Read

Kubernetes Volumes Local Lab Setup with Practical Examples

calendar_today Published: 2026-08-26
update Last Updated: 2026-08-26
analytics SEO Efficiency: 100%
Technical guide illustration for Kubernetes Volumes Local Lab Setup with Practical Examples.

A practical guide to building a safe Kubernetes volumes lab on your local machine for testing PersistentVolumes, PersistentVolumeClaims, StorageClasses, and pod storage configurations.

Intro

Kubernetes volumes are a fundamental building block for stateful applications, yet they are often misunderstood. A local lab gives you a safe, isolated environment to experiment with PersistentVolumes (PVs), PersistentVolumeClaims (PVCs), and StorageClasses without risking production data. This guide walks through setting up such a lab using common tools like Minikube or kind, creating local storage, and running practical tests. By the end, you will have a repeatable workflow for learning and debugging volume behavior.

We will start with environment setup, then create a StorageClass and PVC, attach the volume to a pod, verify persistence, explore failure modes and recovery, and finish with an operations checklist. Each step includes concrete commands, YAML snippets, and expected outputs so you can follow along.

Version and Environment Inventory

Before starting, ensure you have the following installed and compatible:

ComponentRecommended VersionNotes
Kubernetesv1.24 or laterMinikube or kind both work
kubectlv1.24 or laterMatch minor version to cluster
Minikubev1.26 or laterOr kind v0.14 or later
Container runtimeDocker or containerdMinikube can use its own VM
Host OSLinux, macOS, or WindowsLinux is easiest for local volumes

This lab uses Minikube with the default Docker driver. Verify your environment with:

kubectl version --client
# Example output: Client Version: v1.26.3
minikube version
# Example output: minikube version: v1.29.0

Start your cluster:

minikube start --driver=docker --kubernetes-version=v1.26.3
# Example output: Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default.

Verify the cluster is up:

kubectl get nodes
# Expected output:
# NAME       STATUS   ROLES           AGE   VERSION
# minikube   Ready    control-plane   1m    v1.26.3

If your environment uses kind, the steps are similar, but hostPath volumes will be on the kind node container rather than a VM. The commands for creating PVCs and pods remain the same.

Quick check 1 of 2

What is the recommended approach for security and data-isolation according to Kubernetes documentation?

The reference states that for security and data-isolation, dynamic volume provisioning is recommended and volume types that use node resources should be avoided.

Safe Configuration Path

For a safe lab, use a StorageClass with volumeBindingMode: Immediate and a local path provisioner. Minikube provides a built-in standard StorageClass that dynamically provisions hostPath volumes. Alternatively, you can create your own StorageClass for more control.

First, inspect existing StorageClasses:

kubectl get storageclass
# Expected output:
# NAME                 PROVISIONER                RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
# standard (default)   k8s.io/minikube-hostpath   Delete          Immediate           false                  1m

The output shows a default StorageClass named standard with provisioner k8s.io/minikube-hostpath. This provisioner creates a directory under /tmp/hostpath-provisioner/ on the Minikube node for each volume. Because the reclaim policy is Delete, removing the PVC will delete the associated directory.

If you need a custom StorageClass, create a YAML file custom-sc.yaml:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-hp
provisioner: k8s.io/minikube-hostpath
reclaimPolicy: Retain
volumeBindingMode: Immediate

Apply it:

kubectl apply -f custom-sc.yaml
# Expected output: storageclass.storage.k8s.io/local-hp created

For this lab, we will use the default standard class for simplicity.

Now create a PVC to request storage from this StorageClass. Save the following as pvc.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: lab-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

Apply it:

kubectl apply -f pvc.yaml
# Expected output: persistentvolumeclaim/lab-pvc created

Check the PVC status:

kubectl get pvc lab-pvc
# Expected output:
# NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
# lab-pvc   Bound    pvc-1234abcd-56ef-7890-ghij-klmnopqrstuv   1Gi        RWO            standard       5s

A PV was automatically created. View it:

kubectl get pv
# Expected output:
# NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
# pvc-1234abcd-56ef-7890-ghij-klmnopqrstuv   1Gi        RWO            Delete           Bound    default/lab-pvc   standard                10s

The PV is bound to the PVC. Note the reclaim policy is Delete, meaning when the PVC is deleted, the PV and underlying data will be removed.

Now deploy a pod that uses this PVC. Save the following as pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
    - name: app
      image: nginx:latest
      volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: lab-pvc

Apply the pod:

kubectl apply -f pod.yaml
# Expected output: pod/volume-test created

Verify the pod is running:

kubectl get pod volume-test
# Expected output:
# NAME           READY   STATUS    RESTARTS   AGE
# volume-test   1/1     Running   0          10s

Verification and Diagnostics

To verify the volume is working, write a file from inside the pod and then check it from the host or another pod.

First, exec into the pod and create a file:

kubectl exec -it volume-test -- sh -c 'echo Hello from volume > /usr/share/nginx/html/test.txt'
# No output if successful

Read the file from the pod:

kubectl exec volume-test -- cat /usr/share/nginx/html/test.txt
# Expected output: Hello from volume

Now, inspect the host path where the volume is mounted. For Minikube, you can use minikube ssh:

minikube ssh
# Inside the minikube VM
sudo ls /tmp/hostpath-provisioner/default/lab-pvc
# Expected output: test.txt
sudo cat /tmp/hostpath-provisioner/default/lab-pvc/test.txt
# Expected output: Hello from volume

This confirms the volume persists on the host. Exit the SSH session with exit.

To test persistence across pod restarts, delete the pod and recreate it:

kubectl delete pod volume-test
# Expected output: pod "volume-test" deleted
kubectl apply -f pod.yaml
# Expected output: pod/volume-test created

After the pod starts, check the file still exists:

kubectl exec volume-test -- cat /usr/share/nginx/html/test.txt
# Expected output: Hello from volume

To see detailed volume information, describe the PVC and PV:

kubectl describe pvc lab-pvc
# Look for Events:
#   Normal  ProvisioningSucceeded  10s   k8s.io/minikube-hostpath_minikube  Successfully provisioned volume pvc-1234abcd-56ef-7890-ghij-klmnopqrstuv
kubectl describe pv pvc-1234abcd-56ef-7890-ghij-klmnopqrstuv
# Look for Source:
#   Type: HostPath (path: /tmp/hostpath-provisioner/default/lab-pvc)

Check storage capacity and usage from inside the pod:

kubectl exec volume-test -- df -h /usr/share/nginx/html
# Example output:
# Filesystem      Size  Used Avail Use% Mounted on
# /dev/sda1       9.7G  1.2G  8.5G  12%  /usr/share/nginx/html

Quick check 2 of 2

What is the purpose of a PersistentVolumeClaim?

A PersistentVolumeClaim is a request for storage by a user, similar to how Pods consume node resources.

Failure Modes and Recovery

Common failures in a local lab include PVC stuck in Pending, pod failing to mount, or data loss due to reclaim policy.

PVC Pending

If the PVC is not bound, check StorageClass and provisioner:

kubectl describe pvc lab-pvc
# Look for Events:
#   Warning  ProvisioningFailed  10s  k8s.io/minikube-hostpath_minikube  failed to provision volume with StorageClass "standard": ...

If using a custom StorageClass, ensure the provisioner is correct and available. For Minikube, the standard class works out of the box.

Pod Mount Errors

If the pod fails to start with a mount error, check the PVC status and the pod events:

kubectl get pvc
kubectl describe pod volume-test
# Look for Events:
#   Warning  FailedMount  30s  kubelet  MountVolume.SetUp failed for volume "pvc-..." : ...

Sometimes the issue is that the volume is already mounted by another pod with ReadWriteOnce on a different node. In a single-node Minikube, this is rare.

Data Loss on PVC Deletion

The default reclaim policy for the standard StorageClass is Delete. If you delete the PVC, the PV and hostPath data are removed.

kubectl delete pvc lab-pvc
# Expected output: persistentvolumeclaim "lab-pvc" deleted

If you need to retain data, change the reclaim policy to Retain on the PV before deleting the PVC. However, for a lab, you can recreate the PVC and pod from scratch.

Recovery Steps

  • Check cluster events: kubectl get events --sort-by=.metadata.creationTimestamp
  • Verify StorageClass: kubectl get sc
  • Inspect hostPath on the node if using hostPath: minikube ssh and browse /tmp/hostpath-provisioner/...
  • Recreate resources if necessary.

To reset the lab completely, delete all created resources:

kubectl delete pod volume-test
kubectl delete pvc lab-pvc
# No output, but resources are deleted

Then reapply your YAML files.

Operations Checklist

Use this checklist for repeatable lab operations:

StepCommand / ActionExpected Result
Start clusterminikube startCluster ready
Check StorageClasskubectl get scstandard listed
Apply PVCkubectl apply -f pvc.yamlPVC created
Verify PVC boundkubectl get pvcSTATUS Bound
Apply podkubectl apply -f pod.yamlPod running
Write test filekubectl exec ... -- sh -c 'echo test > /mnt/test.txt'No error
Read test filekubectl exec ... -- cat /mnt/test.txtOutput test
Delete pod and recreatekubectl delete pod ... && kubectl apply -f pod.yamlData persists
Clean upkubectl delete pod, pvcResources removed

For deeper inspection:

  • kubectl describe pvc shows provisioning events.
  • kubectl describe pv shows volume source details.
  • minikube ssh allows host-level file checks.

Keep YAML files version-controlled for reproducible labs.

Conclusion

You now have a functional Kubernetes volumes lab on your local machine. You learned how to set up a cluster, create a StorageClass, provision a PVC, attach it to a pod, verify data persistence, and recover from common failures. This lab serves as a foundation for exploring more advanced topics like StatefulSets, dynamic provisioning with different storage backends, and CSI drivers. Remember to start with a narrow scenario and expand gradually, as suggested by the research evidence for effective local development. Keep your environment clean and your YAML files organized for repeatable learning.

To extend this lab, experiment with different access modes, reclaim policies, and custom StorageClasses. Try deploying multiple pods sharing a ReadWriteMany volume, or use a StatefulSet to manage persistent storage for each replica. These exercises will deepen your understanding of Kubernetes storage and prepare you for production scenarios.

Related Research

Article Quality Score

Reader usefulness 100%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL