By default, container filesystems are ephemeral and isolated. If a container crashes, any changes or files written to its filesystem are lost, and a newly restarted container starts with a clean state. Additionally, containers running within the same Pod cannot share files or access each other’s filesystems unless explicit volume mapping is established.
To solve these limitations, Kubernetes implements Volumes. A Volume is a directory that is accessible to all containers in a Pod, allowing data persistence and inter-container data sharing.
graph TD
subgraph Pod: volume-share-devops
direction TB
subgraph container1 [volume-container-devops-1]
path1["/tmp/media <br> (Mounts volume-share)"]
end
subgraph container2 [volume-container-devops-2]
path2["/tmp/cluster <br> (Mounts volume-share)"]
end
emptyDir[("emptyDir Shared Volume <br> (volume-share)")]
emptyDir <-->|Mounted at /tmp/media| path1
emptyDir <-->|Mounted at /tmp/cluster| path2
end
emptyDirThe simplest volume type is emptyDir. As the name suggests, it starts as an empty directory when the Pod is scheduled onto a node.
Key characteristics of emptyDir include:
emptyDir volume is strictly tied to the lifetime of the Pod. If the Pod is deleted, relocated, or terminated, the data in the emptyDir is deleted permanently. (However, it survives container crashes).emptyDir volume. The containers can mount it at the same or different mount paths, enabling simple, fast sharing of assets, logs, and configuration state.emptyDir volumes are stored on whatever medium backs the node (such as local SSD/HDD). However, you can configure the volume to store data on a memory-backed filesystem (tmpfs) by setting the medium field to Memory for ultra-fast cache tasks.Kubernetes supports a wide variety of volume types designed for different architectures:
emptyDir: Temporary directory created on Pod startup. Used for scratch space, sorting algorithms, caching, or shared directories between sidecars and application containers.configMap / secret: Injects configuration details and credentials directly into the container as files.hostPath: Mounts a file or directory from the host node’s filesystem into the Pod. Used for system-level monitoring agents (like Fluentd or Prometheus Node Exporter) that need access to node logs/system files.persistentVolumeClaim (PVC): Deconstructs storage requests from specific infrastructure, allowing Pods to mount block or file storage (like AWS EBS, NFS, Ceph, Google Persistent Disk) dynamically.Shared volumes form the foundation of the Sidecar Pattern, where a helper container works alongside the main container. Typical examples include:
emptyDir volume, and a sidecar container reads and streams those logs to a centralized storage cluster (e.g., Elasticsearch, Splunk).thordefaultvolume-share-devopsvolume-share (type: emptyDir)volume-container-devops-1ubuntu:latest/tmp/mediasleep 3600 (to prevent container exit)volume-container-devops-2ubuntu:latest/tmp/clustersleep 3600Access the admin terminal host configured with cluster credentials:
ssh thor@jump_host_ip
Create a new file named volume-share.yaml defining the multi-container Pod structure with shared volume mounts:
apiVersion: v1
kind: Pod
metadata:
name: volume-share-devops
labels:
app: volume-share
spec:
volumes:
- name: volume-share
emptyDir: {}
containers:
- name: volume-container-devops-1
image: ubuntu:latest
command: ["/bin/sh", "-c", "sleep 3600"]
volumeMounts:
- name: volume-share
mountPath: /tmp/media
- name: volume-container-devops-2
image: ubuntu:latest
command: ["/bin/sh", "-c", "sleep 3600"]
volumeMounts:
- name: volume-share
mountPath: /tmp/cluster
Apply the manifest file to start container creation in the active namespace:
kubectl apply -f volume-share.yaml
Expected Output:
pod/volume-share-devops created
Verify that the Pod successfully initializes and both containers transition to the Running state:
kubectl get pods
Expected Output showing 2/2 containers ready:
NAME READY STATUS RESTARTS AGE
volume-share-devops 2/2 Running 0 15s
To verify that the containers are successfully sharing the same volume, perform the following validation steps.
Access the terminal of the first container and write a string to a file inside the mounted path /tmp/media:
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- /bin/sh -c 'echo "Shared Volume DevOps Verification Success" > /tmp/media/media.txt'
Query the file from the second container under its configured mount path /tmp/cluster:
kubectl exec -it volume-share-devops -c volume-container-devops-2 -- cat /tmp/cluster/media.txt
Expected Output:
Shared Volume DevOps Verification Success
This confirms the file created in container 1 was written to the shared emptyDir volume and read successfully from container 2!
Describe the running Pod to confirm that both containers successfully mount the volume using volume-share:
kubectl get pod volume-share-devops -o jsonpath='{.spec.containers[*].volumeMounts}'
Expected Output showing correct mount paths:
[{"mountPath":"/tmp/media","name":"volume-share"}] [{"mountPath":"/tmp/cluster","name":"volume-share"}]
Induce a crash/restart on Container 1 to verify that data survives container restarts:
# Get PID of sleep inside container 1 and kill it
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- kill 1
Check status:
kubectl get pods
Expected Output showing 1 restart on Container 1:
NAME READY STATUS RESTARTS AGE
volume-share-devops 2/2 Running 1 (10s ago) 2m
Check if the file is still present inside container 2:
kubectl exec -it volume-share-devops -c volume-container-devops-2 -- cat /tmp/cluster/media.txt
Expected Output:
Shared Volume DevOps Verification Success
(This confirms that while container 1 crashed and restarted, the data was kept intact because it resides in the pod-level emptyDir volume, not the container filesystem).