Workstation Logo
Produtos
Labs de IAAgentes OpenAIAgentes ClaudeGrok BotWorkstation CRM (WSL CRM)MarketingTodos os Produtos
Soluções IA
Estações de Trabalho IAAI SME PackagesIA PrivadaClusters GPUIA EdgeLaboratório IA EmpresarialIA por Indústria
Serviços
Modernização de plataformaEngenharia digitalFundações de dados e IAOperações autónomasConsultoria de IAAutomação DevOpsCibersegurançaDesenvolvimento de softwareConstrução de agentesConfiguração MLOps
Sobre Nós
ParceirosHistórias de Clientes
Artigos
Documentação
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
Blog
Contacte-nosLogin
Workstation

Estações de trabalho de IA, software multiagente de IA, infraestrutura de GPU e soluções de agentes inteligentes para empresas modernas.

Contacte-nos

Soluções de IA

Estações de Trabalho IAAI SME PackagesIA PrivadaClusters GPUIA EdgeLaboratório IA EmpresarialIA por Indústria

Produtos

Todos os ProdutosWSL CRM e ERPMarketingAgentes OpenAIWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

Empresa

Sobre NósPor que WorkstationParceirosHistórias de ClientesPreçosContato

Recursos

ArtigosDocumentaçãoBlogPesquisarMapa do Site
Escritório Reino Unido
77-79 Marlowes, Hemel Hempstead HP1 1LFComo chegar: pegue a saída 20 da M25, Outer LondonN.º da empresa: 11641870Seg - Sex: 9:00 - 18:00 GMT
+44 7515 356 146
Escritório Bélgica
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683Seg - Sex: 9:00 - 18:00 CET
+32 492 45 67 46
Escritório Índia
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. Todos os direitos reservados.

PrivacidadeCookiesTermos de ServiçoMapa do site

Loading blog...

Home / Blog
DatabaseKubernetesDevOpsBackend

Alta disponibilidade nativa PostgreSQL: Patroni, replicação de streaming e estratégias de failover de produção

HA nativa PostgreSQL com Patroni, replicação de streaming e HAProxy

Balinder Walia12 de abril de 202633 min read

A execução de uma única instância PostgreSQL é simples até que a primeira interrupção não planejada lembre você de que um banco de dados é tão valioso quanto sua disponibilidade. Falhas de disco, kernel panics, partições de rede e atualizações malfeitas não são riscos teóricos — são certezas operacionais em um cronograma suficientemente longo. O PostgreSQL não é fornecido com failover automático integrado, mas fornece todos os primitivos de replicação necessários para criar um cluster altamente disponível. Patroni, uma estrutura de HA de código aberto mantida pela Zalando, orquestra esses primitivos em um sistema de failover de nível de produção que foi testado em escala em milhares de clusters PostgreSQL em todo o mundo.

Este artigo é um guia de engenharia aprofundado. Abordaremos replicação de streaming PostgreSQL (síncrona e assíncrona), arquitetura e configuração Patroni, etcd como um armazenamento de configuração distribuído, HAProxy para roteamento de conexão com divisão de leitura e gravação, PgBouncer para pool de conexão, arquivamento WAL e recuperação point-in-time, replicação lógica para sincronização seletiva de dados, pg_basebackup para provisionamento inicial de espera, repmgr como uma alternativa ao Patroni, padrões de implantação específicos de nuvem para AWS, Azure, e GCP, implantação bare metal k3s com Rancher e Longhorn, monitoramento com pg_stat_replication e Prometheus/Grafana, procedimentos de alternância versus failover, prevenção de split-brain, ajuste de produção e engenharia de caos para validação de failover.

Fundamentos da replicação de streaming

PostgreSQL

A replicação de streaming

é a espinha dorsal da alta disponibilidade do PostgreSQL. Ele funciona enviando continuamente registros Write-Ahead Log (WAL) de um servidor primário para um ou mais servidores em espera. O standby aplica esses registros WAL em tempo real, mantendo uma cópia quase idêntica dos dados do primário. Esse mecanismo foi introduzido na PostgreSQL 9.0 e foi refinado em todas as versões subsequentes.

