Working with Volumes
1. Using emptyDir Volumes
volumes:
- name: cache
emptyDir:
medium: Memory # tmpfs (RAM)
sizeLimit: 1Gi
| Property | Detail |
| Lifetime | Pod (deleted with pod) |
| medium | "" (disk) or Memory (tmpfs) |
| Use | Scratch space, sidecar sharing |
2. Using hostPath Volumes
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
| type | Check |
| DirectoryOrCreate | Create if missing |
| Directory | Must exist |
| FileOrCreate / File | Same for files |
| Socket | Unix socket |
Warning: hostPath bypasses pod isolation; restrict via Pod Security Standards. Avoid in multi-tenant clusters.
3. Configuring PersistentVolumes
apiVersion: v1
kind: PersistentVolume
metadata: { name: pv-data-1 }
spec:
capacity: { storage: 100Gi }
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: gp3
csi:
driver: ebs.csi.aws.com
volumeHandle: vol-0abc1234
| Source | Examples |
| CSI | AWS EBS, GCE PD, Azure Disk, Ceph RBD |
| NFS | nfs: { server, path } |
| Local | node-local SSD |
4. Creating PersistentVolumeClaims
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: data }
spec:
accessModes: [ReadWriteOnce]
storageClassName: gp3
resources: { requests: { storage: 50Gi } }
| Field | Detail |
| storageClassName | Dynamic provisioning class |
| accessModes | Subset of PV's modes |
| volumeName | Bind to specific PV (skip class) |
5. Binding PVC to PV
Binding Lifecycle
- PVC created → controller searches matching PV (size, class, modes)
- No match + StorageClass → dynamic provisioner creates PV
- PV bound;
claimRef set; status Bound
- Pod consumes via
persistentVolumeClaim.claimName
6. Listing PersistentVolumes
kubectl get pv
kubectl get pv --sort-by=.spec.capacity.storage
| Status | Meaning |
| Available | Free for binding |
| Bound | In use by PVC |
| Released | PVC deleted (waiting reclaim) |
| Failed | Reclaim failed |
7. Listing PersistentVolumeClaims
kubectl get pvc -A
kubectl get pvc -o wide # shows bound PV
| Status | Meaning |
| Pending | No PV match / provisioner working |
| Bound | Linked to a PV |
| Lost | Underlying PV gone |
8. Understanding Access Modes
| Mode | Meaning |
| ReadWriteOnce (RWO) | R/W by single node |
| ReadOnlyMany (ROX) | RO by many nodes |
| ReadWriteMany (RWX) | R/W by many nodes (NFS, CephFS, EFS) |
| ReadWriteOncePod NEW | R/W by single pod (1.27+) |
9. Setting Reclaim Policies
| persistentVolumeReclaimPolicy | Effect on PVC delete |
| Retain | PV stays; manual cleanup |
| Delete | PV + underlying volume deleted (dynamic default) |
| Recycle | DEPRECATED |
10. Using Dynamic Provisioning
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: { name: gp3 }
provisioner: ebs.csi.aws.com
parameters: { type: gp3, encrypted: "true" }
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
allowVolumeExpansion: true
11. Expanding PersistentVolumes
kubectl patch pvc data -p '{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'
| Requirement | Detail |
| StorageClass | allowVolumeExpansion: true |
| Online expansion | Supported by CSI driver (EBS, GCE PD) |
| Shrinking | Not supported |
12. Deleting PersistentVolumeClaims
kubectl delete pvc data
kubectl delete pv pv-data-1 # only after PVC released & reclaim done
Warning: Default StorageClasses use Delete reclaim — deleting PVC destroys underlying disk. Switch to Retain for production data.