Workstation Logo
Producten
AI LabsOpenAI AgentsClaude AgentsGrok BotWorkstation CRM (WSL CRM)MarketingAlle Producten
AI-Oplossingen
AI-WerkstationsAI SME PackagesPrivé AIGPU-ClustersEdge AIEnterprise AI LabAI per Industrie
Diensten
PlatformmoderniseringDigitale engineeringDatafundamenten & AIAutonome operatiesAI-adviesDevOps-automatiseringCybersecuritySoftwareontwikkelingAgentontwikkelingMLOps-opzet
Over Ons
PartnersKlantverhalen
Artikelen
Documentatie
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
Blog
ContactLogin
Workstation

AI-werkstations, AI multi-agent software, GPU-infrastructuur en intelligente agentoplossingen voor moderne bedrijven.

Contact

AI-oplossingen

AI-WerkstationsAI SME PackagesPrivé AIGPU-ClustersEdge AIEnterprise AI LabAI per Industrie

Producten

Alle ProductenWSL CRM & ERPMarketingOpenAI AgentsWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

Bedrijf

Over OnsWaarom WorkstationPartnersKlantverhalenPrijzenContact

Bronnen

ArtikelenDocumentatieBlogZoekenSitemap
UK-kantoor
77-79 Marlowes, Hemel Hempstead HP1 1LFRoute: neem afrit 20 van de M25, Outer LondonBedrijfsnummer: 11641870Ma - Vr: 9:00 - 18:00 GMT
+44 7515 356 146
België-kantoor
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683Ma - Vr: 9:00 - 18:00 CET
+32 492 45 67 46
India-kantoor
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. Alle rechten voorbehouden.

PrivacyCookiesServicevoorwaardenWebsite-sitemap

Loading blog...

Home / Blog
DatabaseKubernetesDevOpsBackend

PostgreSQL Native hoge beschikbaarheid: Patroni, streamingreplicatie en productiefailoverstrategieën

PostgreSQL Native HA met Patroni, streamingreplicatie en HAProxy

Balinder Walia12 april 202630 min read

Het uitvoeren van een enkele PostgreSQL-instantie is eenvoudig totdat de eerste ongeplande uitval u eraan herinnert dat een database slechts zo waardevol is als de beschikbaarheid ervan. Schijfstoringen, kernelpanics, netwerkpartities en mislukte upgrades zijn geen theoretische risico's; het zijn operationele zekerheden die lang genoeg duren. PostgreSQL wordt niet geleverd met ingebouwde automatische failover, maar biedt wel alle replicatieprimitieven die nodig zijn om een ​​cluster met hoge beschikbaarheid te bouwen. Patroni, een open-source HA-framework dat wordt onderhouden door Zalando, orkestreert deze primitieven in een failover-systeem van productiekwaliteit dat op grote schaal is getest in duizenden PostgreSQL-clusters over de hele wereld.

Dit artikel is een diepgaande technische gids. We behandelen PostgreSQL-streamingreplicatie (synchroon en asynchroon), Patroni-architectuur en -configuratie, etcd als een gedistribueerde configuratieopslag, HAProxy voor verbindingsrouting met lees-schrijfsplitsing, PgBouncer voor verbindingspooling, WAL-archivering en point-in-time herstel, logische replicatie voor selectieve gegevenssynchronisatie, pg_basebackup voor initiële standby-provisioning, repmgr als alternatief voor Patroni, cloudspecifieke implementatiepatronen voor AWS, Azure en GCP, bare metal k3s-implementatie met Rancher en Longhorn, monitoring met pg_stat_replication en Prometheus/Grafana, omschakeling versus failover-procedures, split-brain-preventie, productie-afstemming en chaos-engineering voor failover-validatie.

PostgreSQL Basisprincipes van streamingreplicatie

Streamingreplicatie is de ruggengraat van de hoge beschikbaarheid van PostgreSQL. Het werkt door continu Write-Ahead Log (WAL)-records te verzenden van een primaire server naar een of meer standby-servers. De stand-by past deze WAL-records in realtime toe, waarbij een vrijwel identieke kopie van de primaire gegevens wordt bewaard. Dit mechanisme werd geïntroduceerd in PostgreSQL 9.0 en werd in elke volgende release verfijnd.

Er zijn twee modi voor streamingreplicatie:asynchroonensynchroon. In de asynchrone modus wacht de primaire niet op stand-by's om de ontvangst van WAL-records te bevestigen voordat een transactie wordt vastgelegd. Dit levert maximale schrijfprestaties op, maar introduceert een periode van potentieel gegevensverlies: als de primaire uitvalt voordat een stand-by de meest recente WAL heeft ontvangen, gaan die transacties verloren. In de synchrone modus wacht de primaire modus op ten minste één standby-modus om te bevestigen dat WAL-records naar duurzame opslag zijn geschreven voordat een transactie als vastgelegd wordt gerapporteerd. Dit elimineert gegevensverlies ten koste van een grotere commit-latentie, omdat elke schrijfbewerking naar stand-by moet gaan.

De keuze tussen synchrone en asynchrone replicatie is niet binair. PostgreSQL ondersteuntsynchronous_commitop sessieniveau, zodat latentiegevoelige workloads zich kunnen aanmelden voor asynchrone commits, terwijl kritische financiële transacties gebruik maken van synchrone commits binnen hetzelfde cluster.

De primaire configuratie configureren voor replicatie

De primaire server moet worden geconfigureerd om WAL-records te genereren op een niveau dat voldoende is voor replicatie en om stand-byverbindingen mogelijk te maken. De volgendepostgresql.conf-instellingen zijn essentieel.

# postgresql.conf on the primary
wal_level = replica                    # minimum for streaming replication
max_wal_senders = 10                   # max concurrent replication connections
max_replication_slots = 10             # prevent WAL removal before standby consumption
wal_keep_size = 2GB                    # retain WAL as fallback if slots are unused
hot_standby = on                       # allow read queries on standbys
synchronous_commit = on                # 'on' for sync, 'off' for pure async
synchronous_standby_names = 'ANY 1 (standby1, standby2)'  # sync replication targets
archive_mode = on                      # enable WAL archiving for PITR
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'
listening_addresses = '*'
port = 5432

Authenticatie voor replicatieverbindingen wordt afgehandeld inpg_hba.conf. Replicatieverbindingen gebruiken een speciaal verbindingstype.

# pg_hba.conf — replication entries
# TYPE   DATABASE        USER            ADDRESS              METHOD
host     replication     replicator      10.0.1.0/24          scram-sha-256
host     replication     replicator      10.0.2.0/24          scram-sha-256
host     all             all             10.0.0.0/16          scram-sha-256

Maak de replicatiegebruiker op het primaire bestand.

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strong_replication_password';

Een standby-voorziening inrichten met pg_basebackup

Het hulpprogrammapg_basebackupmaakt een fysieke kopie van de primaire gegevensmap, die het startpunt wordt voor een nieuwe standby-map. Het verwerkt de basisback-up en WAL-streaming op atomaire wijze, zodat de resulterende kopie consistent is.

# On the standby server
pg_basebackup -h primary-host -U replicator -D /var/lib/postgresql/16/main \
  -Fp -Xs -P -R