Existem dois modos de replicação de streaming:assíncronoesíncrono. No modo assíncrono, o primário não espera que os standbys confirmem o recebimento dos registros WAL antes de confirmar uma transação. Isso proporciona desempenho máximo de gravação, mas introduz uma janela de possível perda de dados – se o primário falhar antes que um modo de espera tenha recebido o WAL mais recente, essas transações serão perdidas. No modo síncrono, o primário aguarda pelo menos um modo de espera para confirmar que os registros WAL foram gravados no armazenamento durável antes de relatar uma transação como confirmada. Isso elimina a perda de dados ao custo do aumento da latência de confirmação, uma vez que cada gravação deve ir e voltar para um modo de espera.

A escolha entre replicação síncrona e assíncrona não é binária. O PostgreSQL oferece suporte aosynchronous_commitno nível da sessão, de modo que cargas de trabalho sensíveis à latência podem optar por confirmações assíncronas, enquanto transações financeiras críticas usam confirmações síncronas no mesmo cluster.

Configurando o Primário para Replicação

O servidor primário deve ser configurado para gerar registros WAL em um nível suficiente para replicação e para permitir conexões em espera. As seguintes configurações dopostgresql.confsão essenciais.

# 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

A autenticação para conexões de replicação é tratada empg_hba.conf. As conexões de replicação usam um tipo de conexão dedicado.

# 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

Crie o usuário de replicação no primário.

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strong_replication_password';

Provisionando um Standby com pg_basebackup

O utilitáriopg_basebackupcria uma cópia física do diretório de dados do primário, que se torna o ponto de partida para um novo standby. Ele lida com o backup básico e o streaming WAL atomicamente, para que a cópia resultante seja consistente.

# 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

O sinalizador-Ré crítico – ele gravaprimary_conninfoempostgresql.auto.confe criastandby.signal, que informa ao PostgreSQL para iniciar no modo de espera. Na PostgreSQL 12 e posterior, orecovery.confé substituído por esses dois mecanismos.

# 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'

Crie o slot de replicação no primário antes de iniciar o modo de espera, para evitar que o WAL seja limpo antes que o modo de espera possa consumi-lo.

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

Patroni: Orquestração HA automatizada

A replicação de streaming

oferece redundância de dados, mas não oferece failover automático. Se o primário travar, alguém — um operador humano ou um sistema de automação — deverá promover um standby para primário, reconfigurar os standbys restantes para seguir o novo primário e atualizar o roteamento da conexão. Patroni automatiza tudo isso.

Patroni é um daemon Python executado junto com cada instância PostgreSQL. Ele usa um Distributed Configuration Store (DCS) — normalmente etcd, mas também ZooKeeper ou Consul — para coordenar a eleição do líder e o estado do cluster. Cada nó Patroni grava continuamente seu status de integridade no DCS. Quando o líder (primário) não consegue renovar sua chave DCS dentro do TTL configurado, Patroni inicia uma eleição de líder entre os standbys íntegros. O vencedor é promovido a primário e os nós restantes se reconfiguram como esperas do novo primário – tudo automaticamente, normalmente dentro de 10 a 30 segundos.

ArquiteturaPatroni HA – Cluster PostgreSQL de 3 nósClientes de aplicaçãoBalanceador de carga HAProxyporta 5000 (RW) · porta 5001 (RO)Primário (Líder)PostgreSQL 16 + PatroniNó1 — 10.0.1.10:5432Espera 1 (Sincronização)PostgreSQL 16 + PatroniNó2- 10.0.1.11:5432Standby 2 (Assíncrono)PostgreSQL 16 + PatroniNó3 - 10.0.1.12:5432sincronização de transmissãoTransmissão assíncronaClusteretcd (DCS)Nós3 – eleição de líder e seleção de líder. armazenamento de configuraçãoPrimárioEm esperaetcd DCSHAProxyConfiguração

Patroni YAML

O

Patroni é configurado por meio de um arquivo YAML que define a conexão DCS, parâmetros PostgreSQL, comportamento de replicação e configurações de bootstrap. A seguir está uma configuração de nível de produção para o nó primário.

# /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

Os nós em espera usam uma configuração idêntica com seus próprios valoresname,connect_addresselisten. Patroni cuida do resto – ele detecta se um nó deve ser o líder ou uma réplica com base no estado DCS e configura o PostgreSQL de acordo.

etcd como armazenamento de configuração distribuída

etcd é o sistema nervoso de um cluster Patroni. Ele armazena a identidade do líder atual, a topologia do cluster, a configuração desejada e o status de funcionamento de cada nó. Um cluster etcd de três nós é o mínimo para produção, tolerando a falha de um nó enquanto mantém o quorum.

# 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

