PostgreSQL StatefulSet with Persistent Storage

Deploy PostgreSQL as a Kubernetes StatefulSet with persistent volume claims, exec-based readiness probes, and environment variables for database initialization.

Databases

Detailed Explanation

PostgreSQL on Kubernetes

Databases require stable network identities and persistent storage — exactly what StatefulSets provide. Unlike Deployments, StatefulSets give each pod a stable hostname and ensure volumes persist across pod restarts and rescheduling.

Key Configuration

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
  labels:
    app: "postgres"
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: postgres
          image: postgres:16-alpine
          ports:
            - name: postgres
              containerPort: 5432
          env:
            - name: POSTGRES_DB
              value: "mydb"
            - name: POSTGRES_USER
              value: "admin"
            - name: POSTGRES_PASSWORD
              value: "changeme"
          resources:
            requests:
              cpu: "250m"
              memory: "256Mi"
            limits:
              cpu: "1000m"
              memory: "1Gi"
          volumeMounts:
            - name: pgdata
              mountPath: /var/lib/postgresql/data
          livenessProbe:
            tcpSocket:
              port: 5432
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            exec:
              command:
                - "pg_isready"
                - "-U"
                - "admin"
            initialDelaySeconds: 5
            periodSeconds: 10
      volumes:
        - name: pgdata
          persistentVolumeClaim:
            claimName: pgdata-pvc

Why StatefulSet?

  • Stable network identity: Pod is always postgres-0, enabling predictable DNS (postgres-0.postgres.default.svc.cluster.local)
  • Persistent volumes: PVCs survive pod restarts and rescheduling
  • Ordered deployment: Pods are created and terminated in order (critical for primary/replica setups)

Readiness Probe

The exec-based readiness probe runs pg_isready inside the container. This is more accurate than a TCP check because it verifies that PostgreSQL is actually accepting connections, not just that the port is open. The -U admin flag checks if the specific user can connect.

Production Considerations

In production, you should:

  • Use Kubernetes Secrets instead of plain-text environment variables for passwords
  • Set up WAL archiving for point-in-time recovery
  • Consider an operator like CloudNativePG for automated failover
  • Use a larger PVC with a storage class that supports snapshots

Use Case

Deploying a PostgreSQL database for development or staging environments in Kubernetes, with persistent data that survives pod restarts. For production, consider using a database operator.

Try It — K8s Pod Spec Builder

Open full tool