# -Fp: plain format
# -Xs: stream WAL during backup
# -P:  show progress
# -R:  create standby.signal and configure primary_conninfo in postgresql.auto.conf

De-R-vlag is van cruciaal belang: deze schrijftprimary_conninfonaarpostgresql.auto.confen creëertstandby.signal, die PostgreSQL vertelt om in de standby-modus te starten. In PostgreSQL 12 en hoger wordtrecovery.confvervangen door deze twee mechanismen.

# postgresql.auto.conf (generated by pg_basebackup -R)
primary_conninfo = 'host=primary-host port=5432 user=replicator password=strong_replication_password application_name=standby1'
primary_slot_name = 'standby1_slot'

Maak het replicatieslot op de primaire schijf voordat u de stand-by start, om te voorkomen dat WAL wordt opgeschoond voordat de stand-by deze kan gebruiken.

SELECT pg_create_physical_replication_slot('standby1_slot');
SELECT pg_create_physical_replication_slot('standby2_slot');

Patroni: Geautomatiseerde HA-orkestratie

Streaming-replicatie geeft u gegevensredundantie, maar biedt geen automatische failover. Als de primaire crasht, moet iemand (een menselijke operator of een automatiseringssysteem) een standby-modus promoveren tot primair, de resterende standby-systemen opnieuw configureren om de nieuwe primaire te volgen en de verbindingsroutering bijwerken. Patroni automatiseert dit allemaal.

Patroni is een Python-daemon die naast elke PostgreSQL-instantie draait. Het maakt gebruik van een Distributed Configuration Store (DCS) – meestal etcd, maar ook ZooKeeper of Consul – om de verkiezing van leiders en de clusterstatus te coördineren. Elk Patroni-knooppunt schrijft voortdurend zijn gezondheidsstatus naar het DCS. Wanneer de leider (primair) er niet in slaagt zijn DCS-sleutel binnen de geconfigureerde TTL te vernieuwen, initieert Patroni een leiderverkiezing onder de gezonde standbys. De winnaar wordt gepromoveerd tot primair, en de resterende knooppunten configureren zichzelf opnieuw als stand-by van het nieuwe primaire knooppunt – allemaal automatisch, doorgaans binnen 10-30 seconden.

Patroni HA-architectuur — PostgreSQL-cluster met 3 knooppuntenApplicatieclientsHAProxy-loadbalancerpoort 5000 (RW) · poort 5001 (RO)Primair (leider)PostgreSQL 16 + Patroniknooppunt1 — 10.0.1.10:5432Stand-by 1 (Synchroniseren)PostgreSQL 16 + Patroniknooppunt2 — 10.0.1.11:5432Stand-by 2 (asynchroon)PostgreSQL 16 + Patroniknooppunt3 — 10.0.1.12:5432synchroniseert streamingasynchroon streamenenz. Cluster (DCS)3 knooppunten — leiderverkiezing & configuratieopslagPrimaireStand-byenz. DCSHAProxy

Patroni YAML Configuratie

Patroni wordt geconfigureerd via een YAML-bestand dat de DCS-verbinding, PostgreSQL-parameters, replicatiegedrag en bootstrap-instellingen definieert. Het volgende is een configuratie op productieniveau voor het primaire knooppunt.

# /etc/patroni/patroni.yml — Node 1 (Primary)
scope: pg-ha-cluster
namespace: /postgresql-ha/
name: node1

restapi:
  listen: 0.0.0.0:8008
  connect_address: 10.0.1.10:8008

etcd3:
  hosts:
    - 10.0.2.10:2379
    - 10.0.2.11:2379
    - 10.0.2.12:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576  # 1MB — only promote standbys within this lag
    synchronous_mode: true
    synchronous_mode_strict: false
    postgresql:
      use_pg_rewind: true
      use_slots: true
      parameters:
        wal_level: replica
        hot_standby: 'on'
        max_connections: 200
        max_wal_senders: 10
        max_replication_slots: 10
        wal_keep_size: 2GB
        synchronous_commit: 'on'
        archive_mode: 'on'
        archive_command: 'test ! -f /archive/%f && cp %p /archive/%f'
        archive_timeout: 60
        wal_log_hints: 'on'
        shared_preload_libraries: 'pg_stat_statements'
        track_commit_timestamp: 'on'
      pg_hba:
        - host replication replicator 10.0.0.0/16 scram-sha-256
        - host all all 10.0.0.0/16 scram-sha-256
        - host all all 0.0.0.0/0 scram-sha-256

  initdb:
    - encoding: UTF8
    - data-checksums

  users:
    admin:
      password: 'admin_secure_password'
      options:
        - createrole
        - createdb
    replicator:
      password: 'repl_secure_password'
      options:
        - replication

postgresql:
  listen: 0.0.0.0:5432
  connect_address: 10.0.1.10:5432
  data_dir: /var/lib/postgresql/16/main
  bin_dir: /usr/lib/postgresql/16/bin
  config_dir: /var/lib/postgresql/16/main
  pgpass: /tmp/pgpass0
  authentication:
    superuser:
      username: postgres
      password: 'postgres_secure_password'
    replication:
      username: replicator
      password: 'repl_secure_password'
    rewind:
      username: postgres
      password: 'postgres_secure_password'
  parameters:
    unix_socket_directories: '/var/run/postgresql'
  create_replica_methods:
    - basebackup
  basebackup:
    max-rate: 100M
    checkpoint: fast

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false
  nosync: false

De standby-knooppunten gebruiken een identieke configuratie met hun eigenname-,connect_address- enlisten-waarden. Patroni doet de rest: het detecteert of een knooppunt de leider of een replica moet zijn op basis van de DCS-status en configureert PostgreSQL dienovereenkomstig.

enz. als gedistribueerd configuratiearchief

etcd is het zenuwstelsel van een Patroni-cluster. Het slaat de huidige leidersidentiteit, de clustertopologie, de gewenste configuratie en de gezondheidsstatus van elk knooppunt op. Een etcd-cluster met drie knooppunten is het minimum voor productie, waarbij één knooppuntstoring wordt getolereerd terwijl het quorum behouden blijft.

# Install and configure etcd on three dedicated nodes
# /etc/etcd/etcd.conf.yml — Node etcd1 (10.0.2.10)
name: etcd1
data-dir: /var/lib/etcd
listen-client-urls: http://0.0.0.0:2379
listen-peer-urls: http://0.0.0.0:2380
advertise-client-urls: http://10.0.2.10:2379
initial-advertise-peer-urls: http://10.0.2.10:2380
initial-cluster: etcd1=http://10.0.2.10:2380,etcd2=http://10.0.2.11:2380,etcd3=http://10.0.2.12:2380
initial-cluster-state: new
initial-cluster-token: patroni-etcd-cluster

# Start etcd
systemctl enable --now etcd

# Verify cluster health
etcdctl endpoint health --cluster \
  --endpoints=http://10.0.2.10:2379,http://10.0.2.11:2379,http://10.0.2.12:2379

Voor productie-implementaties schakelt u TLS in tussen etcd-peers en tussen etcd- en Patroni-clients. Niet-versleuteld etcd-verkeer stelt clusterreferenties en configuratie bloot aan aanvallers op netwerkniveau.