Para implantações de produção, ative o TLS entre pares etcd e entre clientes etcd e Patroni. O tráfego etcd não criptografado expõe as credenciais e a configuração do cluster a invasores no nível da rede.

HAProxy para roteamento de conexão

Patroni expõe um REST API em cada nó (porta 8008 por padrão) que informa se o nó é o líder atual ou uma réplica. O HAProxy usa esses endpoints de verificação de integridade para rotear o tráfego: as gravações vão para o líder, as leituras vão para as réplicas íntegras. Isso oferece divisão automática de leitura e gravação sem quaisquer alterações no nível do aplicativo.

# /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

O endpoint/primaryretorna HTTP 200 apenas no líder Patroni atual. O endpoint/replicaretorna 200 em esperas íntegras. Quando ocorre um failover, o novo primário começa a retornar 200 em/primarye o HAProxy redireciona automaticamente o tráfego de gravação — normalmente dentro de um único intervalo de verificação de integridade (3 segundos). A diretivaon-marked-down shutdown-sessionsencerra imediatamente as conexões existentes com um primário com falha, forçando os clientes a se reconectarem ao novo líder.

PgBouncer para pool de conexões

PostgreSQL cria um novo processo backend para cada conexão do cliente. Em escala – centenas ou milhares de microsserviços, cada um mantendo pools de conexões – a sobrecarga de criação de processos e consumo de memória torna-se significativa. O PgBouncer fica entre o aplicativo e o PostgreSQL, mantendo um conjunto de conexões do lado do servidor e multiplexando as conexões do cliente neles.

# /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

Quando usado com Patroni, o PgBouncer normalmente está localizado em cada nó PostgreSQL ou nos nós HAProxy. O modo pooltransactioné a melhor escolha para a maioria das cargas de trabalho — ele atribui uma conexão de servidor durante uma transação e a retorna ao pool entre as transações. Isto é muito mais eficiente que o modosession, que mantém uma conexão para toda a sessão do cliente.

Arquivamento WAL e recuperação pontual

A replicação de streaming protege contra falhas do servidor, mas não protege contra erros lógicos — umDROP TABLEacidental ou uma migração de aplicativo incorreta é replicado para todos os standbys imediatamente. O arquivamento WAL combinado com a recuperação pontual (PITR) permite restaurar a qualquer momento antes da ocorrência do erro.

O arquivamento WAL

copia segmentos WAL concluídos para um arquivo durável – normalmente um bucket S3, uma montagem NFS ou um servidor de backup dedicado. Ferramentas comopgBackResteWAL-Glidam com arquivamento de forma eficiente com compactação, criptografia e transferência paralela.

# 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"'

Para executar uma recuperação pontual, especifique um carimbo de data/hora de destino.

# 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
Replicação lógica

para sincronização seletiva de dados

Embora a replicação de streaming crie uma cópia física exata de todo o cluster de banco de dados, a replicação lógica opera no nível da tabela, replicando tabelas individuais ou subconjuntos de dados entre instâncias PostgreSQL independentes. Isso é útil para atualizações de versões principais com tempo de inatividade zero, réplicas de leitura entre regiões que precisam apenas de tabelas específicas, alimentação de data warehouse e distribuição de dados multilocatários.

# 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;
A replicação lógica

pode ser executada junto com a replicação de streaming. Um padrão comum é usar replicação de streaming para HA (failover físico rápido) e replicação lógica para réplicas de análise entre regiões que precisam apenas de um subconjunto de tabelas.

Replicação de streaming multirregional

Para recuperação de desastres e desempenho de leitura global, os clusters PostgreSQL podem abranger diversas regiões. O padrão padrão é a replicação síncrona dentro de uma região (para zero perda de dados no failover local) e a replicação assíncrona entre regiões (para evitar penalidades de latência entre regiões em cada gravação). Cada região possui seu próprio HAProxy para roteamento de leitura local.

Replicação de streaming PostgreSQL multirregionalRegião 1 — AWS eu-west-1Primáriopg-node1 (RW)Sincronização em esperapg-node2 (RO)SincronizaçãoHAProxy (local)Região 2 — Azure Europa OcidentalEspera assíncronapg-nó3 (RO)Espera assíncronapg-node4 (RO)SincronizaçãoHAProxy (local)Região 3 — GCP europa-oeste1Espera assíncronanó pg5 (RO)Espera assíncronapg-node6 (RO)SincronizaçãoHAProxy (local)assíncrono WALassíncrono WAL envioArquivo WAL compartilhado(S3 / Blob / GCS)pgBackRest ou WAL-G - PITRentre regiõesGlobal DNS (Route53 / Gerenciador de Tráfego / Nuvem DNS)Legenda:Replicação de sincronização (dentro da região)Replicação assíncrona (entre regiões)Arquivamento WAL para armazenamento de objetosPrimárioEm esperaProcedimentos de failover e comutação

