Data Classification in Containerized Environments
Container filesystems are inherently ephemeral. When a container crashes or is deleted, any changes made to its local storage are lost. To manage data effectively, we generally categorize container data into three types:
- Configuration Data: Initial settings or files required at startup.
- Transient Shared Data: Temporary information shared between containers within the same Pod (e.g., a local cache).
- Persistent Data: Information that must survive the Pod lifecycle, such as database files or user uploads.
Kubernetes Volumes
A Volume is an abstractoin that allows containers to access storage. Unlike the container's internal filesystem, a Volume's lifetime is tied to the Pod, ensuring data persists even if individual containers within that Pod restart.
emptyDir
The emptyDir volume is created when a Pod is assigned to a Node and exists as long as that Pod is running on that node. It starts empty and is primari used for temporary scratch space or as a communication bridge between containers in the same Pod.
apiVersion: v1
kind: Pod
metadata:
name: shared-data-pod
spec:
containers:
- name: writer-app
image: busybox
command: ["/bin/sh", "-c", "echo 'Hello from writer' > /mnt/data/msg; sleep 3600"]
volumeMounts:
- name: scratch-pad
mountPath: /mnt/data
- name: reader-app
image: busybox
command: ["/bin/sh", "-c", "cat /mnt/data/msg; sleep 3600"]
volumeMounts:
- name: scratch-pad
mountPath: /mnt/data
volumes:
- name: scratch-pad
emptyDir:
sizeLimit: 256Mi
hostPath
A hostPath volume mounts a file or directory from the host node's filesystem into you're Pod. This is often used for system-level monitoring or logging tools that need access to the underlying node.
apiVersion: v1
kind: Pod
metadata:
name: node-log-viewer
spec:
containers:
- name: log-tailer
image: alpine
command: ["tail", "-f", "/var/log/system.log"]
volumeMounts:
- name: system-logs
mountPath: /var/log/system.log
readOnly: true
volumes:
- name: system-logs
hostPath:
path: /var/log/syslog
type: File
NFS (Network File System)
NFS volumes allow multiple Pods to mount the same share simultaneously. Since the data resides on a remote server, it persists even after the Pod is deleted.
apiVersion: v1
kind: Pod
metadata:
name: nfs-web-pod
spec:
containers:
- name: nginx-server
image: nginx
volumeMounts:
- name: remote-assets
mountPath: /usr/share/nginx/html
volumes:
- name: remote-assets
nfs:
server: 192.168.1.100
path: /exports/web-data
PersistentVolumes and PersistentVolumeClaims
To decouple storage infrastructure from application logic, Kubernetes provides the PersistentVolume (PV) and PersistentVolumeClaim (PVC) system.
- PersistentVolume (PV): A piece of storage in the cluster provisioned by an administrator or dynamically provisioned using Storage Classes. It is a cluster-level resource.
- PersistentVolumeClaim (PVC): A request for storage by a user. It defines specific requirements like size and access modes.
PV Reclaim Policies
When a PVC is deleted, the Reclaim Policy determines what happens to the PV:
- Retain: The PV remains, allowing for manual recovery.
- Recycle: Performs a basic scrub (
rm -rf) to make the volume available again (deprecated). - Delete: The PV and the associated storage asset in the external infrastructure are removed.
Access Modes
- ReadWriteOnce (RWO): Mounted as read-write by a single node.
- ReadOnlyMany (ROX): Mounted as read-only by many nodes.
- ReadWriteMany (RWX): Mounted as read-write by many nodes.
Static Provisioning Example
First, create the PersistentVolume:
apiVersion: v1
kind: PersistentVolume
metadata:
name: static-nfs-pv
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: manual-nfs
nfs:
path: /srv/nfs/shared
server: 10.10.20.50
Next, request the storage via a PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-storage-pvc
spec:
storageClassName: manual-nfs
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
Dynamic Provisioning with StorageClass
Manually creating PVs becomes unscalable in large clusters. A StorageClass allows administrators to define "templates" for storage. When a user creates a PVC referencing a StorageClass, the cluster automatically provisions the PV.
Configuring an NFS Provisioner
In this scenario, an external provisioner (like nfs-subdir-external-provisioner) monitors the cluster for PVCs requesting a specific StorageClass.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-nfs-storage
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "false"
reclaimPolicy: Delete
mountOptions:
- hard
- nfsvers=4.1
Using Dynamic Storage in a Deployment
When a PVC is created using the fast-nfs-storage class, the PV is automatically generated and bound.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dynamic-web-pvc
spec:
storageClassName: fast-nfs-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: html-dir
mountPath: /usr/share/nginx/html
volumes:
- name: html-dir
persistentVolumeClaim:
claimName: dynamic-web-pvc
In the dynamic model, Kubernetes handles the lifecycle of the underlying storage assets automatically, significantly reducing administrative overhead while providing developers with self-service storage capabilities.