Skip to content
docktionary

Snippets / Kubernetes

StatefulSet for Postgres

A single-node Postgres StatefulSet with a persistent volume claim template.

statefulsetpostgresstorage
statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db
spec:
  # Must match the headless Service below by name -- this is what gives
  # each pod ("db-0", "db-1", ...) its own stable DNS record.
  serviceName: db
  replicas: 1
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
        - name: postgres
          image: postgres:16-alpine
          env:
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: password
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  # Unlike a Deployment's volumes, each replica of a StatefulSet gets its
  # own PersistentVolumeClaim created from this template ("data-db-0",
  # "data-db-1", ...) -- storage isn't shared between replicas.
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 20Gi
---
apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  # clusterIP: None makes this a headless Service -- instead of one
  # load-balanced IP, DNS returns each pod's individual address
  # (db-0.db, db-1.db, ...), which a StatefulSet's stable identities need.
  clusterIP: None
  selector:
    app: db
  ports:
    - port: 5432