We are working on an application that will be deployed on multiple containers within a pod on Kubernetes cluster. There is a requirement to share a volume among the containers to save some temporary data. The Nautilus DevOps team is developing a similar template to replicate the scenario. Below you can find more details about it.
- Create a pod named
volume-share-devops. - For the first container, use image
debianwithlatesttag only and remember to mention the tag i.edebian:latest, container should be named asvolume-container-devops-1, and run asleepcommand for it so that it remains in running state. Volumevolume-shareshould be mounted at path/tmp/official. - For the second container, use image
debianwith thelatesttag only and remember to mention the tag i.edebian:latest, container should be named asvolume-container-devops-2, and again run asleepcommand for it so that it remains in running state. Volumevolume-shareshould be mounted at path/tmp/apps. - Volume name should be
volume-shareof typeemptyDir. - After creating the pod, exec into the first container i.e
volume-container-devops-1, and just for testing create a fileofficial.txtwith the contentWelcome to xFusionCorp Industriesunder the mounted path of first container i.e/tmp/official. - The file
official.txtshould be present under the mounted path/tmp/appson the second containervolume-container-devops-2as well, since they are using a shared volume.
🎉 CONGRATULATIONS! 🎉
You have successfully completed the Kubernetes Shared Volumes challenge! Let me help you create a complete blog post for this topic.
Introduction
Welcome to Day 54 of my 100 Days of DevOps journey! Today, we're exploring one of Kubernetes' most powerful features: Shared Volumes.
Why Shared Volumes Matter
Imagine two containers in a pod needing to share data – one writes files, the other reads them. Without shared volumes, they'd be isolated. With shared volumes, they can communicate through a common storage space!
┌─────────────────────────────────────────────────────────────────────────────┐
│ The Problem That Shared Volumes Solve │
│ │
│ Before (No Shared Volume): │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Container 1 │ │ Container 2 │ │
│ │ Writes file │ │ Needs file │ │
│ │ ❌ Isolated │ │ ❌ Can't access │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ After (With Shared Volume): │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Shared Volume │ │
│ │ ┌──────────────────┐ ┌──────────────────┐ │ │
│ │ │ Container 1 │ │ Container 2 │ │ │
│ │ │ Writes file ✅ │◄────────►│ Reads file ✅ │ │ │
│ │ └──────────────────┘ └──────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
📋 What We'll Build Today
Our Task:
-
Pod Name:
volume-share-devops -
Container 1:
volume-container-devops-1(debian:latest) – mounts at/tmp/official -
Container 2:
volume-container-devops-2(debian:latest) – mounts at/tmp/apps -
Volume:
volume-share(type: emptyDir) - Goal: Create a file in one container and verify it's accessible in the other
📖 Understanding Shared Volumes
What is an emptyDir Volume?
An emptyDir volume is a temporary shared directory that:
- ✅ Exists for the lifetime of the Pod
- ✅ Starts empty
- ✅ Can be read and written by all containers in the Pod
- ✅ Is deleted when the Pod is removed
┌─────────────────────────────────────────────────────────────────────────────┐
│ How emptyDir Volume Works │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Pod: volume-share-devops │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────────────────┐ │ │
│ │ │ emptyDir Volume: volume-share │ │ │
│ │ │ Shared storage space │ │ │
│ │ └────────────────────────────────────────────────────────────────┘ │ │
│ │ ▲ ▲ │ │
│ │ │ │ │ │
│ │ ┌─────────────────┴──────┐ ┌───────────┴───────────────┐ │ │
│ │ │ Container 1 │ │ Container 2 │ │ │
│ │ │ volume-container- │ │ volume-container- │ │ │
│ │ │ devops-1 │ │ devops-2 │ │ │
│ │ │ │ │ │ │ │
│ │ │ Mount: /tmp/official │ │ Mount: /tmp/apps │ │ │
│ │ │ Writes official.txt │ │ Reads official.txt │ │ │
│ │ └────────────────────────┘ └────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
🔧 Step-by-Step Guide
Step 1: Create the YAML Manifest
First, let's create a YAML file describing our Pod:
vi volume-share-devops.yaml
YAML Content:
apiVersion: v1
kind: Pod
metadata:
name: volume-share-devops
spec:
containers:
- name: volume-container-devops-1
image: debian:latest
command: ["sleep"]
args: ["infinity"]
volumeMounts:
- name: volume-share
mountPath: /tmp/official
- name: volume-container-devops-2
image: debian:latest
command: ["sleep"]
args: ["infinity"]
volumeMounts:
- name: volume-share
mountPath: /tmp/apps
volumes:
- name: volume-share
emptyDir: {}
📖 YAML Breakdown
| Field | Value | Explanation |
|---|---|---|
apiVersion |
v1 |
The stable Kubernetes API version |
kind |
Pod |
We're creating a Pod |
metadata.name |
volume-share-devops |
The Pod's name |
containers[0].name |
volume-container-devops-1 |
First container name |
containers[0].image |
debian:latest |
Debian Linux image |
containers[0].command |
["sleep"] |
Keep container running |
containers[0].args |
["infinity"] |
Sleep forever |
volumeMounts[0].name |
volume-share |
Which volume to mount |
volumeMounts[0].mountPath |
/tmp/official |
Where to mount it |
volumes[0].name |
volume-share |
Volume name |
volumes[0].emptyDir |
{} |
emptyDir volume type |
Why sleep infinity?
Without a command, Debian containers would exit immediately. sleep infinity keeps them running indefinitely.
Step 2: Create the Pod
# Apply the configuration
kubectl apply -f volume-share-devops.yaml
Output:
pod/volume-share-devops created
Step 3: Verify the Pod is Running
# Check pod status
kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE
volume-share-devops 2/2 Running 0 10s
# Get detailed pod information
kubectl describe pod volume-share-devops
Key Output:
Containers:
volume-container-devops-1:
Mounts:
/tmp/official from volume-share (rw)
volume-container-devops-2:
Mounts:
/tmp/apps from volume-share (rw)
Volumes:
volume-share:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Step 4: Create a File in the First Container
Let's create a file in the first container:
# Exec into the first container
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- /bin/bash
# Inside the container:
# Create the directory (if it doesn't exist)
mkdir -p /tmp/official
# Create the file with content
echo "Welcome to xFusionCorp Industries" > /tmp/official/official.txt
# Verify the file was created
cat /tmp/official/official.txt
# Exit the container
exit
Output:
root@volume-share-devops:/# mkdir -p /tmp/official
root@volume-share-devops:/# echo "Welcome to xFusionCorp Industries" > /tmp/official/official.txt
root@volume-share-devops:/# cat /tmp/official/official.txt
Welcome to xFusionCorp Industries
root@volume-share-devops:/# exit
Step 5: Verify the File in the Second Container
Now let's check if the file is accessible in the second container:
# Exec into the second container
kubectl exec -it volume-share-devops -c volume-container-devops-2 -- /bin/bash
# Inside the container:
# Check if the file exists
cat /tmp/apps/official.txt
# Verify the directory contents
ls -la /tmp/apps/
# Exit the container
exit
Output:
root@volume-share-devops:/# cat /tmp/apps/official.txt
Welcome to xFusionCorp Industries
root@volume-share-devops:/# ls -la /tmp/apps/
total 12
drwxrwxrwx 2 root root 4096 Aug 17 10:49 .
drwxrwxrwt 1 root root 4096 Aug 17 10:46 ..
-rw-r--r-- 1 root root 34 Aug 17 10:49 official.txt
root@volume-share-devops:/# exit
📝 Complete Commands Summary
# 1. Create the YAML file
cat > volume-share-devops.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
name: volume-share-devops
spec:
containers:
- name: volume-container-devops-1
image: debian:latest
command: ["sleep"]
args: ["infinity"]
volumeMounts:
- name: volume-share
mountPath: /tmp/official
- name: volume-container-devops-2
image: debian:latest
command: ["sleep"]
args: ["infinity"]
volumeMounts:
- name: volume-share
mountPath: /tmp/apps
volumes:
- name: volume-share
emptyDir: {}
EOF
# 2. Create the pod
kubectl apply -f volume-share-devops.yaml
# 3. Check pod status
kubectl get pods
# 4. Create file in first container (interactive)
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- /bin/bash
# Inside: mkdir -p /tmp/official && echo "Welcome to xFusionCorp Industries" > /tmp/official/official.txt
# Inside: exit
# 5. Verify in second container (interactive)
kubectl exec -it volume-share-devops -c volume-container-devops-2 -- /bin/bash
# Inside: cat /tmp/apps/official.txt
# Inside: exit
# 6. Quick one-liner verification
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- cat /tmp/official/official.txt
kubectl exec -it volume-share-devops -c volume-container-devops-2 -- cat /tmp/apps/official.txt
📊 Before and After Comparison
| Aspect | Before | After |
|---|---|---|
| Container 1 Mount | /tmp/official |
/tmp/official |
| Container 2 Mount | /tmp/apps |
/tmp/apps |
| Shared Volume | Created | Created |
| File in Container 1 | ❌ Not present | ✅ official.txt created |
| File in Container 2 | ❌ Not present | ✅ official.txt accessible |
| Volume Type | emptyDir | emptyDir |
| Pod Status | Running | Running |
🔍 Additional Verification
# Check both containers have the file
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- ls -la /tmp/official/
kubectl exec -it volume-share-devops -c volume-container-devops-2 -- ls -la /tmp/apps/
# Check file content in both containers
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- cat /tmp/official/official.txt
kubectl exec -it volume-share-devops -c volume-container-devops-2 -- cat /tmp/apps/official.txt
# Check pod logs
kubectl logs volume-share-devops -c volume-container-devops-1
kubectl logs volume-share-devops -c volume-container-devops-2
# Check pod details
kubectl describe pod volume-share-devops
🎯 Key Learnings
1. Use sleep infinity to Keep Containers Running
Without this, containers would exit immediately. Both containers need to stay running.
2. Different Mount Paths, Same Volume
Even though containers mount at different paths (/tmp/official and /tmp/apps), they share the same underlying storage.
3. Volumes are Pod-Level Resources
Volumes are defined at the Pod level and shared among all containers.
4. emptyDir Volumes are Ephemeral
Data in emptyDir volumes is deleted when the Pod is removed.
5. Multi-Container Pods Share Network and Storage
Containers in the same Pod share:
- Network namespace (same IP)
- Storage volumes
- They can communicate via
localhost
🛠️ Common Mistakes and Solutions
Mistake 1: Wrong Command for kubectl exec
❌ Wrong:
kubectl exec -it volume-container-devops-1 -c volume-container-devops-1 -- /bin/bash
✅ Correct:
kubectl exec -it volume-share-devops -c volume-container-devops-1 -- /bin/bash
Note: Use the Pod name as the first argument, not the container name!
Mistake 2: Forgetting mkdir -p
❌ Wrong:
echo "content" > /tmp/official/official.txt
# Error: No such file or directory
✅ Correct:
mkdir -p /tmp/official
echo "content" > /tmp/official/official.txt
Mistake 3: Container Exiting Immediately
❌ Wrong:
containers:
- name: my-container
image: debian:latest
✅ Correct:
containers:
- name: my-container
image: debian:latest
command: ["sleep"]
args: ["infinity"]
📊 Volume Types Comparison
| Volume Type | Use Case | Persistence | When to Use |
|---|---|---|---|
| emptyDir | Temporary shared storage | Pod lifetime | Sharing data between containers |
| hostPath | Access host files | Node lifetime | Accessing host filesystem |
| PersistentVolumeClaim | Persistent storage | Beyond pod lifetime | Database storage |
| ConfigMap | Configuration files | Read-only | Application configuration |
| Secret | Sensitive data | Read-only | Passwords, API keys |
🚀 Next Steps
After completing this challenge, you can:
- Use a PersistentVolumeClaim for persistent storage
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: my-pvc
- Mount ConfigMaps for configuration
volumes:
- name: config
configMap:
name: app-config
- Mount Secrets for sensitive data
volumes:
- name: secrets
secret:
secretName: app-secrets
✅ Task Summary
| Requirement | Status |
|---|---|
Pod volume-share-devops created |
✅ |
Container 1: volume-container-devops-1 (debian:latest) |
✅ |
Container 1 mount: /tmp/official
|
✅ |
Container 2: volume-container-devops-2 (debian:latest) |
✅ |
Container 2 mount: /tmp/apps
|
✅ |
Volume: volume-share (emptyDir) |
✅ |
| Both containers running | ✅ |
| File created in container 1 | ✅ |
| File accessible in container 2 | ✅ |
🎉 You Did It!
You've successfully created a Kubernetes Pod with shared volumes! This is a critical skill for:
- ✅ Web applications – Sharing files between web server and application server
- ✅ Logging – Centralized log collection
- ✅ Data processing – Sharing intermediate data
- ✅ Backup and restore – Sharing backup files
📚 Quick Reference
Volume Commands
| Command | Purpose |
|---|---|
kubectl apply -f volume-share-devops.yaml |
Create Pod with volume |
kubectl exec -it <pod> -c <container> -- /bin/bash |
Get shell in container |
kubectl exec <pod> -c <container> -- <command> |
Run command in container |
kubectl describe pod <pod> |
View volume details |
Volume YAML Template
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: container-1
image: image:latest
volumeMounts:
- name: shared-volume
mountPath: /mount/path
- name: container-2
image: image:latest
volumeMounts:
- name: shared-volume
mountPath: /other/path
volumes:
- name: shared-volume
emptyDir: {}
Stay tuned for Day 55! 🚀
Top comments (0)