Warrior, this is one of the most important Kubernetes chapters.
So far, you've learned:
Deployment → Pods → ContainersBut containers are generally ephemeral.
That creates a serious problem:
What happens to my data when a Pod is deleted or recreated?
For stateless applications, losing local container data may be fine.
For databases like PostgreSQL, MySQL, MongoDB, it can be disastrous.
Let's understand how Kubernetes handles storage.
Imagine a Node.js container:
┌────────────────────────────┐
│ Node.js Container │
│ │
│ /app │
│ /app/uploads │
│ /app/data │
│ │
└────────────────────────────┘Suppose your application writes:
/app/data/user.jsonThen the container crashes.
Kubernetes creates a replacement:
Old container
❌
↓
New containerThe new container has its own writable filesystem.
So:
Old Container
/app/data/user.json
❌
New Container
/app/data/
emptyThat's the problem.
Kubernetes provides Volumes so data can live outside the container's writable layer.
Instead of:
Container
↓
Container filesystemwe can have:
Container
↓
Volume
↓
StorageThen:
Container dies
↓
New container
↓
Same volume
↓
Data remainsThink of a volume as:
A storage location that can be mounted inside a Pod.
For example:
Pod
│
┌────────┴────────┐
│ │
Container Volume
│ │
└───────┬─────────┘
│
/dataThe container sees:
/databut the actual storage can live somewhere outside the container filesystem.
emptyDir#The simplest Kubernetes volume is:
emptyDirWhen a Pod is created:
Pod created
↓
emptyDir createdContainers inside the Pod can use it.
Example:
apiVersion: v1
kind: Pod
metadata:
name: volume-demo
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: shared-data
mountPath: /data
volumes:
- name: shared-data
emptyDir: {}Now the container gets:
/dataemptyDir Mean?#emptyDir starts empty.
Pod starts
↓
emptyDir = emptyApplication writes:
/data/file.txtNow:
/data
└── file.txtIf the container restarts inside the same Pod, the emptyDir data normally remains.
But:
If the Pod itself is deleted, the
emptyDiris deleted.
This distinction is extremely important.
Suppose:
Pod
│
└── Container
❌ crashesKubernetes restarts the container.
The Pod still exists.
Therefore:
emptyDir
↓
usually survives container restartBut:
Pod
❌ deletedthen:
emptyDir
❌ deletedemptyDir Is Useful#It's useful for temporary data.
Examples:
Upload
↓
Temporary file
↓
Process
↓
DeletePod
│
├── Main application
│
├── Sidecar
│
└── emptyDir
↑
│
Both containers access itSuppose:
Pod
│
├── Application
│
└── LoggerBoth need access to:
/logsYou can use:
volumes:
- name: shared-logs
emptyDir: {}Mount it into both containers:
containers:
- name: app
image: my-app
volumeMounts:
- name: shared-logs
mountPath: /logs
- name: logger
image: log-collector
volumeMounts:
- name: shared-logs
mountPath: /logsNow:
Pod
│
┌───────┴────────┐
│ │
App Logger
│ │
└───────┬────────┘
│
shared volume
/logsemptyDir Is NOT Persistent Storage#This is the key point.
If you need:
Database
User uploads
Documents
Permanent application datadon't use emptyDir as your primary persistent storage.
You need Kubernetes persistent storage mechanisms.
That brings us to:
PersistentVolume
PersistentVolumeClaim
StorageClassA PersistentVolume (PV) represents storage available to the Kubernetes cluster.
Think:
PV = actual storage resourceConceptually:
Kubernetes Cluster
│
▼
PersistentVolume
│
▼
Actual StorageThe actual storage could be backed by cloud storage such as:
AWS EBS
Google Persistent Disk
Azure Disk
NFS
Ceph
other storage systemsA developer usually doesn't want to manually select a physical disk.
Instead, the application says:
"I need 20 GB of persistent storage."
That's a:
PersistentVolumeClaimor:
PVCThink:
PV
↓
Storage available
PVC
↓
Application's request for storageImagine a rental system.
PV = Apartment
PVC = Rental application
Pod = TenantThe tenant says:
I need an apartment with 2 bedrooms.
That's the PVC.
Kubernetes finds suitable storage.
Kubernetes
│
┌───────┴────────┐
│ │
Pod PVC
│ │
│ │
└───────┬────────┘
│
▼
PV
│
▼
Physical/Cloud
StorageExample:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10GiThis means:
I want 10 GiB of persistent storage.
Apply:
kubectl apply -f pvc.yamlCheck:
kubectl get pvcYou may see:
NAME STATUS VOLUME CAPACITY
app-storage Bound pvc-abc 10GiBound Mean?#You might see:
STATUS
BoundThis means:
PVC
↓
Successfully connected to storageConceptually:
PVC
│
│ Bound
▼
PVNow the Pod can use it:
apiVersion: v1
kind: Pod
metadata:
name: storage-demo
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: app-storage
mountPath: /data
volumes:
- name: app-storage
persistentVolumeClaim:
claimName: app-storageNow:
Container
│
▼
/data
│
▼
PVC
│
▼
PV
│
▼
Persistent StorageSuppose the Pod gets deleted:
Pod
❌Kubernetes creates another Pod:
New PodThe new Pod can mount the same PVC:
New Pod
│
▼
same PVC
│
▼
same storageSo:
Pod 1
↓
PVC
↓
Data
Pod 1 deleted
↓
Pod 2
↓
same PVC
↓
Data still existsThat's the whole point of persistent storage.
Now we reach an important production concept.
Imagine you have:
100 applicationsand manually create PVs for every application.
That's inconvenient.
Kubernetes supports:
StorageClassA StorageClass defines how storage should be dynamically provisioned.
Think:
PVC
↓
StorageClass
↓
Dynamic provisioning
↓
PV
↓
Cloud storageWithout dynamic provisioning:
Admin
↓
Create PV manually
↓
Developer creates PVCWith dynamic provisioning:
Developer
↓
Creates PVC
↓
StorageClass
↓
Kubernetes provisions storage
↓
PV created
↓
PVC becomes BoundThis is much more convenient.
Suppose you're running Kubernetes on AWS EKS.
You might have:
PVC
↓
StorageClass
↓
AWS EBSOn GKE:
PVC
↓
StorageClass
↓
Google Persistent DiskOn AKS:
PVC
↓
StorageClass
↓
Azure DiskThe application doesn't need to know the physical storage details.
PVCs commonly use these access modes:
ReadWriteOnce
ReadOnlyMany
ReadWriteManyLet's understand them.
Read + WriteThe volume can generally be mounted read-write by Pods on a single node at a time.
Common example:
PostgreSQLMany Pods
↓
Read onlyMultiple nodes can mount the volume read-only, depending on the storage backend.
Pod A ─┐
Pod B ─┼──> Same volume
Pod C ─┘Multiple nodes can mount it read-write, if the underlying storage supports it.
NFS and certain distributed filesystems can support RWX.
Now you can understand the difference between:
Statelessand:
StatefulExample:
Next.js
Node.js APIUsually:
Request
↓
Pod
↓
ResponseThe Pod doesn't need to permanently store user data locally.
Example:
PostgreSQL
MongoDB
MySQLThey maintain important data:
Users
Orders
Payments
TransactionsTherefore persistent storage is required.
A typical Kubernetes architecture:
Service
│
┌───────────┼───────────┐
▼ ▼ ▼
Pod A Pod B Pod C
│ │ │
Node.js Node.js Node.jsIf Pod A dies:
Pod A ❌No important application state should be lost.
Deployment creates:
Pod DFor PostgreSQL:
PostgreSQL
│
▼
PVC
│
▼
Persistent
StorageIf the PostgreSQL Pod restarts:
Pod dies
↓
New Pod
↓
Same storage
↓
Database data remainsKubernetes provides another workload type:
StatefulSetIt is designed for applications that need stable identity and/or persistent storage.
For example:
postgres-0
postgres-1
postgres-2Unlike a typical Deployment where Pods may have generated names:
node-api-7d89f6...
node-api-7d89f6...StatefulSet gives stable identities.
We'll study StatefulSets in more detail later when discussing production workloads.
| Feature | Deployment | StatefulSet |
|---|---|---|
| Typical use | Stateless apps | Stateful apps |
| Stable Pod identity | ❌ | ✅ |
| Persistent storage | Possible | Common |
| Typical example | Node.js API | PostgreSQL |
| Scaling | Easy | More ordered |
| Pod names | Generated | Stable ordinal names |
Don't interpret this as "StatefulSet automatically makes a database production-ready." Database operation still requires backups, replication, failover, upgrades, etc.
Here's the hierarchy you should remember:
Application
│
▼
Pod
│
volumeMount
│
▼
Volume
│
▼
PVC
│
▼
PV
│
▼
Storage ProviderWith dynamic provisioning:
Pod
│
▼
PVC
│
▼
StorageClass
│
▼
Dynamic Provisioning
│
▼
PV
│
▼
Cloud StorageThis confuses beginners.
A volume is something a Pod mounts.
Pod → VolumeA request for persistent storage.
Application → PVCThe persistent storage resource.
PVC → PVDefines how storage can be dynamically provisioned.
PVC → StorageClass → PVImagine your application:
Next.js
↓
Node.js API
↓
PostgreSQLKubernetes:
Internet
│
▼
Ingress
│
▼
Node API
│
▼
PostgreSQL Service
│
▼
PostgreSQL Pod
│
▼
PVC
│
▼
Persistent StorageIf the PostgreSQL Pod dies:
PostgreSQL Pod
❌
↓
New PostgreSQL Pod
↓
Same PVC
↓
Same dataPersistent storage does not mean backup.
Suppose:
Database
↓
Persistent DiskThe disk survives Pod deletion.
But if:
Disk gets corruptedor:
Someone deletes the storageyour data can still be lost.
Therefore production databases need:
Persistent storage
+
Backups
+
Replication/HA where appropriate
+
Monitoring
+
Disaster recoveryThis distinction is extremely important.
Using:
emptyDirfor database data.
❌ Dangerous.
Thinking:
PVC = backup❌ No.
PVC provides persistent storage access, not backup.
Assuming every storage system supports:
ReadWriteMany❌ Not necessarily.
Access modes depend on the storage implementation.
Putting user uploads inside a random Pod filesystem.
For example:
/app/uploadsIf your application has:
Pod A
Pod B
Pod Ceach Pod can have its own local filesystem.
Instead consider:
Object Storagesuch as:
Amazon S3
Google Cloud Storage
Azure Blob Storagefor many user-upload scenarios.
Containers have ephemeral writable storage. Volumes provide storage that can be shared between containers or have a lifecycle independent of an individual container.
emptyDir?#A temporary volume created when a Pod is assigned to a node. It survives container restarts within that Pod but is deleted when the Pod is removed.
A cluster-level storage resource representing persistent storage available to Kubernetes workloads.
A request from a workload for a certain amount and type of persistent storage.
A Kubernetes object that describes classes of storage and enables dynamic provisioning of persistent volumes.
Typically:
Pod deleted
↓
PVC remains
↓
Persistent storage remains
↓
New Pod mounts PVCThe exact behavior depends on the storage and reclaim policy.
No.
PVC provides persistent storage; it doesn't replace backups.
emptyDir
↓
Temporary Pod storage
Volume
↓
Storage mounted into Pod
PVC
↓
Application requests storage
PV
↓
Persistent storage resource
StorageClass
↓
Dynamic storage provisioningAnd remember this:
Pod deleted
↓
emptyDir → gone
Pod deleted
↓
PVC → normally remains
↓
Persistent data → remainsYou now have:
Kubernetes Cluster
│
┌───────────┴───────────┐
│ │
DEV PROD
│ │
Deployment Deployment
│ │
ReplicaSet ReplicaSet
│ │
Pods Pods
│ │
Containers Containers
│ │
┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │
ConfigMap Secret ConfigMap Secret
│
▼
Volume
│
▼
PVC
│
▼
PV
│
▼
Persistent StorageContainers run your application; Volumes preserve or share data; PVCs request persistent storage; PVs represent that storage.
This is a big chapter.
We'll build the complete networking picture:
Pod IP
↓
Container communication
↓
Pod-to-Pod communication
↓
Service
↓
ClusterIP
↓
NodePort
↓
LoadBalancer
↓
DNS
↓
Ingress
↓
InternetAnd you'll finally understand how a request travels through a Kubernetes cluster from browser → Ingress → Service → Pod → container.
Mark it as complete to track your mastery.