In this tutorial, we’ll deploy PostgreSQL on AKS using:
- StatefulSet
- Azure Managed Disk (CSI)
- ReadWriteOnce (RWO)
- Premium SSD storage
- Persistent volume validation
On Azure Kubernetes Service
🧠 Why Run PostgreSQL on AKS?
Common use cases:
- SaaS apps with per-tenant DB
- Internal microservice database
- Dev/Test ephemeral environments
- Platform engineering demos
Key benefits:
✅ Data survives pod restarts
✅ Azure-managed disk durability
✅ Zone-aware scheduling
✅ Snapshot + backup integration
🏗 Architecture Overview
PostgreSQL runs as:
- StatefulSet
- Backed by Azure Managed Disk
- Using CSI driver
- Access mode:
ReadWriteOnce - Storage SKU:
Premium_LRS
Kubernetes dynamically provisions the disk.
Step 1️⃣ — Verify StorageClass
AKS automatically creates a default CSI storage class.
Check it:
kubectl get storageclass
Then inspect:
kubectl describe storageclass default
Look for:
Provisioner: disk.csi.azure.com
skuName: Premium_LRS
If you see Premium_LRS, you're using Premium SSD.
Step 2️⃣ — Create Namespace
kubectl create namespace postgres-demo
Step 3️⃣ — Create Secret
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
namespace: postgres-demo
type: Opaque
stringData:
POSTGRES_PASSWORD: supersecurepassword
Apply:
kubectl apply -f secret.yaml
Step 4️⃣ — Create Headless Service
StatefulSets require a headless service.
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: postgres-demo
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
Apply:
kubectl apply -f service.yaml
Step 5️⃣ — Deploy PostgreSQL StatefulSet
⚠ Important: Azure disks contain a lost+found directory at root.
PostgreSQL refuses to initialize if the directory is not empty.
We fix this by using a subdirectory via PGDATA.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: postgres-demo
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: default
resources:
requests:
storage: 10Gi
Apply:
kubectl apply -f statefulset.yaml
Step 6️⃣ — Verify Deployment
Wait for pod:
kubectl rollout status statefulset/postgres -n postgres-demo
Check PVC:
kubectl get pvc -n postgres-demo
Check pod:
kubectl get pods -n postgres-demo
You should see:
postgres-0 Running
Step 7️⃣ — Confirm Azure Disk Creation
In Azure Portal:
- Open resource group starting with:
MC_<your-rg>_<cluster>_<region>
- Find the Managed Disk
- Verify:
- SKU = Premium SSD
- Size = 10Gi
- Attached to AKS node
AKS automatically:
- Created disk
- Attached it
- Mounted it
- Bound PVC to Pod
Step 8️⃣ — Test Persistence
Enter PostgreSQL:
kubectl exec -it postgres-0 -n postgres-demo -- psql -U postgres
Create database:
CREATE DATABASE demo;
Now delete pod:
kubectl delete pod postgres-0 -n postgres-demo
Wait for restart:
kubectl rollout status statefulset/postgres -n postgres-demo
Verify:
kubectl exec -it postgres-0 -n postgres-demo -- psql -U postgres -l
You should still see:
demo
✅ Data persisted
✅ Disk reattached automatically
✅ No data loss
🔍 What This Demonstrates
| Feature | Why It Matters |
|---|---|
| StatefulSet | Stable volume binding |
| RWO | Single-writer DB safety |
| Azure CSI | Dynamic disk provisioning |
| Premium SSD | Low latency production storage |
| PGDATA fix | Proper Azure disk compatibility |
🏆 Production Improvements
For real workloads, add:
- Resource limits
- Liveness/readiness probes
- PodDisruptionBudget
- Anti-affinity rules
- Replica for HA
- Backup strategy (Velero or Azure Backup)
- Monitoring (Azure Monitor / Prometheus)
🎯 Final Architecture
PostgreSQL (StatefulSet)
↓
PVC (RWO)
↓
Azure Managed Disk (Premium SSD)
↓
Zone-aware AKS node
🚀 When to Use This Pattern
Use PostgreSQL on AKS if:
- You need full control
- You want per-tenant DB isolation
- You want environment parity (dev → prod)
- You’re building platform-level tooling
Use managed DB service instead if:
- You want automatic patching
- You want built-in HA
- You don’t want operational overhead
🔚 Conclusion
You’ve now:
✔ Deployed PostgreSQL on AKS
✔ Used Azure Premium SSD
✔ Configured StatefulSet properly
✔ Solved lost+found issue
✔ Verified data persistence
This is the foundation of running stateful workloads on AKS safely and correctly.


Top comments (0)