/엔지니어/데이터베이스/Patroni + etcd로 PostgreSQL 자
데이터베이스고급linuxpostgresqlpatronietcd

Patroni + etcd로 PostgreSQL 자동 페일오버 HA 클러스터 구성

Patroni와 etcd를 이용해 PostgreSQL 3노드 HA 클러스터를 구성하고, Primary 장애 시 자동 Failover와 HAProxy 기반 부하분산까지 설정합니다.

Patroni란?

Patroni는 Python 기반 PostgreSQL HA 솔루션으로, etcd/Consul/ZooKeeper 등 DCS(Distributed Configuration Store)를 사용해 Leader 선출과 자동 페일오버를 수행합니다.

구성 요소

컴포넌트역할
PatroniPostgreSQL 프로세스 관리 + 페일오버
etcdLeader 선출용 분산 합의 저장소
HAProxy애플리케이션 → Primary/Replica 라우팅

클러스터 구성

서버IP역할
pg1192.168.1.10PostgreSQL + Patroni + etcd
pg2192.168.1.11PostgreSQL + Patroni + etcd
pg3192.168.1.12PostgreSQL + Patroni + etcd
lb192.168.1.20HAProxy

1. etcd 클러스터 설치 (3노드 모두)

Bash
sudo apt install -y etcd
Bash
# /etc/default/etcd (pg1 기준)
ETCD_NAME="pg1"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://192.168.1.10:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.1.10:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.10:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.10:2379"
ETCD_INITIAL_CLUSTER="pg1=http://192.168.1.10:2380,pg2=http://192.168.1.11:2380,pg3=http://192.168.1.12:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="pg-etcd-cluster"
Bash
sudo systemctl enable --now etcd
# 상태 확인
etcdctl endpoint status --cluster -w table

2. PostgreSQL 설치 (3노드 모두)

Bash
sudo apt install -y postgresql-17
sudo systemctl disable --now postgresql   # Patroni가 대신 관리

3. Patroni 설치 및 설정

Bash
sudo apt install -y python3-pip
pip3 install patroni[etcd] psycopg2-binary

/etc/patroni/config.yml (pg1 기준)

YAML
scope: pg-cluster
namespace: /db/
name: pg1

restapi:
  listen: 192.168.1.10:8008
  connect_address: 192.168.1.10:8008

etcd:
  hosts: 192.168.1.10:2379,192.168.1.11:2379,192.168.1.12:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576   # 1MB
    postgresql:
      use_pg_rewind: true
      parameters:
        wal_level: replica
        max_wal_senders: 5
        max_replication_slots: 5
        hot_standby: on
  initdb:
    - encoding: UTF8
    - data-checksums

  pg_hba:
    - host replication replicator 192.168.1.0/24 md5
    - host all all 0.0.0.0/0 md5

  users:
    admin:
      password: AdminPass!23
      options: [createrole, createdb]

postgresql:
  listen: 192.168.1.10:5432
  connect_address: 192.168.1.10:5432
  data_dir: /var/lib/postgresql/17/main
  bin_dir: /usr/lib/postgresql/17/bin
  pgpass: /tmp/pgpass

  authentication:
    replication:
      username: replicator
      password: ReplPass!23
    superuser:
      username: postgres
      password: PgPass!23
    rewind:
      username: rewind_user
      password: RewindPass!23

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false

pg2, pg3는 name, listen, connect_address의 IP만 각 서버에 맞게 변경합니다.

systemd 서비스

Bash
cat > /etc/systemd/system/patroni.service << 'EOF'
[Unit]
Description=Patroni PostgreSQL HA
After=network.target etcd.service

[Service]
User=postgres
ExecStart=/usr/local/bin/patroni /etc/patroni/config.yml
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now patroni

4. 클러스터 상태 확인

Bash
patronictl -c /etc/patroni/config.yml list
CODE
+ Cluster: pg-cluster ----+----+-----------+
| Member | Host           | Role    | State   |
+--------+----------------+---------+---------+
| pg1    | 192.168.1.10   | Leader  | running |
| pg2    | 192.168.1.11   | Replica | running |
| pg3    | 192.168.1.12   | Replica | running |
+--------+----------------+---------+---------+

5. HAProxy 설정 (lb 서버)

Bash
sudo apt install -y haproxy
CODE
# /etc/haproxy/haproxy.cfg
frontend pg_write
    bind *:5432
    default_backend pg_primary

backend pg_primary
    option httpchk GET /master
    http-check expect status 200
    server pg1 192.168.1.10:5432 check port 8008
    server pg2 192.168.1.11:5432 check port 8008
    server pg3 192.168.1.12:5432 check port 8008

frontend pg_read
    bind *:5433
    default_backend pg_replicas

backend pg_replicas
    balance roundrobin
    option httpchk GET /replica
    http-check expect status 200
    server pg1 192.168.1.10:5432 check port 8008
    server pg2 192.168.1.11:5432 check port 8008
    server pg3 192.168.1.12:5432 check port 8008

Patroni REST API의 /master, /replica 엔드포인트를 health check에 활용합니다.


6. 수동 전환 / 페일오버

Bash
# 계획된 전환 (데이터 무손실)
patronictl -c /etc/patroni/config.yml switchover pg-cluster

# 강제 페일오버 (비상 시)
patronictl -c /etc/patroni/config.yml failover pg-cluster

정리

기능담당
Leader 선출etcd 분산 합의
자동 페일오버Patroni (TTL 30초 이내)
쓰기 라우팅HAProxy → /master
읽기 분산HAProxy → /replica (Round Robin)

트러블슈팅 & 자주 묻는 질문

증상원인해결
페일오버가 안 됨etcd 쿼럼 상실(3노드 중 2개 다운)etcd 노드 복구 → 과반수 확보 시 Patroni 자동 재개
Split-brain 우려네트워크 파티션Patroni는 DCS(etcd) 리더 임차로 방지 — etcd를 단일 신뢰 소스로 유지
patronictl list가 비어 있음config.yml의 namespace/scope 불일치모든 노드의 namespace·scope 값이 동일한지 확인
Leader 승격이 느림ttl/loop_wait 과대 설정ttl: 30, loop_wait: 10, retry_timeout: 10 권장

Q. postgresql patroni와 etcd는 각각 무슨 역할인가요? A. Patroni는 각 PostgreSQL 노드에 붙어 상태를 관리하고 페일오버를 실행하는 에이전트이고, etcd는 '누가 리더인가'를 분산 합의로 저장하는 신뢰 소스(DCS)입니다. etcd 과반수가 살아 있어야 리더 선출과 자동 페일오버가 동작합니다.

Q. Patroni만 있으면 되지 왜 etcd가 필요한가요? A. 단일 Patroni는 자기 노드만 압니다. 여러 노드가 '리더는 하나뿐'이라는 합의에 도달하려면 외부 분산 저장소가 필요하고, 그 역할을 etcd(또는 Consul·ZooKeeper)가 맡습니다. etcd 없이는 split-brain을 막을 수 없습니다.

#postgresql#patroni#etcd#ha#failover#haproxy
편집 안내 · Editorial Note

이 가이드는 AI 도구를 활용해 초안을 구성하고 사람이 명령어·문맥을 검토해 발행했습니다. 운영체제와 도구 버전에 따라 결과가 달라질 수 있으므로 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요.

관련 공식 문서PostgreSQL 공식 문서

질문 & 답변 (Q&A)

이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.