BLOG

Kubernetes 5 Volumes
Volumes in Kubernetes

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

  1. 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
  1. Developer creates a PersistentVolumeClaim (PVC).
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  1. 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

Other Linux File System Types (for Formatting Volumes or Nodes)

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