HAProxy voor verbindingsroutering

Patroni stelt op elk knooppunt een REST API beschikbaar (standaard poort 8008) die rapporteert of het knooppunt de huidige leider of een replica is. HAProxy gebruikt deze eindpunten voor de gezondheidscontrole om verkeer te routeren: schrijfbewerkingen gaan naar de leider, leesbewerkingen gaan naar gezonde replica's. Hierdoor kunt u automatisch lezen en schrijven splitsen zonder wijzigingen op applicatieniveau.

# /etc/haproxy/haproxy.cfg
global
    maxconn 2000
    log /dev/log local0
    stats socket /var/run/haproxy.sock mode 660 level admin

defaults
    mode tcp
    log global
    retries 3
    timeout client 30m
    timeout connect 4s
    timeout server 30m
    timeout check 5s
    maxconn 1000

listen pg_write
    bind *:5000
    option httpchk GET /primary
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server node1 10.0.1.10:5432 check port 8008
    server node2 10.0.1.11:5432 check port 8008
    server node3 10.0.1.12:5432 check port 8008

listen pg_read
    bind *:5001
    balance roundrobin
    option httpchk GET /replica
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server node1 10.0.1.10:5432 check port 8008
    server node2 10.0.1.11:5432 check port 8008
    server node3 10.0.1.12:5432 check port 8008

listen stats
    bind *:7000
    mode http
    stats enable
    stats uri /
    stats refresh 10s

Het/primary-eindpunt retourneert HTTP 200 alleen op de huidige Patroni-leider. Het/replica-eindpunt retourneert 200 bij gezonde standbys. Wanneer er een failover plaatsvindt, begint de nieuwe primaire versie 200 op/primaryte retourneren, en HAProxy leidt het schrijfverkeer automatisch om, meestal binnen één statuscontrole-interval (3 seconden). Deon-marked-down shutdown-sessions-richtlijn beëindigt onmiddellijk bestaande verbindingen met een mislukte primaire verbinding, waardoor clients worden gedwongen opnieuw verbinding te maken met de nieuwe leider.

PgBouncer voor verbindingspooling

PostgreSQL creëert een nieuw backend-proces voor elke clientverbinding. Op grote schaal – honderden of duizenden microservices die elk verbindingspools onderhouden – wordt de overhead van het maken van processen en het geheugengebruik aanzienlijk. PgBouncer bevindt zich tussen de applicatie en PostgreSQL en onderhoudt een pool van serververbindingen en multiplext clientverbindingen daarop.

# /etc/pgbouncer/pgbouncer.ini
[databases]
* = host=127.0.0.1 port=5432 dbname=appdb

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt

pool_mode = transaction
max_client_conn = 1000
default_pool_size = 50
min_pool_size = 10
reserve_pool_size = 10
reserve_pool_timeout = 3
server_lifetime = 3600
server_idle_timeout = 600
server_connect_timeout = 5
server_login_retry = 3

log_connections = 1
log_disconnections = 1
stats_period = 60

Bij gebruik met Patroni bevindt PgBouncer zich doorgaans op elk PostgreSQL-knooppunt of op de HAProxy-knooppunten. Detransaction-poolmodus is de beste keuze voor de meeste werkbelastingen: deze wijst een serververbinding toe voor de duur van een transactie en stuurt deze tussen transacties terug naar de pool. Dit is veel efficiënter dan desession-modus, die een verbinding voor de hele clientsessie vasthoudt.

WAL-archivering en point-in-time herstel

Streaming-replicatie beschermt tegen serverstoringen, maar biedt geen bescherming tegen logische fouten: een onbedoeldeDROP TABLEof een slechte applicatiemigratie wordt onmiddellijk naar alle stand-by-systemen gerepliceerd. Dankzij WAL-archivering in combinatie met point-in-time herstel (PITR) kunt u herstellen naar elk moment voordat de fout optrad.

WAL-archivering kopieert voltooide WAL-segmenten naar een duurzaam archief - meestal een S3-bucket, een NFS-mount of een speciale back-upserver. Tools zoalspgBackRestenWAL-Gverwerken archivering efficiënt met compressie, codering en parallelle overdracht.

# pgBackRest configuration — /etc/pgbackrest/pgbackrest.conf
[global]
repo1-type=s3
repo1-s3-bucket=pg-wal-archive
repo1-s3-endpoint=s3.eu-west-1.amazonaws.com
repo1-s3-region=eu-west-1
repo1-s3-key=AKIAIOSFODNN7EXAMPLE
repo1-s3-key-secret=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
repo1-path=/pgbackrest
repo1-retention-full=4
repo1-retention-diff=7
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=strong_encryption_passphrase
compress-type=zst
compress-level=3
process-max=4

[pg-ha-cluster]
pg1-path=/var/lib/postgresql/16/main
pg1-port=5432

# In postgresql.conf
archive_command = 'pgbackrest --stanza=pg-ha-cluster archive-push %p'
restore_command = 'pgbackrest --stanza=pg-ha-cluster archive-get %f "%p"'

Om een herstel op een bepaald tijdstip uit te voeren, geeft u een doeltijdstempel op.

# Restore to a specific point in time
pgbackrest --stanza=pg-ha-cluster --type=time \
  --target="2026-04-12 11:25:00" \
  --target-action=promote \
  restore

Logische replicatie voor selectieve gegevenssynchronisatie

Terwijl streaming-replicatie een exacte fysieke kopie van het gehele databasecluster creëert, werkt logische replicatie op tabelniveau, waarbij individuele tabellen of subsets van gegevens worden gerepliceerd tussen onafhankelijke PostgreSQL-instanties. Dit is handig voor grote versie-upgrades zonder downtime, leesreplica's tussen regio's die alleen specifieke tabellen nodig hebben, datawarehouse-invoer en gegevensdistributie tussen meerdere tenants.

# On the publisher (source database)
wal_level = logical  # must be 'logical' — higher than 'replica'

CREATE PUBLICATION app_pub FOR TABLE orders, customers, products;

# On the subscriber (target database)
CREATE SUBSCRIPTION app_sub
  CONNECTION 'host=publisher-host port=5432 dbname=appdb user=replicator password=pass'
  PUBLICATION app_pub;

Logische replicatie kan naast streaming-replicatie worden uitgevoerd. Een veelvoorkomend patroon is het gebruik van streaming-replicatie voor HA (snelle fysieke failover) en logische replicatie voor analytische replica's tussen regio's die slechts een subset van tabellen nodig hebben.

Streamingreplicatie in meerdere regio's

