Kubernetes Volume Types Comparison
Volume Type |
Persistent |
Shared Between Containers (Same Pod) |
Shared Between Pods |
Backed By |
Common Use Cases |
emptyDir |
❌ No |
✅ Yes |
❌ No |
Node ephemeral disk |
Temp files, shared scratch space |
hostPath |
⚠️ Depends |
✅ Yes |
⚠️ Risky |
Host node's filesystem |
Debugging, access host files |
configMap |
❌ No |
✅ Yes |
❌ No |
In-cluster config |
Injecting app configuration |
secret |
❌ No |
✅ Yes |
❌ No |
Kubernetes Secrets |
Injecting sensitive data (tokens, certs) |
persistentVolumeClaim |
✅ Yes |
✅ Yes |
✅ Yes (with RWX) |
Network disk / EBS |
Databases, shared storage |
nfs |
✅ Yes |
✅ Yes |
✅ Yes |
NFS server |
Cross-Pod shared files |
projected |
❌ No |
✅ Yes |
❌ No |
Composite (secret + configMap) |
Unified config bundles |
downwardAPI |
❌ No |
✅ Yes |
❌ No |
Pod metadata |
Access Pod/Container info as files |
ephemeral (inline PVC) |
✅ Yes |
✅ Yes |
❌ No |
PVC provisioned on demand |
Short-lived persistent data |
EmptyDir
apiVersion: v1
kind: Pod
metadata:
name: shared-volume-demo # string: Name of the Pod
labels:
app: volume-test # key-value pair for selector or grouping
spec:
volumes:
- name: shared-data # string: Volume name, used by containers
emptyDir: {} # emptyDir: creates an ephemeral empty volume
containers:
- name: writer # Container A: writes to the volume
image: busybox # image with basic shell tools
command: ["/bin/sh", "-c"]
args:
- echo "Hello from writer!" > /data/message.txt && sleep 3600
volumeMounts:
- name: shared-data # Must match volume name above
mountPath: /data # Where the volume is mounted inside the container
- name: reader # Container B: reads from the same volume
image: busybox
command: ["/bin/sh", "-c"]
args:
- cat /data/message.txt && sleep 3600
volumeMounts:
- name: shared-data
mountPath: /data
Use Cases
Use Case |
Description |
Shared cache or buffer |
One container writes, another processes |
Socket or pipe file sharing |
UNIX domain socket communication |
Intermediate processing files |
e.g. download -> process -> upload workflow |
HostPath
apiVersion: v1
kind: Pod
metadata:
name: hostpath-demo
spec:
containers:
- name: debug
image: busybox
command: ["/bin/sh", "-c", "ls /host/log && sleep 3600"]
volumeMounts:
- name: host-logs
mountPath: /host/log # Mount path inside the container
volumes:
- name: host-logs
hostPath:
path: /var/log # Path on the host node
type: DirectoryOrCreate # Create if not exists
Supported type
Values for hostPath
type |
Description |
DirectoryOrCreate |
If the path does not exist, it will be created as an empty directory. |
Directory |
Path must already exist and be a directory. |
FileOrCreate |
If the file does not exist, it will be created as an empty file. |
File |
Path must already exist and be a file. |
Socket |
Path must be a UNIX domain socket. |
CharDevice |
Path must be a character device (e.g., /dev/null ). |
BlockDevice |
Path must be a block device (e.g., a disk like /dev/sda ). |
Use Cases
Use Case |
Why use hostPath |
Debug node-level data |
Mount /var/log, /etc, etc. from the host |
Access a Docker socket |
Mount /var/run/docker.sock to interact with Docker |
Read/write to node-local storage |
Store temporary files or shared state |
Logging agents (e.g., Fluentd) |
Collect host logs via /var/log |
Share files across Pods on same node |
Only if you're certain they'll schedule together |
NFS
apiVersion: v1
kind: Pod
metadata:
name: nfs-demo
spec:
containers:
- name: app
image: busybox
command: ["/bin/sh", "-c", "echo Hello > /mnt/data/hello.txt && sleep 3600"]
volumeMounts:
- name: nfs-volume
mountPath: /mnt/data
volumes:
- name: nfs-volume
nfs:
server: 10.0.0.100 # IP of your NFS server
path: /export/shared-data # Path exported on the NFS server
PV & PVC
- PV (PersistentVolume) = Empty hotel room (pre-booked by hotel)
- PVC (PersistentVolumeClaim) = Guest's reservation
Example
- Admin creates a PV.
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs: # backend could also be awsEBS, hostPath, etc.
server: 10.0.0.100
path: /exports/data
- Developer creates a PersistentVolumeClaim (PVC).
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
- Pod uses the PVC:
volumes:
- name: my-volume
persistentVolumeClaim:
claimName: my-pvc
volumeMounts:
- mountPath: /data
name: my-volume
Kubernetes-Supported File System Types (for Volumes)
File System Type |
Description |
RWX Support |
Typical Use Case |
nfs |
Network File System (shared over network) |
✅ Yes |
Shared config, logs, media, general storage |
cifs / smb |
Windows-style file sharing |
✅ Yes |
Windows interop, AD integration |
glusterfs |
Distributed, replicated storage |
✅ Yes |
HA shared volume across nodes |
cephfs |
POSIX-compliant distributed filesystem (Ceph) |
✅ Yes |
Cloud-native scalable shared volume |
awsElasticFileSystem / efs |
AWS managed NFS |
✅ Yes |
Shared cloud storage on AWS |
gcp-filestore |
Google Cloud's managed NFS |
✅ Yes |
Shared storage on GKE |
azure-file |
Azure Files via SMB |
✅ Yes |
RWX support on Azure |
local |
Node-local storage (local disk or SSD) |
❌ No |
Fast storage pinned to a node |
hostPath |
Mount a file or dir from host into container |
⚠️ Yes |
Debugging, low-level system access |
emptyDir |
Ephemeral volume, deleted with Pod |
❌ No |
Scratch space, inter-container sharing |
configMap / secret |
Inject configs or secrets as files |
❌ No |
Environment configs, TLS certs, credentials |
File System |
Description |
Notes |
ext4 |
Default Linux file system |
Fast, stable, widely supported |
xfs |
High-performance journaling FS |
Great for large files, logs, databases |
btrfs |
Copy-on-write FS with snapshots |
Advanced features, not always production-ready |
zfs |
Robust FS with compression, snapshots, RAID |
Requires extra kernel modules, very powerful |
f2fs |
Flash-friendly FS |
Optimized for SSDs, not commonly used in K8s |
vfat |
FAT filesystem (Windows compatible) |
For compatibility, not for persistent storage |
Cloud-native RWX File Systems
Cloud Provider |
File System |
Backed By |
Kubernetes CSI Driver |
AWS |
EFS (Elastic FS) |
NFS |
efs.csi.aws.com |
GCP |
Filestore |
NFS |
GKE NFS CSI / in-tree support |
Azure |
Azure Files |
SMB |
file.csi.azure.com |
Alibaba Cloud |
NAS / CPFS |
NFS-like |
nasplugin.csi.alibabacloud.com |
DigitalOcean |
NFS Volumes (3rd-party) |
NFS |
Community drivers (or mount manually) |
Longhorn |
RWX via internal NFS |
NFS |
longhorn.io/longhorn + built-in RWX share |
PV & PVC Life Cycle
1. Create PV
- PersistentVolume is created manually or provisioned dynamically.
- Status: Available
- Note: This step is optional if you’re using dynamic provisioning via StorageClass.
2. Create PVC
- A PersistentVolumeClaim is created by the user/application.
- Status: Pending → Bound
- Kubernetes matches the PVC to an existing PV, or creates one dynamically if StorageClass is defined.
3. Pod Uses PVC
- A Pod mounts the PVC as a volume using persistentVolumeClaim.
- Data is read/written from this mounted volume.
4. Delete Pod
- The Pod is deleted or rescheduled.
- The PVC and PV remain — the data is not deleted.
5. Delete PVC
- The PVC is deleted by the user.
- What happens next depends on the reclaimPolicy of the PV:
- Retain: PV remains in Released state, data is still there.
- Delete: PV is deleted along with the underlying storage.
- Recycle: (deprecated) would scrub and reuse the volume (no longer used).
6. Clean up PV
- If reclaimPolicy is Retain, an admin must manually:
- Reuse the PV (reset it to Available)
- Or delete the PV and clean the storage manually.
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
APP_ENV: "production"
LOG_LEVEL: "debug"
config.json: |
{
"host": "localhost",
"port": 8080
}
apiVersion: v1
kind: Pod
metadata:
name: config-env-demo
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo $APP_ENV && echo $LOG_LEVEL && sleep 3600"]
envFrom:
- configMapRef:
name: my-config
apiVersion: v1
kind: Pod
metadata:
name: config-individual-env
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo $APP_ENV && echo $LOG_LEVEL && sleep 3600"]
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: my-config
key: APP_ENV
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: my-config
key: LOG_LEVEL
apiVersion: v1
kind: Pod
metadata:
name: config-volume-demo
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "cat /config/APP_ENV && cat /config/config.json && sleep 3600"]
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: my-config
Secret
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: dXNlcg== # base64 for "user"
password: cGFzc3dvcmQ= # base64 for "password"
apiVersion: v1
kind: Pod
metadata:
name: secret-demo
spec:
containers:
- name: app
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: secret-vol
mountPath: /etc/secrets # Mount secret here
readOnly: true
volumes:
- name: secret-vol
secret:
secretName: my-secret # Reference to the Secret