Sign inSign up

cagriekin/repmgr

By cagriekin

•Updated about 1 month ago

High-availability PostgreSQL 18 with repmgr 5.5.0 for Kubernetes StatefulSet auto-failover

Image
Databases & storage
0

10.0K

cagriekin/repmgr repository overview

⁠repmgr 5.5.0

High-availability PostgreSQL image with automatic failover for Kubernetes StatefulSet deployments. Built on Debian Trixie with repmgr 5.5.0 for streaming replication and automated failover management.

⁠Quick Reference

  • Source: GitHub⁠
  • Base image: debian:trixie-slim
  • PostgreSQL: 18
  • repmgr: 5.5.0
  • Kubernetes: 1.19+
  • Exposed port: 5432

⁠Multi-Mode Architecture

This image serves four distinct roles within a single Kubernetes StatefulSet pod, selected via the entrypoint argument:

entrypoint.sh <mode>
ModeContainer TypePurpose
postgresMain containerPostgreSQL server with initdb and replication setup
initInit containerGenerate repmgr.conf, clone standby data from primary
repmgrdSidecarRegister node and run repmgr failover daemon
service-updaterSidecarPatch Kubernetes Service selector on primary failover

⁠Environment Variables

⁠Required (all modes)
VariableDescription
REPMGR_PASSWORDPassword for the repmgr replication user
⁠postgres mode
VariableRequiredDefaultDescription
POSTGRES_USERYes-Application database user
POSTGRES_PASSWORDYes-Application database password
POSTGRES_DBYes-Application database name
PGDATANo/var/lib/postgresql/data/pgdataData directory path
REPMGR_USERNorepmgrRepmgr database user
REPMGR_DBNorepmgrRepmgr metadata database
⁠init mode
VariableRequiredDefaultDescription
HEADLESS_SERVICEYes-Headless service FQDN for node discovery
REPMGR_USERNorepmgrRepmgr database user
REPMGR_DBNorepmgrRepmgr metadata database
PGDATANo/var/lib/postgresql/data/pgdataData directory path
⁠service-updater mode
VariableRequiredDefaultDescription
NAMESPACEYes-Kubernetes namespace
MASTER_SERVICEYes-Service name to patch on failover
HEADLESS_SERVICEYes-Headless service FQDN for node discovery
REPMGR_USERNorepmgrRepmgr database user
REPMGR_DBNorepmgrRepmgr metadata database
MONITORING_INTERVALNo30Polling interval in seconds
⁠repmgrd mode

Reads /etc/repmgr/repmgr.conf generated by the init container. No additional environment variables required beyond PGDATA.

⁠Volumes

PathTypePurpose
/var/lib/postgresql/dataPVCPostgreSQL data directory
/etc/repmgremptyDirrepmgr.conf shared between init and sidecar containers

⁠How It Works

⁠Cluster Bootstrap
  1. Init container generates repmgr.conf per pod. Ordinal 0 initializes as primary; ordinal N clones from the primary via pg_basebackup.
  2. Main container starts PostgreSQL. On first boot (ordinal 0), runs initdb, configures WAL replication (wal_level=replica, max_wal_senders=10, wal_keep_size=1GB), and creates application and repmgr databases.
  3. repmgrd sidecar registers the node as primary or standby based on pg_is_in_recovery(), then starts the repmgrd daemon.
  4. service-updater sidecar polls the cluster and patches the Kubernetes Service statefulset.kubernetes.io/pod-name selector to point to the current primary.
⁠Automatic Failover

When the primary pod becomes unavailable:

  1. repmgrd detects failure and promotes a standby to primary
  2. Remaining standbys follow the new primary
  3. service-updater patches the Kubernetes Service selector to the new primary pod
⁠Failed Primary Rejoin

When a failed primary pod restarts:

  1. Init container detects existing data and probes partner nodes
  2. Finds another active primary, wipes local data, and re-clones as standby
  3. repmgrd registers the node as standby
⁠Scaling
  • Scale up: new pods clone from the current primary
  • Scale down: removed pods leave inactive entries in repmgr.nodes (harmless)
  • Stale PVC recovery: init container detects timeline mismatch and re-clones

⁠StatefulSet Pod Spec Example

initContainers:
  - name: init-repmgr
    image: cagriekin/repmgr:trixie-5.5.0
    command: ["/usr/local/bin/entrypoint.sh", "init"]
    env:
      - name: HEADLESS_SERVICE
        value: "pg-headless.default.svc.cluster.local"
      - name: REPMGR_PASSWORD
        valueFrom:
          secretKeyRef:
            name: pg-secrets
            key: repmgr-password
    volumeMounts:
      - name: data
        mountPath: /var/lib/postgresql/data
      - name: repmgr-config
        mountPath: /etc/repmgr

containers:
  - name: postgres
    image: cagriekin/repmgr:trixie-5.5.0
    command: ["/usr/local/bin/entrypoint.sh", "postgres"]
    ports:
      - containerPort: 5432
    env:
      - name: POSTGRES_USER
        value: "app"
      - name: POSTGRES_PASSWORD
        valueFrom:
          secretKeyRef:
            name: pg-secrets
            key: postgres-password
      - name: POSTGRES_DB
        value: "appdb"
      - name: REPMGR_PASSWORD
        valueFrom:
          secretKeyRef:
            name: pg-secrets
            key: repmgr-password
    volumeMounts:
      - name: data
        mountPath: /var/lib/postgresql/data
      - name: repmgr-config
        mountPath: /etc/repmgr

  - name: repmgrd
    image: cagriekin/repmgr:trixie-5.5.0
    command: ["/usr/local/bin/entrypoint.sh", "repmgrd"]
    volumeMounts:
      - name: data
        mountPath: /var/lib/postgresql/data
      - name: repmgr-config
        mountPath: /etc/repmgr

  - name: service-updater
    image: cagriekin/repmgr:trixie-5.5.0
    command: ["/usr/local/bin/entrypoint.sh", "service-updater"]
    env:
      - name: NAMESPACE
        valueFrom:
          fieldRef:
            fieldPath: metadata.namespace
      - name: MASTER_SERVICE
        value: "pg-primary"
      - name: HEADLESS_SERVICE
        value: "pg-headless.default.svc.cluster.local"
      - name: REPMGR_PASSWORD
        valueFrom:
          secretKeyRef:
            name: pg-secrets
            key: repmgr-password

Tag summary

Content type

Image

Digest

sha256:c1bba0363…

Size

248 Bytes

Last updated

about 1 month ago

docker pull cagriekin/repmgr:sha256-b67d66cf89a3487ef8bd29709e166a92075a46650a907a337af04ef3a1d2f49d.sig