Voor noodherstel en wereldwijde leesprestaties kunnen PostgreSQL-clusters meerdere regio's bestrijken. Het standaardpatroon is synchrone replicatie binnen een regio (voor nul gegevensverlies bij lokale failover) en asynchrone replicatie tussen regio's (om latentieboetes tussen regio's bij elke schrijfbewerking te voorkomen). Elke regio heeft zijn eigen HAProxy voor lokale leesroutering.

PostgreSQL streamingreplicatie voor meerdere regio'sRegio 1 — AWS eu-west-1Primairepg-node1 (RW)Synchronisatie stand-bypg-node2 (RO)synchroniseertHAProxy (lokaal)Regio 2 — Azure west-EuropaAsynchrone stand-bypg-node3 (RO)Asynchrone stand-bypg-node4 (RO)synchroniseertHAProxy (lokaal)Regio 3 — GCP europa-west1Asynchrone stand-bypg-node5 (RO)Asynchrone stand-bypg-node6 (RO)synchroniseertHAProxy (lokaal)async WALasync WAL-verzendingGedeeld WAL-archief (S3 / Blob / GCS)pgBackRest of WAL-G — regiooverschrijdend PITRGlobal DNS (Route53 / Verkeersmanager / Cloud DNS)Legende:Synchronisatiereplicatie (binnen regio)Asynchrone replicatie (regiooverschrijdend)WAL-archivering naar objectopslagPrimaireStand-by

Failover- en omschakelingsprocedures

Het begrijpen van het verschil tussen failover en omschakeling is van cruciaal belang. Eenfailoveris een ongeplande promotie die wordt geactiveerd door het falen van de huidige primaire. Een-omschakelingis een geplande, sierlijke rolverandering, die doorgaans vóór onderhoud wordt uitgevoerd. Patroni ondersteunt beide.

Geplande omschakeling

# List cluster members
patronictlctl -c /etc/patroni/patroni.yml list

# Perform switchover to a specific node
patronictlctl -c /etc/patroni/patroni.yml switchover \
  --master node1 --candidate node2 --force

# Or use the Patroni REST API
curl -s http://10.0.1.10:8008/switchover -XPOST \
  -d '{"leader": "node1", "candidate": "node2"}'

Tijdens een omschakeling degradeert Patroni de huidige primaire naar standby, promoveert de beoogde kandidaat en configureert alle andere standbys opnieuw om de nieuwe primaire te volgen. Het proces duurt 5-15 seconden. HAProxy detecteert de wijziging via gezondheidscontroles en leidt het verkeer automatisch om.

Automatische failover-sequentie

Wanneer de primaire versie onverwacht uitvalt, volgt Patroni een precieze volgorde om de service te herstellen. Het volgende diagram illustreert de stappen.

Patroni automatische failover-sequentie1Primaire foutCrash, netwerkpartitie ofschijffout op knooppunt 12Patroni Detecteert via DCSLeader-sleutel TTL verloopt in etcd(standaard 30s TTL)3LeiderverkiezingStandbys racen omte verwervenleiderslot in etcd4Stand-by GesponsordeWinnaar voert pg_ctl uit omte promotenen wordt de nieuwe primaire5HAProxy werktbijGezondheidscontroles detecteren nieuwe primaire/primair retourneert 200 op nieuwe leider6-clients hebben opnieuw verbinding gemaakt metApplicaties maken opnieuw verbinding via HAProxynaar nieuwe primaire transparantTypische totale failovertijdDCS TTL-vervaldatum: ~15-30sverkiezing: ~2-5sHAProxy-detectie: ~3-10sSluitopnieuw aan≈ 20-45 seconden totaalBelangrijkste parameters die de failoversnelheid beïnvloeden:• ttl (standaard 30s) — Hoe lang duurt het voordat de leidersleutel verloopt in DCS• loop_wait (standaard 10s) — Hoe vaak Patroni de clusterstatuscontroleert• retry_timeout (standaard 10s) — Time-out voor DCS- en PostgreSQL-bewerkingen• maximum_lag_on_failover (1MB) — Promoot alleen standbys binnen deze replicatievertraging

Preventie van gespleten hersenen

Split-brain – waarbij twee knooppunten tegelijkertijd denken dat ze de primaire zijn – is de gevaarlijkste storingsmodus in elk HA-systeem. Patroni voorkomt gespleten hersenen via verschillende mechanismen:

  1. DCS-gebaseerd leiderslot:Slechts één knooppunt kan op elk moment de leidersleutel in etcd vasthouden. De sleutel heeft een TTL en de leider moet deze voortdurend vernieuwen. Als een netwerkpartitie de leider isoleert van etcd, verloopt de sleutel en degradeert de leider zichzelf.
  2. Watchdog:Patroni kan een Linux watchdog-apparaat configureren (/dev/watchdog). Als Patroni de toegang tot de DCS verliest en niet kan bevestigen dat deze leider moet blijven, zal de waakhond het knooppunt opnieuw opstarten of uitschakelen - een hard hekwerkmechanisme dat garandeert dat de oude primaire schrijfbewerkingen niet blijft accepteren.
  3. pg_rewind:Wanneer een voormalige primaire versie weer online komt, bevat deze mogelijk WAL-records die nooit zijn gerepliceerd.pg_rewindspoelt de tijdlijn terug naar het punt van divergentie, waardoor het knooppunt opnieuw kan deelnemen als stand-by zonder een volledige basisback-up. Patroni'suse_pg_rewind: true-instelling automatiseert dit.
# Enable watchdog in Patroni config
bootstrap:
  dcs:
    postgresql:
      use_pg_rewind: true
      parameters:
        wal_log_hints: 'on'  # required for pg_rewind

# Watchdog configuration
watchdog:
  mode: required        # 'off', 'automatic', or 'required'
  device: /dev/watchdog
  safety_margin: 5      # seconds before TTL expiry to trigger watchdog

repmgr als alternatief voor Patroni

repmgris een ander populair HA-hulpmiddel voor PostgreSQL. Het biedt stand-bybeheer, automatische failover en omschakelingsmogelijkheden. Er is echter een fundamenteel andere aanpak nodig dan Patroni. repmgr gebruikt een getuigenknooppunt en een daemon (repmgrd) voor foutdetectie in plaats van een gedistribueerde consensusopslag. Dit maakt het eenvoudiger te implementeren, maar gevoeliger voor split-bras in complexe netwerkpartitiescenario's.

# repmgr.conf on the primary
node_id=1
node_name='node1'
conninfo='host=10.0.1.10 user=repmgr dbname=repmgr connect_timeout=2'
data_directory='/var/lib/postgresql/16/main'
failover=automatic
promote_command='repmgr standby promote -f /etc/repmgr.conf --log-to-file'
follow_command='repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'
monitoring_history=yes
monitor_interval_secs=5
reconnect_attempts=6
reconnect_interval=10

Voor nieuwe implementaties is Patroni de aanbevolen keuze vanwege de sterkere garanties voor het voorkomen van gespleten hersenen en de actievere ontwikkelingsgemeenschap. repmgr blijft een redelijke optie voor eenvoudigere instellingen of organisaties die al in de tool hebben geïnvesteerd.

Cloud-implementatiepatronen

AWS Implementatie: EC2, EBS en Route53

Implementeer op AWS elk PostgreSQL + Patroni-knooppunt op een EC2-instantie met EBS gp3- of io2-volumes. Gebruik afzonderlijke instanties in meerdere Beschikbaarheidszones voor HA. etcd-knooppunten moeten ook AZ's omvatten.

# Terraform sketch for PostgreSQL HA on AWS
resource "aws_instance" "pg_node" {
  count                = 3
  ami                  = "ami-0abcdef1234567890"  # Ubuntu 22.04
  instance_type        = "r6g.2xlarge"             # 8 vCPU, 64GB RAM
  subnet_id            = aws_subnet.private[count.index].id
  vpc_security_group_ids = [aws_security_group.pg_sg.id]
  availability_zone    = element(["eu-west-1a", "eu-west-1b", "eu-west-1c"], count.index)

  root_block_device {
    volume_size = 50
    volume_type = "gp3"
  }

  tags = {
    Name = "pg-node-${count.index + 1}"
    Role = "patroni"
  }
}

resource "aws_ebs_volume" "pg_data" {
  count             = 3
  availability_zone = element(["eu-west-1a", "eu-west-1b", "eu-west-1c"], count.index)
  size              = 500
  type              = "gp3"
  iops              = 6000
  throughput        = 250
  encrypted         = true

  tags = {
    Name = "pg-data-${count.index + 1}"
  }
}

resource "aws_route53_health_check" "pg_primary" {
  count             = 3
  ip_address        = aws_instance.pg_node[count.index].private_ip
  port              = 8008
  type              = "HTTP"
  resource_path     = "/primary"
  failure_threshold = 3
  request_interval  = 10
}

Gebruik een Network Load Balancer (NLB) in plaats van HAProxy als u de voorkeur geeft aan een door AWS beheerde oplossing. De NLB kan doelgroepgezondheidscontroles tegen de Patroni REST API gebruiken om verkeer naar de huidige primaire te routeren.

Azure-implementatie: VM's, beheerde schijven en Azure LB

Gebruik op Azure Standard_E8s_v5 VM's (geoptimaliseerd geheugen) met Premium SSD Managed Disks voor datavolumes. Implementeer in beschikbaarheidszones. Azure Load Balancer biedt het equivalent van HAProxy met gezondheidstests tegen de Patroni REST API.

# Azure CLI — create PostgreSQL VM with Managed Disk
az vm create \
  --resource-group pg-ha-rg \
  --name pg-node-1 \
  --image Canonical:0001-com-ubuntu-server-jammy:22_04-lts:latest \
  --size Standard_E8s_v5 \
  --zone 1 \
  --vnet-name pg-vnet \
  --subnet pg-subnet \
  --nsg pg-nsg \
  --admin-username pgadmin \
  --ssh-key-value ~/.ssh/id_rsa.pub

az disk create \
  --resource-group pg-ha-rg \
  --name pg-data-1 \
  --size-gb 512 \
  --sku Premium_LRS \
  --zone 1

az vm disk attach \
  --resource-group pg-ha-rg \
  --vm-name pg-node-1 \
  --name pg-data-1

# Azure Load Balancer health probe for Patroni
az network lb probe create \
  --resource-group pg-ha-rg \
  --lb-name pg-lb \
  --name patroni-primary-probe \
  --protocol Http \
  --port 8008 \
  --path /primary \
  --interval 5 \
  --threshold 3

GCP-implementatie: Compute Engine en Cloud Load Balancing

Gebruik op GCP n2-highmem-8-instanties (8 vCPU, 64 GB RAM) met SSD Persistent Disks. Verdeel over zones binnen een regio. Gebruik een interne TCP/UDP-load balancer met Patroni-statuscontroles.

# GCP — create instance and persistent disk
gcloud compute instances create pg-node-1 \
  --zone=europe-west1-b \
  --machine-type=n2-highmem-8 \
  --image-family=ubuntu-2204-lts \
  --image-project=ubuntu-os-cloud \
  --boot-disk-size=50GB \
  --network=pg-network \
  --subnet=pg-subnet

gcloud compute disks create pg-data-1 \
  --zone=europe-west1-b \
  --size=500GB \
  --type=pd-ssd

gcloud compute instances attach-disk pg-node-1 \
  --disk=pg-data-1 \
  --zone=europe-west1-b

# Health check for Patroni primary endpoint
gcloud compute health-checks create http patroni-primary-check \
  --port=8008 \
  --request-path=/primary \
  --check-interval=5s \
  --timeout=5s \
  --unhealthy-threshold=3 \
  --healthy-threshold=2

Bare Metal k3s-implementatie met Rancher en Longhorn

Voor organisaties die hun eigen hardware gebruiken, biedt de implementatie van PostgreSQL HA op bare metal met k3s, Rancher en Longhorn een volledig open-source, cloud-onafhankelijke infrastructuur. k3s is een lichtgewicht Kubernetes-distributie die efficiënt draait op bare metal-servers zonder de overhead van een volledige Kubernetes-distributie.

Blank metaal k3s HA — PostgreSQL met PatroniVirtueel IP (Keepalived VRRP) — 10.0.0.100Drijvende VIP voor HAProxy actief/stand-byHAProxy (actief)blank metaal-lb1HAProxy (stand-by)blank metaal-lb2k3s Cluster (beheerd door Rancher)k3s Knooppunt 1 (server)PostgreSQL PrimairePatroni + PgBouncerLonghorn-volume (500 GB)NVMe SSD — bare-metal-srv1k3s Knooppunt 2 (server)PostgreSQL Stand-by 1Patroni + PgBouncerLonghorn-volume (500 GB)NVMe SSD — bare-metal-srv2k3s Knooppunt 3 (server)PostgreSQL Stand-by 2Patroni + PgBouncerLonghorn-volume (500 GB)NVMe SSD — bare-metal-srv3Extern etcd-cluster (3 speciale knooppunten)etcd1 (10.0.3.10) · etcd2 (10.0.3.11) · etcd3 (10.0.3.12)RancherbeheerUI + clusterlevenscyclusPrimaireStand-byenz.LanghoornHAProxyStreamingreplicatie weergegeven als groene stippellijnen

k3s en Longhorn-installatie

# Install k3s on the first server node
curl -sfL https://get.k3s.io | K3S_TOKEN=my-cluster-token \
  INSTALL_K3S_EXEC="server --cluster-init --disable traefik --disable servicelb" sh -

# Join additional server nodes
curl -sfL https://get.k3s.io | K3S_TOKEN=my-cluster-token \
  K3S_URL=https://10.0.0.1:6443 \
  INSTALL_K3S_EXEC="server" sh -

# Install Longhorn for distributed block storage
helm repo add longhorn https://charts.longhorn.io
helm install longhorn longhorn/longhorn \
  --namespace longhorn-system --create-namespace \
  --set defaultSettings.defaultDataPath=/mnt/longhorn \
  --set defaultSettings.replicaCount=3 \
  --set defaultSettings.storageMinimalAvailablePercentage=15

# Deploy PostgreSQL with Patroni using the Zalando Postgres Operator
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator
helm install postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-system --create-namespace
# PostgreSQL cluster manifest for the Zalando Postgres Operator
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-ha-cluster
  namespace: production
spec:
  teamId: "platform"
  numberOfInstances: 3
  volume:
    size: 500Gi
    storageClass: longhorn
  users:
    appuser:
      - superuser
      - createdb
    replicator: []
  databases:
    appdb: appuser
  postgresql:
    version: "16"
    parameters:
      shared_buffers: "16GB"
      effective_cache_size: "48GB"
      work_mem: "256MB"
      maintenance_work_mem: "2GB"
      max_connections: "200"
      max_wal_senders: "10"
      wal_level: replica
      synchronous_commit: "on"
      wal_keep_size: "2GB"
      archive_mode: "on"
      track_commit_timestamp: "on"
  patroni:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    synchronous_mode: true
  resources:
    requests:
      cpu: "4"
      memory: 32Gi
    limits:
      cpu: "8"
      memory: 64Gi

Keepalived voor HAProxy VIP

# /etc/keepalived/keepalived.conf on lb1
vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2
    weight 2
}