Compreender a diferença entre failover e switchover é fundamental. Um failoveré uma promoção não planejada desencadeada pela falha do primário atual. Uma alternância deé uma mudança de função planejada e elegante – normalmente realizada antes da manutenção. Patroni apoia ambos.

Mudança planejada

# 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"}'

Durante uma transição, Patroni rebaixa o primário atual para standby, promove o candidato alvo e reconfigura todos os outros standbys para seguir o novo primário. O processo leva de 5 a 15 segundos. O HAProxy detecta a mudança por meio de verificações de integridade e redireciona o tráfego automaticamente.

Sequência de failover automático

Quando o primário falha inesperadamente, Patroni segue uma sequência precisa para restaurar o serviço. O diagrama a seguir ilustra as etapas.

Sequência de failover automáticoPatroni1primário falhaCrash, partição de rede ouFalha no discono nó12Patroni detecta via DCSO TTL da chave líderexpira no etcd(TTL 30s padrão)3Eleição do LíderStandbys corre para adquirirBloqueio de líderno etcd4em espera promovidoO vencedor doexecuta pg_ctl para promover oe se torna o novoprimário5Atualizações HAProxyAs verificações de integridade dodetectam o novoprimário/primary retorna 200 no novo líder6ClientesreconectadosAplicativosreconectados via HAProxypara novo primário de forma transparenteTempo total de failover típico doExpiração do TTL do DCS: ~15-30sEleição: ~2-5sDetecção de proxyHA: ~3-10sReconectar≈ 20-45 segundos no totalParâmetros principais doque afetam a velocidade de failover:• ttl (padrão 30s) — Quanto tempo antes que a chave líder expire no DCS• loop_wait (padrão 10s) — Com que frequência Patroni verifica o estado do cluster• retry_timeout (padrão 10s) — Tempo limite para operações DCS e PostgreSQL•maximum_lag_on_failover (1MB) — Promova apenas standbys dentro deste atraso de replicação

Prevenção de divisão cerebral

Split-brain – onde dois nós acreditam simultaneamente que são o primário – é o modo de falha mais perigoso em qualquer sistema HA. Patroni evita divisão do cérebro através de vários mecanismos:

  1. Bloqueio líder baseado em DCS:Apenas um nó pode conter a chave líder no etcd a qualquer momento. A chave possui um TTL e o líder deve renová-la continuamente. Se uma partição de rede isolar o líder do etcd, a chave expirará e o líder será rebaixado.
  2. Watchdog:Patroni pode configurar um dispositivo watchdog Linux (/dev/watchdog). Se Patroni perder o acesso ao DCS e não puder confirmar se deve permanecer como líder, o watchdog irá reinicializar ou desligar o nó – um mecanismo de isolamento rígido que garante que o antigo primário não continue aceitando gravações.
  3. pg_rewind:Quando um antigo primário fica on-line novamente, ele pode ter registros WAL que nunca foram replicados. Opg_rewindretrocede a linha do tempo até o ponto de divergência, permitindo que o nó volte a entrar em espera sem um backup de base completo. A configuraçãouse_pg_rewind: truedo Patroni automatiza isso.
# 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

como alternativa ao Patroni

repmgré outra ferramenta HA popular para PostgreSQL. Ele fornece recursos de gerenciamento de espera, failover automático e alternância. No entanto, é necessária uma abordagem fundamentalmente diferente da de Patroni. repmgr usa um nó testemunha e um daemon (repmgrd) para detecção de falhas em vez de um armazenamento de consenso distribuído. Isso torna a implantação mais simples, mas mais suscetível à divisão do cérebro em cenários complexos de partição de rede.

# 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

Para novas implantações, Patroni é a escolha recomendada devido às suas garantias mais fortes de prevenção de cérebro dividido e à comunidade de desenvolvimento mais ativa. repmgr continua sendo uma opção razoável para configurações mais simples ou organizações que já investiram na ferramenta.

Padrões de implantação em nuvem

Implantação

AWS: EC2, EBS e Route53

