Chapter 7: Volumes & Storage
Authored by syscook.dev
What are Volumes and Storage in Kubernetes?
Volumes in Kubernetes provide persistent storage for pods and enable data sharing between containers. Storage is essential for stateful applications that need to persist data beyond the lifecycle of individual pods.
Key Concepts:
- Volumes: Storage units attached to pods
- Persistent Volumes (PV): Cluster-wide storage resources
- Persistent Volume Claims (PVC): Storage requests from users
- Storage Classes: Dynamic provisioning of storage
- Volume Types: EmptyDir, HostPath, NFS, Cloud Storage
- Data Persistence: Ensuring data survives pod restarts
Why Use Volumes and Storage?
1. Data Persistence
Ensure data survives pod restarts and failures.
# Example: Pod with persistent volume
apiVersion: v1
kind: Pod
metadata:
name: database-pod
namespace: production
spec:
containers:
- name: postgres
image: postgres:13
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: "myapp"
- name: POSTGRES_USER
value: "user"
- name: POSTGRES_PASSWORD
value: "password"
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pvc
2. Data Sharing
Share data between containers in the same pod.
# Example: Pod with shared volume
apiVersion: v1
kind: Pod
metadata:
name: web-app-pod
namespace: production
spec:
containers:
- name: web-server
image: nginx:1.20
ports:
- containerPort: 80
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
- name: log-processor
image: fluent/fluent-bit:1.8
volumeMounts:
- name: shared-data
mountPath: /var/log/nginx
volumes:
- name: shared-data
emptyDir: {}
How to Use Volumes and Storage?
1. Volume Types
EmptyDir Volume
# Example: EmptyDir volume for temporary storage
apiVersion: v1
kind: Pod
metadata:
name: temp-pod
spec:
containers:
- name: app
image: nginx:1.20
volumeMounts:
- name: temp-storage
mountPath: /tmp
volumes:
- name: temp-storage
emptyDir:
sizeLimit: 1Gi
HostPath Volume
# Example: HostPath volume for host file access
apiVersion: v1
kind: Pod
metadata:
name: host-pod
spec:
containers:
- name: app
image: nginx:1.20
volumeMounts:
- name: host-storage
mountPath: /host-data
volumes:
- name: host-storage
hostPath:
path: /data
type: DirectoryOrCreate
2. Persistent Volumes
Static PV
# Example: Static persistent volume
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-pv
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: "/mnt/data/postgres"
Dynamic PV with Storage Class
# Example: Storage class for dynamic provisioning
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
encrypted: "true"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete
3. Persistent Volume Claims
Basic PVC
# Example: Basic persistent volume claim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: production
spec:
storageClassName: fast-ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
PVC with Specific Requirements
# Example: PVC with specific requirements
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-pvc
namespace: production
spec:
storageClassName: fast-ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
selector:
matchLabels:
type: database
Practical Examples
1. Database with Persistent Storage
Step 1: Create Storage Class
#!/bin/bash
# create-storage-class.sh
kubectl apply -f - <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
encrypted: "true"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete
EOF
echo "Storage class created successfully!"
Step 2: Create PVC
#!/bin/bash
# create-pvc.sh
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: production
spec:
storageClassName: fast-ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
EOF
echo "PVC created successfully!"
Step 3: Create Database Deployment
#!/bin/bash
# create-database-deployment.sh
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deployment
namespace: production
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: "myapp"
- name: POSTGRES_USER
value: "user"
- name: POSTGRES_PASSWORD
value: "password"
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pvc
EOF
echo "Database deployment created successfully!"
Best Practices
1. Storage Class Configuration
# Good: Proper storage class configuration
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
encrypted: "true"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete
2. PVC Configuration
# Good: Proper PVC configuration
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-pvc
namespace: production
spec:
storageClassName: fast-ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
3. Volume Mount Configuration
# Good: Proper volume mount configuration
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
subPath: postgres
Common Pitfalls and Solutions
1. Storage Class Issues
# ❌ Problem: No storage class available
# Error: no storage class is default
# ✅ Solution: Set default storage class
kubectl patch storageclass fast-ssd -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
2. PVC Binding Issues
# ❌ Problem: PVC not binding
# Error: no persistent volumes available
# ✅ Solution: Check storage class and node affinity
kubectl get storageclass
kubectl get pv
kubectl describe pvc postgres-pvc
3. Volume Mount Issues
# ❌ Problem: Volume mount fails
# Error: path not found
# ✅ Solution: Check mount path and permissions
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
subPath: postgres
Conclusion
Volumes and storage are essential for stateful applications in Kubernetes. By understanding:
- What volumes and storage are and their purposes
- Why they're important for data persistence and sharing
- How to use them effectively in applications
You can create robust applications that maintain data across pod restarts and failures. Proper configuration ensures that your applications have reliable storage for their data needs.
Next Steps
- Practice with different storage scenarios
- Learn about application deployment
- Move on to Chapter 8: Application Deployment
This tutorial is part of the Kubernetes Mastery series by syscook.dev