vrrp_instance VI_PG {
    state MASTER
    interface eth0
    virtual_router_id 52
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass pgha_vip_pass
    }
    virtual_ipaddress {
        10.0.0.100/24
    }
    track_script {
        chk_haproxy
    }
}

Bewaking van PostgreSQL-replicatie

Het bewaken van de replicatiestatus is niet onderhandelbaar in productie. PostgreSQL biedt hiervoor verschillende ingebouwde weergaven, en Prometheus met Grafana biedt de zichtbaarheid en waarschuwingen op lange termijn die u nodig heeft.

Ingebouwde monitoringquery's

-- Check replication status on the primary
SELECT
    client_addr,
    application_name,
    state,
    sync_state,
    sent_lsn,
    write_lsn,
    flush_lsn,
    replay_lsn,
    (sent_lsn - replay_lsn) AS replication_lag_bytes,
    write_lag,
    flush_lag,
    replay_lag
FROM pg_stat_replication;

-- Check replication slot status
SELECT
    slot_name,
    slot_type,
    active,
    wal_status,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS slot_lag
FROM pg_replication_slots;

-- Check standby recovery status (run on standby)
SELECT
    pg_is_in_recovery() AS is_standby,
    pg_last_wal_receive_lsn() AS last_received,
    pg_last_wal_replay_lsn() AS last_replayed,
    pg_last_xact_replay_timestamp() AS last_replayed_timestamp,
    EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::int AS replay_lag_seconds;

