How to Deploy a Database in Kubernetes with StatefulSets

Databases need stable, predictable identities and durable storage — requirements that regular Deployments don't fully address. StatefulSets are Kubernetes' purpose-built solution for these stateful workloads.

Why Not Use a Regular Deployment for a Database

Deployments treat all Pod replicas as interchangeable, with random names and no guaranteed storage-to-Pod mapping. Databases need each replica to keep the same identity and the same attached storage across restarts — exactly what StatefulSets provide.

Key StatefulSet Guarantees

  • Stable, predictable Pod names (e.g. postgres-0, postgres-1)
  • Each Pod gets its own dedicated PersistentVolumeClaim that persists across restarts
  • Ordered, sequential deployment and scaling (Pod 0 starts before Pod 1, and so on)

Step 1 — Create a Headless Service

apiVersion: v1
kind: Service
metadata:
  name: postgres
spec:
  clusterIP: None
  selector:
    app: postgres
  ports:
  - port: 5432

clusterIP: None makes this a "headless" service, giving each Pod its own stable DNS entry rather than a single load-balanced IP.

Step 2 — Create the StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:16
        env:
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: postgres-secret
              key: password
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: postgres-storage
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: postgres-storage
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi

volumeClaimTemplates automatically creates a dedicated PersistentVolumeClaim for each replica — this is the key feature distinguishing StatefulSets from Deployments.

Step 3 — Create the Password Secret First

kubectl create secret generic postgres-secret --from-literal=password=CHANGE_ME_STRONG_PASSWORD

Step 4 — Apply the StatefulSet

kubectl apply -f postgres-statefulset.yaml

Step 5 — Verify It's Running

kubectl get statefulsets
kubectl get pods
kubectl get pvc

Connecting to the Database from Another Pod

postgres-0.postgres.default.svc.cluster.local:5432

Each replica gets a predictable DNS name in the form POD_NAME.SERVICE_NAME.NAMESPACE.svc.cluster.local.

Should You Run Your Production Database in Kubernetes?

Running a single-instance database in Kubernetes for convenience (co-located with your app) is reasonable for smaller projects. For genuinely critical production data with replication/HA requirements, consider whether a dedicated, purpose-built database VPS (see Databases category) or a managed database service might offer more operational simplicity and maturity than self-managing complex database clustering within Kubernetes.

Common Errors

StatefulSet Pod stuck in "Pending" — usually a PVC binding issue; check kubectl describe pvc for the specific reason (often insufficient storage capacity or no matching StorageClass).

Data appears lost after Pod restart — verify you didn't delete the PVC along with the Pod; PVCs from StatefulSets aren't automatically deleted when Pods are removed, by design.

Continue Reading

Browse more articles in Kubernetes & Container Orchestration.

  • kubernetes statefulset, kubernetes database, postgresql kubernetes, stateful workloads
  • 0 Users Found This Useful
Was this answer helpful?

Related Articles

What Is Kubernetes and When Do You Need It on a VPS?

Kubernetes is a container orchestration platform — it automates deploying, scaling, and...

How to Install a Single-Node Kubernetes Cluster with k3s

k3s is a lightweight, certified Kubernetes distribution designed to run efficiently on modest...

How to Install kubeadm and Set Up a Multi-Node Kubernetes Cluster

kubeadm is the official tool for bootstrapping a standard, full-featured Kubernetes cluster. This...

Kubernetes Pods, Deployments & Services Explained

Understanding these three core Kubernetes objects — Pods, Deployments, and Services —...

How to Expose Applications with a Kubernetes Ingress Controller (Nginx Ingress)

An Ingress lets you route external HTTP/HTTPS traffic to multiple services within your cluster...