JumpToTech DevOps Lab
Production-Style StatefulSet + Persistent Storage + Argo CD
Estimated time: 2–3 hours
Level: Intermediate
Technologies: Kubernetes, StatefulSet, PV, PVC, StorageClass, Nginx, Git, GitHub, Argo CD
1. Lab Objective
In this lab you will deploy a stateful workload using Kubernetes and manage it through Argo CD.
By the end of the lab, you should understand this architecture:
GitHub Repository
|
v
Argo CD
|
v
Kubernetes
|
v
StatefulSet
|
+----+----+
| | |
web-0 web-1 web-2
| | |
PVC PVC PVC
| | |
PV PV PV
| | |
+----+----+
|
v
Persistent Storage
You will prove that:
Pod != Persistent Data
A Pod can be destroyed and recreated while its persistent data survives.
2. Important Concepts
Before starting, understand these components.
StatefulSet
A StatefulSet manages Pods that require stable identities.
Instead of names such as:
web-5d8478b7c4-xk29p
web-5d8478b7c4-8h2mm
a StatefulSet creates:
web-0
web-1
web-2
These identities are stable.
If:
web-1
is deleted, StatefulSet recreates:
web-1
rather than creating a randomly named replacement.
3. PV vs PVC vs Storage
Understand this chain:
Pod
|
v
PVC
|
v
PV
|
v
Actual Storage
PVC — PersistentVolumeClaim
PVC is a request for storage.
Example:
I need 2Gi of persistent storage.
PV — PersistentVolume
PV is the Kubernetes resource representing persistent storage.
Actual Storage
The real storage backend could be:
AWS EBS
AWS EFS
Azure Disk
Google Persistent Disk
NFS
Ceph
etc.
For example:
Pod
↓
PVC
↓
PV
↓
AWS EBS
4. StorageClass
StorageClass defines how a class of storage can be dynamically provisioned.
Check available StorageClasses:
kubectl get storageclass
Short version:
kubectl get sc
Look for the default StorageClass:
kubectl get sc
Example:
NAME PROVISIONER
standard (default) ...
The exact output depends on your cluster.
Conceptually:
PVC
|
| requests storage
v
StorageClass
|
v
CSI Provisioner
|
v
Actual Volume
|
v
PV
|
v
PVC becomes Bound
This is called:
Dynamic Provisioning
5. Check the Cluster
Run:
kubectl cluster-info
Then:
kubectl get nodes
Expected:
NAME STATUS ROLES
node-1 Ready ...
Do not continue if your nodes are not Ready.
6. Create the Project
Create a directory:
mkdir statefulset-production-lab
cd statefulset-production-lab
Create directories:
mkdir -p k8s
Check:
tree
Expected:
statefulset-production-lab/
└── k8s/
If tree is unavailable:
find .
7. Create Namespace
Create:
vim k8s/namespace.yaml
Add:
apiVersion: v1
kind: Namespace
metadata:
name: stateful-app
labels:
app.kubernetes.io/part-of: stateful-app
Apply:
kubectl apply -f k8s/namespace.yaml
Verify:
kubectl get ns
8. Create ConfigMap
Production applications should separate configuration from the container image.
Create:
vim k8s/configmap.yaml
Add:
apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
namespace: stateful-app
data:
APP_ENV: "production"
LOG_LEVEL: "info"
Apply:
kubectl apply -f k8s/configmap.yaml
Check:
kubectl get configmap -n stateful-app
9. Create Secret
Create:
vim k8s/secret.yaml
For this training lab:
apiVersion: v1
kind: Secret
metadata:
name: web-secret
namespace: stateful-app
type: Opaque
stringData:
APP_PASSWORD: "jumptotech-lab-password"
Apply:
kubectl apply -f k8s/secret.yaml
Check:
kubectl get secret -n stateful-app
Production note: committing plaintext secrets to Git is not a production secret-management strategy. Real GitOps environments commonly integrate an external secrets solution, cloud secret manager, or encrypted/sealed secret workflow. This file is included only to demonstrate Kubernetes Secret consumption.
10. Create Headless Service
StatefulSets commonly use a Headless Service to provide stable network identities.
Create:
vim k8s/headless-service.yaml
Add:
apiVersion: v1
kind: Service
metadata:
name: web-headless
namespace: stateful-app
spec:
clusterIP: None
selector:
app: web
ports:
- name: http
port: 80
targetPort: 80
Notice:
clusterIP: None
This makes it a:
Headless Service
Architecture:
Headless Service
|
+---- web-0
|
+---- web-1
|
+---- web-2
11. Create Production-Style StatefulSet
Create:
vim k8s/statefulset.yaml
Add:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: stateful-app
spec:
serviceName: web-headless
replicas: 3
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
terminationGracePeriodSeconds: 30
containers:
- name: nginx
image: nginx:1.27
ports:
- name: http
containerPort: 80
envFrom:
- configMapRef:
name: web-config
- secretRef:
name: web-secret
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
volumeMounts:
- name: web-data
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: web-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
12. Understand volumeClaimTemplates
This is one of the most important parts:
volumeClaimTemplates:
- metadata:
name: web-data
StatefulSet uses this template to create a PVC for each replica.
With:
replicas: 3
you should receive approximately:
web-data-web-0
web-data-web-1
web-data-web-2
Architecture:
web-0
|
+---- web-data-web-0
|
v
PV
web-1
|
+---- web-data-web-1
|
v
PV
web-2
|
+---- web-data-web-2
|
v
PV
Each replica therefore maintains its own storage claim.
13. Create PodDisruptionBudget
Create:
vim k8s/pdb.yaml
Add:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
namespace: stateful-app
spec:
minAvailable: 2
selector:
matchLabels:
app: web
The PDB protects application availability during voluntary disruptions, such as certain node-maintenance operations.
It does not prevent every possible Pod failure or deletion.
14. Check All Files
Run:
tree
Expected:
.
└── k8s
├── configmap.yaml
├── headless-service.yaml
├── namespace.yaml
├── pdb.yaml
├── secret.yaml
└── statefulset.yaml
15. Validate Before Deployment
Use client-side parsing/validation first:
kubectl apply --dry-run=client -f k8s/
Then inspect:
kubectl diff -f k8s/
kubectl diff may return a non-zero exit code when differences exist; that does not necessarily mean the manifests are invalid.
16. Deploy
Apply:
kubectl apply -f k8s/
Watch:
kubectl get pods -n stateful-app -w
Expected:
web-0
web-1
web-2
Because OrderedReady is configured, StatefulSet normally progresses through ordinal replicas in order as they become Ready.
Press:
CTRL+C
when complete.
17. Inspect StatefulSet
Run:
kubectl get statefulset -n stateful-app
Short version:
kubectl get sts -n stateful-app
Then:
kubectl describe sts web -n stateful-app
Students should identify:
Replicas
Pod Management Policy
Update Strategy
Volume Claims
Selector
Containers
18. Inspect Pods
Run:
kubectl get pods -n stateful-app -o wide
Expected identities:
web-0
web-1
web-2
Compare this with a Deployment:
Deployment:
web-7d8bc9c87c-d7sk2
web-7d8bc9c87c-j82lm
StatefulSet:
web-0
web-1
web-2
19. Inspect PVCs
Run:
kubectl get pvc -n stateful-app
Expected:
NAME STATUS
web-data-web-0 Bound
web-data-web-1 Bound
web-data-web-2 Bound
The critical status is:
Bound
Now inspect one:
kubectl describe pvc web-data-web-0 -n stateful-app
Look for:
Status
Volume
Capacity
Access Modes
StorageClass
20. Inspect PVs
Run:
kubectl get pv
Notice that PV is cluster-scoped, while PVC is namespaced.
Find the PV bound to web-data-web-0:
kubectl get pvc web-data-web-0 \
-n stateful-app \
-o jsonpath='{.spec.volumeName}{"\n"}'
Save it:
PV_NAME=$(kubectl get pvc web-data-web-0 \
-n stateful-app \
-o jsonpath='{.spec.volumeName}')
Inspect:
kubectl describe pv "$PV_NAME"
Architecture:
web-0
|
v
web-data-web-0
|
v
PV
|
v
Storage Backend
21. Write Persistent Data
Enter:
kubectl exec -it web-0 \
-n stateful-app \
-- sh
Inside:
echo "<h1>JumpToTech Stateful Application</h1>" \
> /usr/share/nginx/html/index.html
Add another file:
echo "This data must survive Pod deletion." \
> /usr/share/nginx/html/data.txt
Check:
cat /usr/share/nginx/html/index.html
Check:
cat /usr/share/nginx/html/data.txt
Exit:
exit
22. Verify Application
Run:
kubectl port-forward \
pod/web-0 \
8080:80 \
-n stateful-app
Open another terminal:
curl localhost:8080
Expected:
<h1>JumpToTech Stateful Application</h1>
Stop port-forward with:
CTRL+C
23. Failure Test
Now deliberately destroy the Pod.
Before:
kubectl get pods -n stateful-app
Delete:
kubectl delete pod web-0 -n stateful-app
Watch:
kubectl get pods -n stateful-app -w
StatefulSet should restore:
web-0
Wait until:
web-0 1/1 Running
24. Verify Data Survived
Run:
kubectl exec web-0 \
-n stateful-app \
-- cat /usr/share/nginx/html/data.txt
Expected:
This data must survive Pod deletion.
This proves:
Pod lifecycle
!=
Persistent storage lifecycle
The Pod was destroyed.
The persistent claim/storage remained available.
The recreated web-0 mounted its storage again.
25. Compare Data Between Replicas
Check web-1:
kubectl exec web-1 \
-n stateful-app \
-- ls -la /usr/share/nginx/html
Do not assume it contains the file written to web-0.
Why?
Because:
web-0 → PVC-0 → Storage-0
web-1 → PVC-1 → Storage-1
web-2 → PVC-2 → Storage-2
The replicas have independent persistent claims.
26. Scale Up
Scale:
kubectl scale statefulset web \
--replicas=5 \
-n stateful-app
Watch:
kubectl get pods -n stateful-app -w
Expected:
web-0
web-1
web-2
web-3
web-4
Check claims:
kubectl get pvc -n stateful-app
You should now see additional claims for the new replicas.
27. Scale Down
Scale back:
kubectl scale statefulset web \
--replicas=3 \
-n stateful-app
Check:
kubectl get pods -n stateful-app
Then:
kubectl get pvc -n stateful-app
Notice the important behavior:
Do not assume scaling down deletes the corresponding PVCs.
StatefulSet storage retention is intentionally conservative because automatically deleting persistent data could be dangerous. StatefulSet also supports PVC retention-policy configuration when a workload explicitly requires different behavior.
28. Examine Stable Network Identity
Run:
kubectl get svc -n stateful-app
You should see:
web-headless
with:
CLUSTER-IP: None
Check DNS from inside the cluster:
kubectl run dns-test \
--image=busybox:1.36 \
--restart=Never \
-n stateful-app \
-- sleep 3600
Wait:
kubectl wait \
--for=condition=Ready \
pod/dns-test \
-n stateful-app \
--timeout=60s
Resolve:
kubectl exec dns-test \
-n stateful-app \
-- nslookup web-0.web-headless.stateful-app.svc.cluster.local
Try:
kubectl exec dns-test \
-n stateful-app \
-- nslookup web-1.web-headless.stateful-app.svc.cluster.local
This demonstrates stable network identity.
Clean up the test Pod:
kubectl delete pod dns-test -n stateful-app
29. Check ConfigMap Environment Variables
Run:
kubectl exec web-0 \
-n stateful-app \
-- printenv APP_ENV
Expected:
production
Check:
kubectl exec web-0 \
-n stateful-app \
-- printenv LOG_LEVEL
Expected:
info
30. Check Resource Requests and Limits
Run:
kubectl describe pod web-0 -n stateful-app
Find:
Requests:
cpu
memory
Limits:
cpu
memory
These help Kubernetes make scheduling decisions and enforce container resource limits.
31. Check Probes
Run:
kubectl describe pod web-0 -n stateful-app
Find:
Liveness
Readiness
Readiness Probe
Answers:
Should this Pod currently receive traffic?
Liveness Probe
Answers:
Does Kubernetes consider this container healthy enough to keep running,
or should it restart it?
32. Check PDB
Run:
kubectl get pdb -n stateful-app
Then:
kubectl describe pdb web-pdb -n stateful-app
Remember:
PDB != replica controller
PDB != protection against every failure
PDB != backup
It primarily constrains voluntary disruptions.
PART II — GITOPS WITH ARGO CD
33. Why Argo CD?
So far deployment was performed manually:
Engineer
|
kubectl apply
|
v
Kubernetes
Production GitOps introduces a different operating model:
Engineer
|
v
Git
|
v
GitHub
|
v
Argo CD
|
v
Kubernetes
Git becomes the desired-state source.
34. Important GitOps Rule
Once Argo CD owns this application, avoid treating manual kubectl apply as the normal deployment process.
Desired workflow:
Change YAML
↓
git add
↓
git commit
↓
git push
↓
Argo CD detects desired-state change
↓
Argo CD syncs
↓
Kubernetes changes
35. Create .gitignore
Create:
vim .gitignore
Add:
.DS_Store
*.log
.env
Do not put credentials, kubeconfigs, tokens, or private keys in the repository.
36. Git Repository
Initialize:
git init
Create branch:
git checkout -b main
Check:
git status
Add files:
git add .
Commit:
git commit -m "feat: add production-style stateful workload"
37. Push to GitHub
Create an empty repository in your GitHub account.
Example repository name:
statefulset-production-lab
Add your actual remote:
git remote add origin <YOUR-GITHUB-REPOSITORY-URL>
Verify:
git remote -v
Push:
git push -u origin main
The repository should contain:
statefulset-production-lab/
│
├── .gitignore
│
└── k8s/
├── namespace.yaml
├── configmap.yaml
├── secret.yaml
├── headless-service.yaml
├── statefulset.yaml
└── pdb.yaml
Again: the demo secret.yaml is for training. Do not use plaintext Git secrets for real production credentials.
38. Install Argo CD
Check first:
kubectl get ns argocd
If Argo CD is already installed, do not reinstall it.
If it is not installed, install Argo CD using the installation method provided for your training cluster.
After installation verify:
kubectl get pods -n argocd
Wait until the required Argo CD components are running.
39. Access Argo CD
For a local/training environment:
kubectl port-forward \
svc/argocd-server \
-n argocd \
8081:443
Then access:
https://localhost:8081
Retrieve the initial admin password when using the standard initial-secret setup:
kubectl -n argocd \
get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" \
| base64 -d
Then:
echo
Username:
admin
40. Create Argo CD Application Manifest
Create a new directory:
mkdir argocd
Create:
vim argocd/application.yaml
Add:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: stateful-app
namespace: argocd
spec:
project: default
source:
repoURL: YOUR_GITHUB_REPOSITORY_URL
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: stateful-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Replace:
YOUR_GITHUB_REPOSITORY_URL
with your repository URL.
41. Important: Avoid the Argo CD Bootstrap Loop
The Argo CD Application manifest itself is stored under:
argocd/application.yaml
but the Application watches only:
path: k8s
Therefore Argo CD manages the Kubernetes workload manifests under k8s/, while the Application definition can be bootstrapped separately.
Commit it:
git add argocd/application.yaml
git commit -m "feat: add Argo CD application"
git push
Bootstrap the Argo CD Application:
kubectl apply -f argocd/application.yaml
42. Check Argo CD
Run:
kubectl get applications -n argocd
Expected eventually:
NAME SYNC STATUS HEALTH STATUS
stateful-app Synced Healthy
You can also inspect:
kubectl describe application stateful-app -n argocd
43. Understand Automated Sync
We configured:
automated:
prune: true
selfHeal: true
Automated sync
Argo CD can automatically synchronize Git desired state into Kubernetes.
prune: true
If a resource managed by the Application is removed from Git, Argo CD can remove that managed resource from the cluster during sync.
selfHeal: true
If a managed Kubernetes resource drifts from Git, Argo CD can restore the Git-defined desired state.
This creates:
GIT
|
|
desired state
|
v
Argo CD
|
compare/reconcile
|
v
Kubernetes
44. GitOps Scaling Test
Do not scale manually for this test.
Edit:
vim k8s/statefulset.yaml
Change:
replicas: 3
to:
replicas: 4
Commit:
git add k8s/statefulset.yaml
git commit -m "scale: increase StatefulSet to four replicas"
git push
Watch:
kubectl get pods -n stateful-app -w
Eventually:
web-0
web-1
web-2
web-3
Check PVC:
kubectl get pvc -n stateful-app
The new replica should receive its corresponding claim.
45. GitOps Self-Healing Test
Git says:
replicas: 4
Now deliberately introduce drift:
kubectl scale statefulset web \
--replicas=2 \
-n stateful-app
Check:
kubectl get sts web -n stateful-app
Argo CD should detect that live state differs from Git.
With automated self-healing enabled, it should reconcile toward the desired state stored in Git.
Check:
kubectl get pods -n stateful-app -w
The desired replica count should return to the Git-defined value.
This demonstrates:
Git = Desired State
Cluster = Live State
Argo CD = Reconciliation
46. GitOps Update Test
Change image:
image: nginx:1.27
to a newer approved image tag available for your environment.
Commit:
git add k8s/statefulset.yaml
git commit -m "chore: update nginx image"
git push
Watch:
kubectl rollout status \
statefulset/web \
-n stateful-app
Then:
kubectl get pods -n stateful-app
Inspect:
kubectl describe sts web -n stateful-app
47. Check Persistent Data After Update
Check:
kubectl exec web-0 \
-n stateful-app \
-- cat /usr/share/nginx/html/data.txt
The original persistent data should still exist if the same PVC/storage remains attached.
This demonstrates the separation between:
Application lifecycle
Container lifecycle
Pod lifecycle
Storage lifecycle
48. Production Architecture
The completed system conceptually looks like:
DEVELOPER
|
|
git push
|
v
GITHUB
|
|
v
ARGO CD
|
desired-state sync
|
v
KUBERNETES CLUSTER
|
v
STATEFULSET
|
+------------+------------+
| | |
v v v
web-0 web-1 web-2
| | |
v v v
PVC-0 PVC-1 PVC-2
| | |
v v v
PV-0 PV-1 PV-2
| | |
+------------+------------+
|
v
STORAGE BACKEND
In an AWS EKS environment using EBS, the lower portion may conceptually be:
StatefulSet
|
v
Pod
|
v
PVC
|
v
StorageClass
|
v
EBS CSI Driver
|
v
AWS EBS Volume
49. Troubleshooting
Pod Pending
Run:
kubectl describe pod web-0 -n stateful-app
Check events:
kubectl get events \
-n stateful-app \
--sort-by=.lastTimestamp
PVC Pending
Run:
kubectl get pvc -n stateful-app
Then:
kubectl describe pvc web-data-web-0 -n stateful-app
Check:
kubectl get sc
Potential causes include:
No suitable/default StorageClass
CSI driver unavailable
Provisioning failure
Topology/zone constraints
Storage quota
Access-mode mismatch
StatefulSet Not Ready
Run:
kubectl describe sts web -n stateful-app
Then:
kubectl describe pod web-0 -n stateful-app
Logs:
kubectl logs web-0 -n stateful-app
Argo CD OutOfSync
Check:
kubectl describe application stateful-app -n argocd
Confirm:
repository URL
branch
path
permissions
manifest validity
destination
50. Useful Commands Cheat Sheet
kubectl get sts -A
kubectl get pods -A
kubectl get pvc -A
kubectl get pv
kubectl get sc
kubectl get svc -A
kubectl get pdb -A
kubectl describe sts web -n stateful-app
kubectl describe pod web-0 -n stateful-app
kubectl describe pvc web-data-web-0 -n stateful-app
kubectl logs web-0 -n stateful-app
kubectl get events -n stateful-app --sort-by=.lastTimestamp
kubectl get applications -n argocd
51. Interview Questions
Students must be able to answer these after completing the lab.
What is a StatefulSet?
A StatefulSet is a Kubernetes workload controller designed for applications whose replicas require stable identities, stable network identities, ordered lifecycle semantics, or stable per-replica storage.
Deployment vs StatefulSet?
Deployment replicas are generally interchangeable.
StatefulSet replicas have stable ordinal identities such as:
web-0
web-1
web-2
and commonly use stable per-replica storage.
What is PVC?
A PersistentVolumeClaim is a request for persistent storage.
What is PV?
A PersistentVolume is a Kubernetes resource representing persistent storage available to workloads.
What is the difference between PV and actual storage?
PV is a Kubernetes resource.
The actual storage backend may be something such as:
AWS EBS
EFS
NFS
Azure Disk
Google Persistent Disk
What is StorageClass?
StorageClass describes a class of storage and how storage may be dynamically provisioned.
What is dynamic provisioning?
Dynamic provisioning allows storage to be provisioned automatically when a PVC requests it rather than requiring an administrator to manually pre-create every PV.
What does volumeClaimTemplates do?
It allows a StatefulSet to create a persistent storage claim for each replica.
Why does StatefulSet use stable identity?
Because individual replicas may need a consistent identity, network name, and association with their own persistent storage.
Does deleting a StatefulSet Pod delete its data?
Not necessarily. Pod lifecycle and persistent storage lifecycle are separate. PVC/PV retention and reclaim behavior determine what happens to persistent storage.
Does StatefulSet automatically configure database replication?
No.
Running:
mysql-0
mysql-1
mysql-2
does not automatically create a properly replicated MySQL cluster.
Database replication, leader election, failover, consistency, backups, and recovery require database-specific configuration or an appropriate Kubernetes Operator/application architecture.
Can Deployment use PVC?
Yes.
Persistent storage is not exclusive to StatefulSet.
StatefulSet is selected when stable per-replica identity and lifecycle/storage relationships are important.
Why use a Headless Service?
It supports direct service discovery and stable DNS identities for StatefulSet replicas rather than providing only one load-balanced Service virtual IP.
What does Argo CD do?
Argo CD continuously compares Kubernetes live state with the desired state stored in Git and can synchronize the cluster to that desired state.
52. Student Assignment
Complete all tasks without copying the finished StatefulSet from another student.
Your final environment must contain:
Namespace
ConfigMap
Secret
Headless Service
StatefulSet
3+ replicas
PVC per replica
PV-backed persistent storage
Resource requests
Resource limits
Readiness probe
Liveness probe
PodDisruptionBudget
Git repository
Argo CD Application
Automated synchronization
Self-healing
Persistent-data test
Perform and document these tests:
1. Delete web-0.
2. Prove web-0 is recreated.
3. Prove its persistent data survives.
4. Show all PVCs.
5. Identify the PV bound to web-0.
6. Scale through Git.
7. Show Argo CD synchronizing the change.
8. Introduce replica-count drift manually.
9. Show Argo CD self-healing.
10. Explain Pod → PVC → PV → actual storage.
53. Required Submission
Submit:
GitHub repository link
and screenshots/output showing:
kubectl get sts -n stateful-app
kubectl get pods -n stateful-app
kubectl get pvc -n stateful-app
kubectl get pv
kubectl get sc
kubectl get svc -n stateful-app
kubectl get pdb -n stateful-app
kubectl get applications -n argocd
Also submit:
kubectl exec web-0 \
-n stateful-app \
-- cat /usr/share/nginx/html/data.txt
after deleting and recreating web-0.
Final Knowledge Map
Every student should be able to reproduce this from memory:
GIT
|
v
ARGO CD
|
v
KUBERNETES
|
v
STATEFULSET
|
+----------+----------+
| | |
web-0 web-1 web-2
| | |
v v v
PVC-0 PVC-1 PVC-2
| | |
v v v
PV-0 PV-1 PV-2
| | |
+----------+----------+
|
v
ACTUAL STORAGE
Memorize:
StatefulSet = stable workload identity
PVC = request for storage
PV = Kubernetes persistent-storage resource
StorageClass = how/class through which storage is provisioned
CSI Driver = Kubernetes-to-storage-system integration
EBS/EFS/etc. = actual storage backend
Argo CD = GitOps reconciliation
Git = desired state
Production principle:
Pods are replaceable.
Persistent data must not depend on
the lifetime of a particular container.
Git defines desired Kubernetes state.
Argo CD continuously reconciles
the cluster toward that state.
Top comments (0)