-- Monitor WAL generation rate
SELECT
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), '0/0')) AS total_wal_generated,
    pg_size_pretty(sum(size)) AS wal_directory_size
FROM pg_ls_waldir();

-- Check for long-running queries that could block replication
SELECT
    pid,
    now() - pg_stat_activity.query_start AS duration,
    query,
    state
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes'
  AND state != 'idle'
ORDER BY duration DESC;

Prometheus en Grafana stapelen

Depostgres_exportergeeft PostgreSQL-statistieken weer in Prometheus-indeling. Gecombineerd met depatroni_exporterkrijgt u volledig inzicht in zowel de databaseprestaties als de HA-clusterstatus.

# Deploy postgres_exporter as a sidecar or standalone
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

# Custom queries for postgres_exporter
# /etc/postgres_exporter/queries.yaml
pg_replication_lag:
  query: |
    SELECT
      CASE WHEN pg_is_in_recovery() THEN
        EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::float
      ELSE 0 END AS lag_seconds
  master: true
  metrics:
    - lag_seconds:
        usage: "GAUGE"
        description: "Replication lag in seconds"

pg_replication_slots:
  query: |
    SELECT
      slot_name,
      active::int AS active,
      pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)::float AS slot_lag_bytes
    FROM pg_replication_slots
  master: true
  metrics:
    - slot_name:
        usage: "LABEL"
    - active:
        usage: "GAUGE"
        description: "Whether the slot is active"
    - slot_lag_bytes:
        usage: "GAUGE"
        description: "Slot lag in bytes"
# PrometheusRule for PostgreSQL HA alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: postgresql-ha-alerts
  namespace: monitoring
spec:
  groups:
    - name: postgresql-replication
      rules:
        - alert: PostgreSQLReplicationLagHigh
          expr: pg_replication_lag_seconds > 30
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "PostgreSQL replication lag exceeds 30s on {{ $labels.instance }}"

        - alert: PostgreSQLReplicationSlotInactive
          expr: pg_replication_slots_active == 0
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "Replication slot {{ $labels.slot_name }} is inactive"

        - alert: PostgreSQLReplicationSlotLagHigh
          expr: pg_replication_slots_slot_lag_bytes > 1073741824
          for: 10m
          labels:
            severity: warning
          annotations:
            summary: "Replication slot lag exceeds 1GB on {{ $labels.slot_name }}"

        - alert: PatroniClusterUnhealthy
          expr: patroni_cluster_members_count < 3
          for: 2m
          labels:
            severity: critical
          annotations:
            summary: "Patroni cluster has fewer than 3 members"

Productie-afstemmingsparameters

De standaardconfiguratie van

PostgreSQL is conservatief, afgestemd op een kleine gedeelde hostingomgeving. Productie-HA-clusters vereisen een zorgvuldige afstemming van replicatie-, geheugen- en WAL-parameters. De volgende tabel vat de belangrijkste instellingen samen voor een 64GB RAM-server met NVMe-opslag.

# postgresql.conf — Production HA tuning

# === Replication ===
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
wal_keep_size = 4GB
synchronous_commit = on
synchronous_standby_names = 'ANY 1 (standby1, standby2)'
track_commit_timestamp = on
wal_log_hints = on

# === WAL ===
min_wal_size = 1GB
max_wal_size = 8GB
wal_buffers = 64MB
wal_compression = zstd
archive_mode = on
archive_timeout = 300
checkpoint_completion_target = 0.9
checkpoint_timeout = 15min

# === Memory ===
shared_buffers = 16GB              # 25% of RAM
effective_cache_size = 48GB        # 75% of RAM
work_mem = 256MB                   # per-operation sort/hash memory
maintenance_work_mem = 2GB         # for VACUUM, CREATE INDEX
huge_pages = try

# === Connections ===
max_connections = 200              # use PgBouncer for higher client counts
superuser_reserved_connections = 5

# === Query Performance ===
random_page_cost = 1.1             # SSD storage
effective_io_concurrency = 200     # NVMe SSD
default_statistics_target = 500
jit = on

# === Logging ===
log_min_duration_statement = 500   # log queries > 500ms
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0
log_autovacuum_min_duration = 0

# === Autovacuum ===
autovacuum_max_workers = 4
autovacuum_naptime = 30s
autovacuum_vacuum_cost_limit = 2000
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.02

Patroni DCS-parameters afstemmen

De relatie tussen Patroni'sttl-,loop_wait- enretry_timeout-parameters heeft een directe invloed op de failover-snelheid en het fout-positieve risico. Een kortere TTL betekent een snellere failover-detectie, maar verhoogt het risico op onnodige failovers tijdens korte netwerkstoringen.

# Conservative (production default)
ttl: 30
loop_wait: 10
retry_timeout: 10
# Failover detection: ~30-40 seconds

# Aggressive (low-latency failover)
ttl: 15
loop_wait: 5
retry_timeout: 5
# Failover detection: ~15-20 seconds
# Warning: Higher risk of false failovers in unstable networks

Chaos-engineering en failover-testen

