Skip to content

Storage

First PublishedByAtif Alam

Containers are ephemeral by default — when a pod restarts, any data written to the container’s filesystem is lost. Kubernetes provides several ways to persist or share data.

A Volume is a directory accessible to containers in a pod. Its lifecycle is tied to the pod (not the container). Common types:

  • emptyDir — Created when a pod starts, deleted when the pod is removed. Useful for scratch space or sharing files between containers in the same pod.
  • hostPath — Mounts a file or directory from the host node’s filesystem. Use with caution (ties pod to a specific node).
spec:
containers:
- name: app
volumeMounts:
- name: scratch
mountPath: /tmp/data
volumes:
- name: scratch
emptyDir: {}

PersistentVolumes and PersistentVolumeClaims

Section titled “PersistentVolumes and PersistentVolumeClaims”

For data that outlives a pod (databases, file uploads), use PersistentVolumes (PV) and PersistentVolumeClaims (PVC).

  • PV — A piece of storage provisioned by an admin or dynamically by a StorageClass.
  • PVC — A request for storage by a user. Kubernetes binds the PVC to a matching PV.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard

Use the PVC in a pod:

spec:
containers:
- name: db
volumeMounts:
- name: data
mountPath: /var/lib/data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc

A StorageClass defines how storage is provisioned (e.g. SSD vs HDD, which cloud provider backend). When a PVC references a StorageClass, Kubernetes automatically provisions a PV.

Terminal window
kubectl get storageclass

Store non-sensitive configuration as key-value pairs. Inject into pods as environment variables or mounted files.

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: "db.example.com"
LOG_LEVEL: "info"

Use as environment variables:

env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST

Or mount as a file:

volumeMounts:
- name: config
mountPath: /etc/config
volumes:
- name: config
configMap:
name: app-config

Like ConfigMaps but for sensitive data (passwords, tokens, TLS certs). Values are base64-encoded (not encrypted by default — enable encryption at rest for production).

apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
password: cGFzc3dvcmQxMjM= # base64 of "password123"

Use as environment variables or volume mounts, same pattern as ConfigMaps:

env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
  • Use emptyDir for scratch space; PVC for persistent data.
  • StorageClasses enable dynamic provisioning — no need to pre-create PVs.
  • ConfigMaps for config, Secrets for sensitive data. Both inject into pods as env vars or files.
  • Secrets are base64-encoded, not encrypted. Enable encryption at rest in production.