DEV Community

janak0ff
janak0ff

Posted on

Day 55: Kubernetes Sidecar Containers

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.

  1. Create a pod named volume-share-devops.
  2. For the first container, use image debian with latest tag only and remember to mention the tag i.e debian:latest, container should be named as volume-container-devops-1, and run a sleep command for it so that it remains in running state. Volume volume-share should be mounted at path /tmp/official.
  3. For the second container, use image debian with the latest tag only and remember to mention the tag i.e debian:latest, container should be named as volume-container-devops-2, and again run a sleep command for it so that it remains in running state. Volume volume-share should be mounted at path /tmp/apps.
  4. Volume name should be volume-share of type emptyDir.
  5. After creating the pod, exec into the first container i.e volume-container-devops-1, and just for testing create a file official.txt with the content Welcome to xFusionCorp Industries under the mounted path of first container i.e /tmp/official.
  6. The file official.txt should be present under the mounted path /tmp/apps on the second container volume-container-devops-2 as 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 ✅   │              │     │
│  │  └──────────────────┘          └──────────────────┘              │     │
│  └────────────────────────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

📋 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        │        │   │
│  │  └────────────────────────┘  └────────────────────────────┘        │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

🔧 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
Enter fullscreen mode Exit fullscreen mode

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: {}
Enter fullscreen mode Exit fullscreen mode

📖 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
Enter fullscreen mode Exit fullscreen mode

Output:

pod/volume-share-devops created
Enter fullscreen mode Exit fullscreen mode

Step 3: Verify the Pod is Running

# Check pod status
kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Output:

NAME                  READY   STATUS    RESTARTS   AGE
volume-share-devops   2/2     Running   0          10s
Enter fullscreen mode Exit fullscreen mode
# Get detailed pod information
kubectl describe pod volume-share-devops
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

📝 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
Enter fullscreen mode Exit fullscreen mode

📊 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
Enter fullscreen mode Exit fullscreen mode

🎯 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
Enter fullscreen mode Exit fullscreen mode

✅ Correct:

kubectl exec -it volume-share-devops -c volume-container-devops-1 -- /bin/bash
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

✅ Correct:

mkdir -p /tmp/official
echo "content" > /tmp/official/official.txt
Enter fullscreen mode Exit fullscreen mode

Mistake 3: Container Exiting Immediately

❌ Wrong:

containers:
- name: my-container
  image: debian:latest
Enter fullscreen mode Exit fullscreen mode

✅ Correct:

containers:
- name: my-container
  image: debian:latest
  command: ["sleep"]
  args: ["infinity"]
Enter fullscreen mode Exit fullscreen mode

📊 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:

  1. Use a PersistentVolumeClaim for persistent storage
   volumes:
   - name: persistent-storage
     persistentVolumeClaim:
       claimName: my-pvc
Enter fullscreen mode Exit fullscreen mode
  1. Mount ConfigMaps for configuration
   volumes:
   - name: config
     configMap:
       name: app-config
Enter fullscreen mode Exit fullscreen mode
  1. Mount Secrets for sensitive data
   volumes:
   - name: secrets
     secret:
       secretName: app-secrets
Enter fullscreen mode Exit fullscreen mode

✅ 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: {}
Enter fullscreen mode Exit fullscreen mode

Stay tuned for Day 55! 🚀

DevOps #Kubernetes #K8s #SharedVolumes #KodeKloud #100DaysOfDevOps #DevOpsJourney

Top comments (0)