본문 바로가기
Database

PostgreSQL 클러스터 구성하기(2)

by kmkhm 2025. 6. 18.

이제 본격적으로 PostgreSQL 고가용성 클러스터를 구성해보겠습니다. 첫 번째 단계는 Etcd 클러스터 구성입니다.

Patroni는 Etcd를 통해 리더 선출, 클러스터 상태 공유, Failover 시점 판단 등을 수행하기 때문에 Etcd는 고가용성 클러스터에서 반드시 선행되어야 하는 핵심 컴포넌트입니다.

 

이번 글에서는 Etcd를 퍼블릭 EC2 인스턴스에 설치하고 구성해보겠습니다.

  • OS: Ubuntu 24.04 LTS
  • 인스턴스 수: 3대 

이번 실습은 퍼블릭 인스턴스를 사용하지만, 운영환경에서는 반드시 프라이빗 서브넷에 데이터베이스를 배치해야 합니다.

 

 

ETCD

Etcd는 분산 키-값 저장소(distributed key-value store)입니다. 기본적으로는 간단한 KVS처럼 작동하지만, RAFT 알고리즘 기반의 합의(consensus) 기능을 제공하여 다중 노드 간 상태 동기화, 리더 선출, 클러스터 메타데이터 공유 등을 가능하게 합니다. 대표적으로 Kubernetes, Patroni가 Etcd를 사용하여 클러스터 상태를 관리합니다.

Etcd는 다음과 같은 특성을 가집니다.

  • 고가용성을 위한 노드 간 합의 알고리즘(RAFT) 사용
  • 정확한 순서보장(consistency) 특성
  • gRPC / HTTP API 기반의 간단한 인터페이스
  • 3개 이상 홀수 노드로 구성해 quorum 투표 기반 운영

Etcd의 PostgreSQL 클러스터에서의 역할

PostgreSQL 자체는 클러스터 기능이 없습니다. 즉, 장애 조치나 리더 선출, 다중 노드 조율 기능이 내장돼 있지 않습니다. 여기서 Patroni가 PostgreSQL 클러스터를 제어하고, Patroni는 Etcd를 통해 다른 노드들과 정보를 공유합니다. Etcd가 PostgreSQL 클러스터에서 담당하는 역할은 다음과 같습니다.

 

1. 리더 선출: 각 노드는 Etcd에 자신이 리더가 될 자격이 있는지 정보를 등록하고, Etcd가 이를 기반으로 리더를 결정

2. 클러스터 상태 공유: 각 노드의 health 상태, replication lag 등의 정보를 Etcd를 통해 다른 노드가 알 수 있음

3. 장애 조치: 리더 노드가 비정상이라고 판단되면 Etcd를 통해 새로운 리더를 선출하고 Patroni가 자동으로 승격 수행

 

즉, Etcd는 Patroni 간 통신의 허브이자 PostgreSQL 클러스터의 중심 제어 센터입니다.

 

Etcd 설치

먼저 각 우분투 서버에서 etcd를 설치해줍니다.

wget https://github.com/etcd-io/etcd/releases/download/v3.5.12/etcd-v3.5.12-linux-amd64.tar.gz

etcd를 시스템 전체에서 사용할 수 있도록 디렉터리를 바꿔줍니다.

sudo mv etcd-v3.5.12-linux-amd64/etcd* /usr/local/bin/

 

설치 후에, 버전 체크를 통해 잘 설치되었는지 확인합니다.

etcd -version
// etcd Version: 3.5.12

 

Etcd 사용자 생성 및 디렉토리 준비

# etcd 전용 사용자 생성
sudo useradd -r -s /sbin/nologin etcd
# etcd가 데이터를 저장할 디렉토리를 생성
 sudo mkdir -p /var/lib/etcd
# 디렉토리의 소유자를 etcd 사용자로 변경
sudo chown etcd:etcd /var/lib/etcd

서비스마다 전용 계정을 만들어 실행 권한을 최소화하는 것은 리눅스 시스템에서의 기본적인 보안 원칙입니다. 그래서 etcd 역시 root가 아닌 전용 사용자 계정(etcd) 를 생성하여 실행되도록 구성합니다. 이렇게 하면 만약 etcd에 보안 취약점이 발생하더라도, 시스템 전체에 미치는 영향을 최소화할 수 있습니다.

 

