12.5 Patroni
Patroni는 Zalando가 만든 PostgreSQL HA 클러스터 관리 도구입니다. 표준 streaming replication을 자동 failover·leader election·새 멤버 자동 합류·설정 동기화까지 통합합니다. etcd/Consul/ZooKeeper/Kubernetes 같은 DCS(Distributed Configuration Store)를 leader election에 활용합니다. 현 PostgreSQL HA의 사실상 표준입니다.
구조
flowchart LR
DCS["DCS<br/>(etcd / Consul / k8s)"]
subgraph N1["node 1 (primary)"]
P1[Patroni]
PG1[PostgreSQL]
end
subgraph N2["node 2 (standby)"]
P2[Patroni]
PG2[PostgreSQL]
end
subgraph N3["node 3 (standby)"]
P3[Patroni]
PG3[PostgreSQL]
end
P1 <--> DCS
P2 <--> DCS
P3 <--> DCS
P1 -. start/stop/promote .-> PG1
P2 -.-> PG2
P3 -.-> PG3
PG1 -- "streaming" --> PG2
PG1 -- "streaming" --> PG3
HAP["HAProxy / PgBouncer<br/>(client routing)"]
HAP --> P1
HAP --> P2
HAP --> P3
classDef dcs fill:#fed7aa,stroke:#c2410c,color:#7c2d12
classDef pa fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef pg fill:#ede9fe,stroke:#6d28d9,color:#3b0764
classDef hap fill:#d1fae5,stroke:#047857,color:#064e3b
class DCS dcs
class P1,P2,P3 pa
class PG1,PG2,PG3 pg
class HAP hap
- Patroni는 각 노드에 데몬으로 동작 — postgres를 직접 시작·정지
- DCS는 leader 정보·구성·healthcheck의 공유 저장소
- 클라이언트는 HAProxy 같은 라우터를 통해 leader에 접속
설치
# RHEL/Rocky
sudo dnf install -y patroni patroni-etcd
# Debian/Ubuntu
sudo apt-get install -y patroniDCS도 같이:
sudo dnf install -y etcd
# 또는 Consul, ZooKeeper, k8s API구성 — /etc/patroni/patroni.yml
scope: app-cluster
namespace: /db/
name: node1
restapi:
listen: 0.0.0.0:8008
connect_address: 10.0.0.1:8008
etcd3:
hosts: 10.0.10.1:2379,10.0.10.2:2379,10.0.10.3:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
synchronous_mode: true
synchronous_mode_strict: false
postgresql:
use_pg_rewind: true
parameters:
max_connections: 200
shared_buffers: 8GB
wal_level: replica
hot_standby: on
max_wal_senders: 10
max_replication_slots: 10
wal_log_hints: on
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication replicator 10.0.0.0/8 scram-sha-256
- hostssl all all 0.0.0.0/0 scram-sha-256
postgresql:
listen: 0.0.0.0:5432
connect_address: 10.0.0.1:5432
data_dir: /var/lib/pgsql/17/data
bin_dir: /usr/pgsql-17/bin
authentication:
superuser:
username: postgres
password: 'super_secret'
replication:
username: replicator
password: 'repl_secret'각 노드는 같은 scope·다른 name 사용합니다.
동작
- bootstrap: 첫 노드가 클러스터를 만든다 (initdb + initial config 적용)
- leader election: DCS에 lock 형태로 leader 등록, TTL 갱신
- 추가 노드 합류: pg_basebackup으로 leader에서 데이터 가져옴 → standby로 가동
- healthcheck: 각 Patroni가 자기 PostgreSQL 상태를 DCS에 보고
- failover: leader의 TTL 만료 또는 healthcheck 실패 → 가장 뒤처지지 않은 standby가 promote
# 명시적 failover (운영 작업)
patronictl failover app-cluster --candidate node2
# 강제 switchover (계획된 작업)
patronictl switchover app-cluster --leader node1 --candidate node2CLI — patronictl
# 클러스터 상태
patronictl -c /etc/patroni/patroni.yml list
# 예시 출력
# + Cluster: app-cluster (7234...) ----+---------+----+-----------+
# | Member | Host | Role | State | TL | Lag in MB |
# +--------+------------+---------+---------+----+-----------+
# | node1 | 10.0.0.1 | Leader | running | 3 | |
# | node2 | 10.0.0.2 | Replica | running | 3 | 0 |
# | node3 | 10.0.0.3 | Replica | running | 3 | 0 |
# +--------+------------+---------+---------+----+-----------+
# 동적 설정 변경 (DCS에 저장 → 모든 노드에 전파)
patronictl edit-config app-cluster
# 노드 일시 정지 (재시작 방지)
patronictl pause app-cluster
patronictl resume app-cluster
# 강제 reinit
patronictl reinit app-cluster node3자동 failover 시나리오
sequenceDiagram
participant Node1 as node1 (leader)
participant Node2 as node2 (replica)
participant Node3 as node3 (replica)
participant DCS
Node1->>DCS: leader lock 갱신 (매 10초)
Note over Node1: 갑자기 죽음 (kill, crash)
Node1-xDCS: 더 이상 갱신 안 함
DCS->>DCS: TTL 30초 만료
Node2->>DCS: leader lock 시도
Node3->>DCS: leader lock 시도
Note over Node2,Node3: 더 신선한 LSN을 가진<br/>candidate 선택
DCS-->>Node2: lock 획득 = new leader
Node2->>Node2: pg_ctl promote
Node3->>Node2: streaming replication 재연결
Node2->>DCS: 새 leader 알림
기본 TTL 30초·loop_wait 10초 → failover까지 약 30~60초.
pg_rewind 통합
옛 primary가 살아 돌아오면 이미 timeline이 갈라져 다시 standby로 못 붙습니다. Patroni가 pg_rewind를 자동 실행해 빠르게 동기화:
postgresql:
use_pg_rewind: true
wal_log_hints: on # pg_rewind 동작에 필요pg_rewind는 옛 primary와 새 primary의 차이만 복사 — 전체 reinit보다 훨씬 빠릅니다.
동기 모드
synchronous_mode: true # 항상 sync standby 1대 유지
synchronous_mode_strict: false # standby 없으면 async fallback (false=fallback OK)
synchronous_node_count: 1strict = true면 sync standby 없을 때 primary commit이 멈춤 — 데이터 손실 0 보장이지만 가용성 ↓.
HAProxy와의 통합
Patroni REST API(:8008/leader, /replica)가 현재 역할을 알려 줌. HAProxy는 healthcheck로 이를 활용:
backend postgres_master
option httpchk OPTIONS /leader
http-check expect status 200
server node1 10.0.0.1:5432 check port 8008
server node2 10.0.0.2:5432 check port 8008
server node3 10.0.0.3:5432 check port 8008
backend postgres_replicas
option httpchk OPTIONS /replica
http-check expect status 200
balance roundrobin
server node1 10.0.0.1:5432 check port 8008
server node2 10.0.0.2:5432 check port 8008
server node3 10.0.0.3:5432 check port 8008클라이언트는 쓰기는 5000 포트, 읽기는 5001 포트 같은 패턴입니다.
DCS 선택
| DCS | 메모 |
|---|---|
| etcd | 가장 흔함. 가볍고 검증됨. PG에는 etcd가 표준 |
| Consul | service discovery 통합 강함 |
| ZooKeeper | 일부 레거시 운영 |
| Kubernetes | k8s 환경에선 k8s API를 DCS로 |
3-5대 등 홀수 노드가 quorum의 표준입니다.
운영 시 주의
| 주의 | 메모 |
|---|---|
| DCS 자체가 죽으면 Patroni가 멈춤 | DCS HA 필수 (3대 이상) |
| split-brain 방지 — DCS quorum이 핵심 | leader 못 잡으면 모두 read-only |
maximum_lag_on_failover 설정 | 너무 뒤처진 standby는 promote 후보 제외 |
pause 안 풀고 잊음 | 자동 failover 안 됨 |
| 옛 primary가 돌아오면 reinit 또는 rewind | 자동, but 디스크 여유 필요 |
Patroni 대안
| 도구 | 메모 |
|---|---|
| repmgr | 옛 표준. DCS 없이 PostgreSQL 자체로 leader 관리 (12.6) |
| pg_auto_failover | Microsoft Citus 팀. 더 단순 (12.7) |
| stolon | etcd 기반, Patroni 유사 |
| PAF (PostgreSQL Automatic Failover) | Pacemaker 통합 |
정리
- Patroni = PostgreSQL HA의 사실상 표준 도구
- DCS(etcd 등)에 leader 정보 저장, healthcheck·자동 failover
patronictl로 운영 관리, HAProxy로 클라이언트 라우팅- 동기 모드 + pg_rewind + use_slots 같은 운영 옵션 통합
- DCS HA가 Patroni HA의 기반 — 3대 이상 quorum 필수
- 옛 primary 복귀는 pg_rewind로 빠른 합류
다음 절(12.6)에서는 더 단순한 대안 — repmgr를 봅니다.