No AWS, implante cada nó PostgreSQL + Patroni em uma instância EC2 com volumes EBS gp3 ou io2. Use instâncias separadas em várias zonas de disponibilidade para alta disponibilidade. Os nós etcd também devem abranger AZs.

# 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
}

Use um Network Load Balancer (NLB) em vez de HAProxy se preferir uma solução gerenciada pelo AWS. O NLB pode usar verificações de integridade do grupo-alvo no Patroni REST API para rotear o tráfego para o primário atual.

Implantação

Azure: VMs, discos gerenciados e Azure LB

No Azure, use VMs Standard_E8s_v5 (com otimização de memória) com discos gerenciados SSD Premium para volumes de dados. Implante em zonas de disponibilidade. O Azure Load Balancer fornece o equivalente ao HAProxy com investigações de integridade no 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
Implantação do GCP

: Compute Engine e Cloud Load Balancing

No GCP, use instâncias n2-highmem-8 (8 vCPU, 64 GB de RAM) com discos permanentes SSD. Distribuir entre zonas dentro de uma região. Use um balanceador de carga TCP/UDP interno com verificações de integridade do Patroni.

# 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
Implantação Bare Metal k3s

com Rancher e Longhorn

Para organizações que operam seu próprio hardware, a implantação do PostgreSQL HA em bare metal com k3s, Rancher e Longhorn fornece uma infraestrutura totalmente de código aberto e independente da nuvem. k3s é uma distribuição Kubernetes leve que funciona com eficiência em servidores bare metal sem a sobrecarga de uma distribuição Kubernetes completa.

Bare Metal k3s HA — PostgreSQL com PatroniIP virtual(VRRP mantido ativo) — 10.0.0.100VIP flutuante para HAProxy ativo/standbyHAProxy (ativo)bare-metal-lb1HAProxy (em espera)bare-metal-lb2Clusterk3s (gerenciado por Rancher)k3s Nó 1 (servidor)PostgreSQL PrimárioPatroni + PgBouncerVolume Longhorn(500 GB)SSDNVMe — bare-metal-srv1k3s Nó 2 (servidor)PostgreSQL em espera 1Patroni + PgBouncerVolume Longhorn(500 GB)SSDNVMe — bare-metal-srv2k3s Nó 3 (servidor)PostgreSQL em espera 2Patroni + PgBouncerVolume Longhorn(500 GB)SSDNVMe — bare-metal-srv3Cluster etcd externo(3 nós dedicados)etcd1 (10.0.3.10) · etcd2 (10.0.3.11) · etcd3 (10.0.3.12)Gerenciamento de fazendeirosUI+ ciclo de vida do clusterPrimárioEm esperaetcdLonghornHAProxyReplicação de streaming mostrada como setas verdes tracejadasConfiguração

k3s e Longhorn

# 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

mantido ativo para 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
    }
}

Monitorando Replicação PostgreSQL

O monitoramento da integridade da replicação não é negociável na produção. O PostgreSQL oferece diversas visualizações integradas para essa finalidade, e o Prometheus com Grafana fornece a visibilidade e os alertas de longo prazo que você precisa.

Consultas de monitoramento integradas do

-- 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;
Pilha

Prometheus e Grafana

Opostgres_exporterexpõe métricas PostgreSQL no formato Prometheus. Combinado com opatroni_exporter, você obtém visibilidade total do desempenho do banco de dados e do estado do cluster HA.

# 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"
Parâmetros de ajuste de produção

A configuração padrão do

PostgreSQL é conservadora, ajustada para um pequeno ambiente de hospedagem compartilhada. Clusters de alta disponibilidade de produção exigem ajuste cuidadoso de parâmetros de replicação, memória e WAL. A tabela a seguir resume as configurações mais importantes para um servidor de 64 GB de RAM com armazenamento NVMe.

# 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
Parâmetros Patroni DCS de ajuste

O relacionamento entre os parâmetrosttl,loop_waiteretry_timeoutda Patroni impacta diretamente a velocidade de failover e o risco de falsos positivos. Um TTL mais curto significa detecção de failover mais rápida, mas aumenta o risco de failovers desnecessários durante breves interrupções na rede.

# 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
Engenharia de caos e testes de failover

Um sistema de failover que nunca foi testado é um sistema que não funciona. A engenharia do caos aplica falhas controladas para validar se sua configuração de HA se comporta corretamente sob condições reais de falha. Cada cluster Patroni deve ser submetido a exercícios regulares de failover.

Manual de teste de failover

# 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
Teste de partição de rede

# 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
Teste automatizado de caos