또한, etcd는 실행 중에 클러스터의 상태나 로그, 스냅샷 등의 데이터를 디스크에 직접 저장하게 됩니다. 이를 위해 /var/lib/etcd 경로에 전용 디렉토리를 만들어주고, 이 디렉토리의 소유자를 etcd 사용자로 지정하여 해당 서비스만 이 디렉토리에 접근할 수 있도록 설정합니다.

 

각 노드에 etcd 설정 파일 생성

이제 각 노드마다 아래와 같이 etcd 설정 파일을 작성해줍니다. 아래 설정 파일에서 IP, node 번호는 유니크하게 작성해야 합니다.

sudo mkdir -p /etc/etcd

cat <<EOF | sudo tee /etc/etcd/etcd.conf.yml
name: node1                            # 각 노드를 구분할 고유 이름 (node2, node3 등으로 변경)
data-dir: /var/lib/etcd               # etcd 데이터(로그, 스냅샷 등)가 저장될 디렉토리
listen-client-urls: http://0.0.0.0:2379           # 클라이언트(Patroni 등) 요청을 수신할 주소
advertise-client-urls: http://172.31.12.153:2379  # 다른 노드에게 알려줄 이 노드의 실제 클라이언트 IP
listen-peer-urls: http://172.31.12.153:2380       # etcd 노드 간(peer) 통신 수신 주소
initial-advertise-peer-urls: http://172.31.12.153:2380  # peer 통신 시 이 노드가 사용할 주소
initial-cluster: node1=http://172.31.12.153:2380,node2=http://172.31.3.207:2380,node3=http://172.31.5.148:2380  # 클러스터에 참여할 모든 노드 정보
initial-cluster-state: new                       # 클러스터를 처음 구성할 때는 'new'로 설정
initial-cluster-token: patroni-etcd              # 클러스터 고유 식별자 (모든 노드에서 동일하게 설정)
EOF

 

위 설정 파일 작성 후, 실행해주시면 아래와 같이 클러스터 목록이 나옵니다.

etcdctl member list

91c1ecfedb276918, started, node1, http://172.31.12.153:2380, http://172.31.12.153:2379, false
9851de89a75ca5e8, started, node2, http://172.31.3.207:2380, http://172.31.3.207:2379, false
f61481db89adae2e, started, node3, http://172.31.5.148:2380, http://172.31.5.148:2379, false

- 첫 번째 컬럼: etcd 내부에서 부여하는 member ID  

- started: etcd 노드 상태 (정상적으로 실행 중)  

- 노드 이름: 우리가 지정한 `name` 필드의 값  

- 2380 포트: 노드 간 통신(Peer)용  

- 2379 포트: 클라이언트 요청(Client)용  

- 마지막 필드: learner 여부 (마지막 true/false):

  • false: 정상적인 etcd 멤버
  • true: learner 노드 (클러스터에 참여하지만, 투표권 없음 / 리더 불가)

 

Etcd 클러스터는 두 가지 주요 포트를 사용합니다.

  • 2380 포트는 etcd 노드 간 통신(Peer-to-Peer) 용도로 사용되며, 클러스터를 구성하고 리더 선출 등의 내부 상태를 동기화하는 데 활용됩니다.
  • 2379 포트는 클라이언트(예: Patroni, HAProxy 등)와의 외부 통신을 위한 포트입니다.
etcdctl --write-out=table --endpoints=http://172.31.12.153:2379,http://172.31.3.207:2379,http://172.31.5.148:2379 endpoint status

위 명령어를 통해 etcd 클러스터에 속한 모든 노드의 상태를 테이블 형식으로 확인할 수 있고, IS LEADER 항목을 통해 현재 리더 노드가 누구인지 쉽게 확인할 수 있습니다.

172.31.12.153:2379 91c1ecfedb276918 3.5.12 33 kB true false 2 9 9
172.31.3.207:2379 9851de89a75ca5e8 3.5.12 25 kB false false 2 9 9
172.31.5.148:2379 f61481db89adae2e 3.5.12 33 kB false false 2 9 9

 

지금까지의 아키텍처를 보면 다음과 같습니다.

 

댓글