Een failoversysteem dat nog nooit is getest, is een systeem dat niet werkt. Chaos-engineering past gecontroleerde fouten toe om te valideren dat uw HA-installatie zich correct gedraagt ​​onder echte foutomstandigheden. Elk Patroni-cluster moet regelmatig worden onderworpen aan failover-oefeningen.

Failover-test Playbook

# 1. Verify cluster health before testing
patronictlctl -c /etc/patroni/patroni.yml list
+----------+---------+---------+----+-----------+
| Member   | Host    | Role    | TL | Lag in MB |
+----------+---------+---------+----+-----------+
| node1    | 10.0.1.10| Leader |  5 |           |
| node2    | 10.0.1.11| Replica |  5 |         0 |
| node3    | 10.0.1.12| Replica |  5 |         0 |
+----------+---------+---------+----+-----------+

# 2. Simulate primary crash (on node1)
sudo systemctl stop patroni
# Or more aggressive: sudo kill -9 $(pgrep -f patroni)

# 3. Monitor failover (from any node with patronictl)
watch -n 1 'patronictl -c /etc/patroni/patroni.yml list'

# 4. Verify new leader is elected (within 30-45 seconds)
# Expected: node2 or node3 promoted to Leader

# 5. Test write availability through HAProxy
PGPASSWORD=app_password psql -h haproxy-host -p 5000 -U appuser -d appdb \
  -c "INSERT INTO health_check (ts) VALUES (now()) RETURNING *;"

# 6. Restart the former primary
sudo systemctl start patroni
# Patroni will use pg_rewind to rejoin as a replica

# 7. Verify the former primary rejoins as replica
patronictlctl -c /etc/patroni/patroni.yml list

Netwerkpartitie testen

# Simulate network partition on the primary using iptables
# Block all traffic to etcd from the primary
sudo iptables -A OUTPUT -d 10.0.2.10 -j DROP
sudo iptables -A OUTPUT -d 10.0.2.11 -j DROP
sudo iptables -A OUTPUT -d 10.0.2.12 -j DROP

# Expected behaviour:
# 1. Primary loses DCS access
# 2. Leader key TTL expires
# 3. Primary demotes itself (with watchdog, node may reboot)
# 4. Standby acquires leader lock and promotes
# 5. After clearing iptables rules, former primary rejoins as replica

# Clean up
sudo iptables -D OUTPUT -d 10.0.2.10 -j DROP
sudo iptables -D OUTPUT -d 10.0.2.11 -j DROP
sudo iptables -D OUTPUT -d 10.0.2.12 -j DROP

Geautomatiseerde chaostests met Toxiproxy

# Run Toxiproxy alongside your Patroni cluster
# Create proxies for etcd and replication connections
toxiproxy-cli create etcd_proxy -l 0.0.0.0:12379 -u 10.0.2.10:2379
toxiproxy-cli create pg_repl_proxy -l 0.0.0.0:15432 -u 10.0.1.10:5432

# Add latency to etcd connections (simulates degraded network)
toxiproxy-cli toxic add etcd_proxy -t latency -a latency=500 -a jitter=200

# Add bandwidth limit to replication (simulates WAN replication)
toxiproxy-cli toxic add pg_repl_proxy -t bandwidth -a rate=1024

# Completely sever the connection (simulates network partition)
toxiproxy-cli toxic add etcd_proxy -t timeout -a timeout=0

# Monitor Patroni behaviour and verify correct failover
watch -n 2 'curl -s http://10.0.1.10:8008/patroni | python3 -m json.tool'

Continu validatiescript

#!/bin/bash
# continuous_ha_check.sh — Run during chaos tests to measure availability

HAPROXY_HOST="10.0.0.100"
WRITE_PORT=5000
READ_PORT=5001
DATABASE="appdb"
USER="appuser"
LOGFILE="/var/log/ha_test_$(date +%Y%m%d_%H%M%S).log"

write_count=0
write_fail=0
read_count=0
read_fail=0

while true; do
    ts=$(date '+%Y-%m-%d %H:%M:%S.%3N')

    # Test write path
    if PGPASSWORD=app_password psql -h $HAPROXY_HOST -p $WRITE_PORT \
       -U $USER -d $DATABASE -c "SELECT 1" &>/dev/null; then
        ((write_count++))
    else
        ((write_fail++))
        echo "$ts WRITE_FAIL total_fails=$write_fail" >> $LOGFILE
    fi

    # Test read path
    if PGPASSWORD=app_password psql -h $HAPROXY_HOST -p $READ_PORT \
       -U $USER -d $DATABASE -c "SELECT 1" &>/dev/null; then
        ((read_count++))
    else
        ((read_fail++))
        echo "$ts READ_FAIL total_fails=$read_fail" >> $LOGFILE
    fi

    total=$((write_count + write_fail))
    if (( total % 100 == 0 )); then
        write_avail=$(echo "scale=2; $write_count * 100 / $total" | bc)
        read_total=$((read_count + read_fail))
        read_avail=$(echo "scale=2; $read_count * 100 / $read_total" | bc)
        echo "$ts Writes: ${write_avail}% ($write_count/$total) Reads: ${read_avail}% ($read_count/$read_total)"
    fi

    sleep 0.5
done

Advanced: trapsgewijze replicatie en vertraagde stand-bys

Voor grote clusters vermindert trapsgewijze replicatie de belasting van de primaire cluster. In plaats van dat alle standbys rechtstreeks vanuit de primaire repliceren, repliceren sommige standbys vanuit andere standbys. Hierdoor ontstaat een boomtopologie waarbij de primaire twee standbys voedt, en die standbys extra downstream standbys voeden.

# postgresql.auto.conf on a cascading standby
primary_conninfo = 'host=standby1-host port=5432 user=replicator application_name=cascade1'
primary_slot_name = 'cascade1_slot'

Eenvertraagde stand-by Depast opzettelijk WAL-records toe met een vertraging — doorgaans 1-4 uur. Dit biedt bescherming tegen logische fouten (per ongeluk verwijderen, slechte migraties) die onmiddellijk worden gerepliceerd naar synchrone standbys. Als er zich een ramp voordoet, kunt u het afspelen van WAL op de vertraagde standby-stand stoppen en gegevens herstellen van vóór de fout.

# postgresql.conf on delayed standby
recovery_min_apply_delay = '1h'

Verbindingsreeksstrategieën

Applicaties die verbinding maken met een door Patroni beheerd cluster moeten altijd verbinding maken via HAProxy of de ingebouwde multi-host-verbindingsreeks van PostgreSQL gebruiken mettarget_session_attrs. Dit biedt failover aan de clientzijde zonder afhankelijk te zijn van een load balancer.

# Multi-host connection string with target_session_attrs
# The client tries each host in order and connects to the one matching the target attribute
postgresql://appuser:password@node1:5432,node2:5432,node3:5432/appdb?target_session_attrs=read-write&sslmode=require

# For read-only connections
postgresql://appuser:password@node1:5432,node2:5432,node3:5432/appdb?target_session_attrs=prefer-standby&sslmode=require

Deze aanpak werkt goed voor toepassingen die niet eenvoudig opnieuw kunnen worden geconfigureerd om naar een HAProxy VIP te verwijzen. De PostgreSQL-clientbibliotheek (libpq) verwerkt de failover op transparante wijze.