com 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'
Script de validação contínua

#!/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

Avançado: Replicação em Cascata e Standbys Atrasados

Para clusters grandes, a replicação em cascata reduz a carga no primário. Em vez de todos os standbys replicarem diretamente do primário, alguns standbys replicam de outros standbys. Isso cria uma topologia em árvore onde o primário alimenta dois standbys e esses standbys alimentam standbys downstream adicionais.

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

Umem espera atrasada Oaplica intencionalmente registros WAL com um atraso - normalmente de 1 a 4 horas. Isso fornece uma defesa contra erros lógicos (exclusões acidentais, migrações incorretas) que são imediatamente replicados para esperas síncronas. Se ocorrer um desastre, você poderá interromper a reprodução do WAL no modo de espera atrasado e recuperar os dados anteriores ao erro.

# postgresql.conf on delayed standby
recovery_min_apply_delay = '1h'
Estratégias de cadeia de conexão

Os aplicativos que se conectam a um cluster gerenciado pelo Patroni devem sempre se conectar por meio do HAProxy ou usar a cadeia de conexão multi-host integrada do PostgreSQL comtarget_session_attrs. Isso fornece failover do lado do cliente sem depender de um balanceador de carga.

# 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

Esta abordagem funciona bem para aplicativos que não podem ser facilmente reconfigurados para apontar para um HAProxy VIP. A biblioteca cliente PostgreSQL (libpq) lida com o failover de forma transparente.

Proteção de segurança

Um cluster PostgreSQL HA de produção deve impor criptografia em trânsito e em repouso, usar autenticação forte e limitar a exposição da rede.

# 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
Estratégia de backup

para clusters HA

Uma estratégia de backup abrangente para clusters Patroni deve incluir arquivamento WAL contínuo, backups completos regulares e backups diferenciais ou incrementais entre backups completos. pgBackRest é a ferramenta recomendada para gerenciamento de backup PostgreSQL de produção.

# 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)
Resumo do Runbook Operacional

Cada equipe que executa um cluster Patroni deve manter um runbook cobrindo os seguintes cenários. Ter procedimentos documentados e testados transforma uma interrupção estressante em uma operação de rotina.

# === 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
Comparação de desempenho do

Antes de entrar em produção, compare seu cluster de HA para estabelecer o desempenho da linha de base e verifique se a latência de replicação síncrona é aceitável para sua carga de trabalho.

# 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
Conclusão

A alta disponibilidade nativa do

PostgreSQL com Patroni não é uma solução de ferramenta única – é um sistema integrado de replicação de streaming, consenso distribuído, roteamento de conexão, pooling de conexão, arquivamento WAL, monitoramento e disciplina operacional. Cada camada aborda um modo de falha específico: a replicação de streaming lida com a redundância de dados, o Patroni lida com a coordenação automática de failover, o etcd fornece o consenso distribuído necessário para a eleição do líder sem divisão cerebral, o HAProxy roteia conexões para o líder correto, o PgBouncer gerencia a sobrecarga de conexão em escala e o arquivamento WAL com pgBackRest fornece a última linha de defesa contra erros lógicos e recuperação de desastres.

Os padrões de implantação variam entre ambientes — AWS com NLB e Route53, Azure com zonas de disponibilidade e balanceador de carga Azure, GCP com grupos de instâncias gerenciadas regionais ou bare metal com k3s, Longhorn e Keepalived — mas a arquitetura principal permanece a mesma. Três ou mais nós PostgreSQL gerenciados pelo Patroni, apoiados por um cluster etcd de três nós, liderado por um balanceador de carga que segue os endpoints de verificação de integridade do Patroni.

O investimento mais importante que você pode fazer não está na configuração, mas nos testes. Execute exercícios de failover mensalmente. Injete partições de rede. Mate processos inesperadamente. Meça o tempo de recuperação e a perda de dados. Crie painéis que mostram o atraso de replicação, a taxa de geração de WAL, a saturação do pool de conexões e a integridade do DCS em tempo real. A confiança que você ganha com testes sistemáticos é o que separa um cluster que sobrevive à sua primeira interrupção real daquele que transforma uma falha de servidor em um incidente com impacto nos negócios.

PostgreSQL oferece todas as primitivas de replicação. Patroni dá a você a orquestração. etcd fornece o consenso. Seu trabalho é conectá-los corretamente, ajustá-los à sua carga de trabalho e validá-los continuamente. Este guia forneceu os projetos — agora crie, teste e opere com confiança.