Beveiligingsversterking

Een productie-PostgreSQL HA-cluster moet encryptie tijdens de overdracht en in rust afdwingen, sterke authenticatie gebruiken en de netwerkblootstelling beperken.

# Enable TLS in postgresql.conf
ssl = on
ssl_cert_file = '/etc/postgresql/certs/server.crt'
ssl_key_file = '/etc/postgresql/certs/server.key'
ssl_ca_file = '/etc/postgresql/certs/ca.crt'
ssl_min_protocol_version = 'TLSv1.3'

# Require TLS for all connections in pg_hba.conf
hostssl replication replicator 10.0.0.0/16 scram-sha-256
hostssl all         all        10.0.0.0/16 scram-sha-256

# etcd TLS
# In Patroni config
etcd3:
  hosts:
    - 10.0.2.10:2379
    - 10.0.2.11:2379
    - 10.0.2.12:2379
  protocol: https
  cacert: /etc/patroni/certs/etcd-ca.crt
  cert: /etc/patroni/certs/etcd-client.crt
  key: /etc/patroni/certs/etcd-client.key

Back-upstrategie voor HA-clusters

Een uitgebreide back-upstrategie voor Patroni-clusters moet continue WAL-archivering, regelmatige volledige back-ups en differentiële of incrementele back-ups tussen volledige back-ups omvatten. pgBackRest is de aanbevolen tool voor productie-PostgreSQL-back-upbeheer.

# Schedule backups via cron
# Full backup weekly (Sunday 2 AM)
0 2 * * 0 pgbackrest --stanza=pg-ha-cluster --type=full backup

# Differential backup daily (2 AM, Mon-Sat)
0 2 * * 1-6 pgbackrest --stanza=pg-ha-cluster --type=diff backup

# Verify backup integrity
pgbackrest --stanza=pg-ha-cluster --set=latest info

# Verify backup can be restored (dry run)
pgbackrest --stanza=pg-ha-cluster --set=latest verify

# List all backups
pgbackrest --stanza=pg-ha-cluster info
            full backup: 20260412-020000F
                timestamp: 2026-04-12 02:00:00 +0000
                wal start/stop: 000000050000000000000040 / 000000050000000000000042
                database size: 150GB, backup size: 150GB
                repository size: 45GB (compressed)
            diff backup: 20260412-020000F_20260413-020000D
                timestamp: 2026-04-13 02:00:00 +0000
                database size: 151GB, backup size: 2.1GB
                repository size: 650MB (compressed)

Operationeel Runbook-samenvatting

Elk team dat een Patroni-cluster draait, moet een runbook bijhouden dat de volgende scenario's bestrijkt. Dankzij gedocumenteerde, geteste procedures verandert een stressvolle storing in een routineoperatie.

# === Quick Reference Commands ===

# Cluster status
patronictlctl -c /etc/patroni/patroni.yml list
patronictlctl -c /etc/patroni/patroni.yml history

# Planned switchover
patronictlctl -c /etc/patroni/patroni.yml switchover --master node1 --candidate node2

# Restart PostgreSQL on a specific node (rolling restart)
patronictlctl -c /etc/patroni/patroni.yml restart pg-ha-cluster node2

# Reload PostgreSQL configuration without restart
patronictlctl -c /etc/patroni/patroni.yml reload pg-ha-cluster

# Pause automatic failover (during maintenance)
patronictlctl -c /etc/patroni/patroni.yml pause

# Resume automatic failover
patronictlctl -c /etc/patroni/patroni.yml resume

# Edit DCS configuration (applies to all nodes)
patronictlctl -c /etc/patroni/patroni.yml edit-config

# Reinitialise a failed replica
patronictlctl -c /etc/patroni/patroni.yml reinit pg-ha-cluster node3

# Check Patroni REST API directly
curl -s http://10.0.1.10:8008/patroni | python3 -m json.tool
curl -s http://10.0.1.10:8008/cluster | python3 -m json.tool

Prestatiebenchmarking

Voordat u naar productie gaat, benchmarkt u uw HA-cluster om basisprestaties vast te stellen en te verifiëren dat de latentie van synchrone replicatie acceptabel is voor uw werklast.

# Benchmark with pgbench — initialise test data
pgbench -i -s 100 -h haproxy-host -p 5000 -U appuser appdb

# Run write-heavy benchmark (measures sync replication impact)
pgbench -h haproxy-host -p 5000 -U appuser -c 32 -j 8 -T 300 appdb
# Compare with async: temporarily set synchronous_commit = off

# Run read-only benchmark through read replica port
pgbench -h haproxy-host -p 5001 -U appuser -c 64 -j 16 -T 300 -S appdb

# Measure failover impact on transactions
# Run pgbench in background, then trigger a failover
pgbench -h haproxy-host -p 5000 -U appuser -c 8 -j 4 -T 600 appdb &
sleep 60 && patronictl switchover --master node1 --candidate node2 --force

Conclusie

PostgreSQL native hoge beschikbaarheid met Patroni is geen oplossing met één tool: het is een geïntegreerd systeem voor streamingreplicatie, gedistribueerde consensus, verbindingsrouting, pooling van verbindingen, WAL-archivering, monitoring en operationele discipline. Elke laag pakt een specifieke foutmodus aan: streaming-replicatie zorgt voor gegevensredundantie, Patroni zorgt voor automatische failover-coördinatie, etcd biedt de gedistribueerde consensus die nodig is voor leiderverkiezing zonder split-brain, HAProxy routeert verbindingen naar de juiste leider, PgBouncer beheert verbindingsoverhead op schaal, en WAL-archivering met pgBackRest biedt de laatste verdedigingslinie tegen logische fouten en noodherstel.

De implementatiepatronen variëren per omgeving – AWS met NLB en Route53, Azure met Availability Zones en Azure Load Balancer, GCP met regionaal beheerde instantiegroepen, of bare metal met k3s, Longhorn en Keepalived – maar de kernarchitectuur blijft hetzelfde. Drie of meer PostgreSQL-knooppunten beheerd door Patroni, ondersteund door een etcd-cluster met drie knooppunten, met aan de voorkant een load balancer die Patroni's eindpunten voor de gezondheidscontrole volgt.

De belangrijkste investering die u kunt doen, zit niet in de configuratie, maar in het testen. Voer maandelijks failover-oefeningen uit. Netwerkpartities injecteren. Stop processen onverwachts. Meet de hersteltijd en gegevensverlies. Bouw dashboards die de replicatievertraging, de WAL-generatiesnelheid, de verzadiging van de verbindingspool en de DCS-status in realtime weergeven. Het vertrouwen dat u krijgt door systematisch testen is wat een cluster dat de eerste echte uitval overleeft, onderscheidt van een cluster dat van een serverstoring een incident met bedrijfsimpact maakt.

PostgreSQL biedt u alle replicatieprimitieven. Patroni geeft jou de orkestratie. etcd geeft u de consensus. Het is jouw taak om ze op de juiste manier met elkaar te verbinden, ze af te stemmen op jouw werklast en ze voortdurend te valideren. Deze handleiding heeft u de blauwdrukken gegeven: u kunt nu met vertrouwen bouwen, testen en werken.