본문으로 건너뛰기

© 2026 Molayo

GeekNews헤드라인2026. 06. 16. 21:34

페일오버가 안전하지 않을 때: Kubernetes 기반 고가용성 PostgreSQL 구축

요약

Kubernetes 환경에서 네트워크 장애 시 발생하는 PostgreSQL의 복제 지연 문제를 해결하기 위한 고가용성 구축 방법을 다룹니다. Patroni와 동기식 복제를 활용한 하이브리드 모델을 통해 데이터 내구성과 자동 페일오버의 안전성을 확보하는 아키텍처를 제안합니다.

핵심 포인트

  • 네트워크 장애 시 가용성보다 데이터 내구성을 우선하는 안전한 페일오버 설계
  • Patroni와 ZooKeeper를 활용한 리더 선출 및 다중 프라이머리 방지
  • 리더 풀에는 동기식, 읽기 풀에는 비동식을 적용한 하이브리드 복제 모델
  • 게임데이를 통한 AZ 장애 시뮬레이션 및 5가지 장애 시나리오 검증
  • k8s 기반 PostgreSQL 클러스터에서 네트워크 장애 시
    복제 지연(replication lag) 이 누적되며 안전한 페일오버가 불가능해지는 구조적 약점을 해결한 방법
  • 기존 구조는
    가용성(availability)내구성(durability) 보다 우선시해, 프라이머리가 쓰기를 계속 받는 동안 복제본이 뒤처지면서 데이터 손실 없이 승격할 후보가 사라짐
  • 해결책으로 페일오버 후보에
    동기식 복제(synchronous replication) 를 적용하고, 오픈소스 고가용성 관리자 Patroni로 조율
  • 리더 풀 스탠바이만 동기식 복제에 참여하고 읽기 복제본은 비동기를 유지하는
    하이브리드 복제 모델로, 내구성과 지연 시간 사이 균형 확보
    remote_apply

모드 적용 시 쓰기 지연 53% 증가 등 성능 비용에도, 5가지 장애 시나리오 검증을 통해 안전한 자동 페일오버 달성

게임데이에서 드러난 문제

  • Datadog은 시스템과 프로세스의 빈틈을 선제적으로 찾기 위해
    게임데이를 정기 실시, 플랫폼에 의도적 부하를 가해 실제 조건에서의 반응 학습

  • 한 게임데이에서 스테이징 환경에
    가용 영역(AZ) 장애를 시뮬레이션하며 네트워크 지연을 유발, PostgreSQL 아키텍처의 약점 노출

  • 여러 Kubernetes 기반 PostgreSQL 클러스터의 프라이머리/라이터 노드가 영향받은 AZ에서 동작 중

  • 네트워크 지연 급증으로 프라이머리가 복제본과 안정적으로 통신 불가, 복제 지연 증가 → 쓰기 정체 → 애플리케이션이 오래된 데이터 제공

  • 충분히 최신 상태인 복제본이 없어 페일오버가 안전하지 않았고, 클러스터가 사실상 멈춤

  • 이 구조는 정상 조건에서는 잘 작동했으나, 특정 네트워크 장애 상황에서
    가용성을 내구성보다 우선시해 안전한 복구 경로가 없음

  • 프라이머리는 복제가 지연되는 동안에도 쓰기를 계속 수용, 복제 지연이 커지며 복제본이 더 뒤처짐

  • 결과적으로 데이터 손실 위험 없이는 페일오버 후보를 승격할 수 없었고, 지연이 잦아들고 복제본이 따라잡기를 기다리는 것이 유일한 선택지

  • 목표는 PostgreSQL 성능 특성을 필요 이상으로 훼손하지 않으면서 페일오버를
    자동이면서 안전하게 만드는 것

기준 아키텍처: Kubernetes 위의 PostgreSQL

  • Kubernetes 기반 PostgreSQL 클러스터는
    leader poolread replica pool 두 풀로 구성, PostgreSQL은 단일 라이터(single-writer) 시스템

  • 읽기/쓰기 분리로 리더 부담 없이 읽기 확장 가능, 쓰기 지연은 예측 가능하고 안정적으로 유지

  • leader pool은 모든 쓰기를 처리하는 단일 활성 라이터 노드 1개와 스탠바이 노드 2개로 구성

  • 스탠바이는 애플리케이션 트래픽을 처리하지 않으나 리더 장애 시 승격 가능

  • read replica pool은 읽기 전용 트래픽을 처리하는 다수 노드로 구성, 읽기 확장성과 쿼리 격리에 최적화되어 페일오버 대상에서 의도적으로 제외

Patroni와 ZooKeeper의 역할

Patroni가 복제, 페일오버, 리더 선출을 관리하며, 분산 구성 저장소(DCS)로 ZooKeeper 사용

  • ZooKeeper는 현재 리더 키/락, 클러스터 구성, 각 멤버의 복제 상태(최신 LSN 등) 메타데이터 저장

  • Patroni는 이 정보로 승격·강등을 보수적으로 판단, 공격적 페일오버보다 데이터 일관성 우선

  • 새 노드가 클러스터에 합류하면 먼저 ZooKeeper에서 리더 존재 여부 확인

  • 리더가 없으면 임시 znode 생성으로 리더 키 획득 시도, ZooKeeper가 단일 노드만 키 획득을 보장해
    다중 프라이머리 형성 방지

  • 리더가 이미 있으면 자신을 복제본으로 구성하고 스트리밍 복제 시작

  • 네트워크 분할(network partition) 시 리더 또는 ZooKeeper와의 연결이 끊긴 복제본은 클러스터 상태를 확인할 수 없어, Patroni가 해당 노드를 일시 중지 또는 강등

  • 리더가 연결을 잃으면 Patroni가 ZooKeeper와 협력해 적격 스탠바이 하나만 리더 락 획득, 부분 네트워크 장애에서도 통제된 페일오버 보장

  • 연결 복구 후 기존 리더는 리더 락 재획득에 실패하면 스스로 스탠바이로 강등,
    split brain 방지

안전한 페일오버가 불가능했던 이유

  • 단일 라이터 모델에서 장애 시 Patroni가 정상 스탠바이 중 새 리더를 선출
  • 데이터 손실 방지를 위해 Patroni는 승격 전 안전 점검 수행, 핵심은
    복제 지연maximum_lag_on_failover

임계값 이내인지 확인

  • 스탠바이가 리더보다 뒤처졌으면 승격 시 데이터 누락·불일치 발생 가능

  • 게임데이에서 프라이머리가 연결을 잃자 모든 스탠바이의 복제 지연이 임계값 초과, Patroni가 페일오버를 정확히 거부

  • 클러스터가 안전한 쓰기 가능 프라이머리 없이 남은 것은 Patroni 때문이 아니라 안전한 승격 후보가 없었기 때문

스트리밍 복제의 두 가지 모드

  • 스트리밍 복제에서 리더는 모든 변경을 담은
    write-ahead log(WAL) 를 복제본에 지속 전송, 복제본은 WAL을 로컬에 적용해 동기화 유지

비동기식 복제 (기본값)

  • 리더가 트랜잭션 커밋 전 복제본의 확인을 기다리지 않음

  • 쓰기 지연 최소화, 높은 처리량 지원

  • 단, 리더 장애 시 프라이머리에 커밋됐으나 아직 복제되지 않은 트랜잭션이 승격 과정에서 손실 가능

동기식 복제

  • 리더가 클라이언트에 응답을 보내기 전 최소 1개 복제본의 확인 대기
  • 적어도 하나의 복제본이 너무 뒤처질 위험을 크게 줄이고, 커밋된 트랜잭션이 다른 노드에 존재함을 확인 후 응답하므로 더 강한 내구성 보장
  • 페일오버 후보가 최신 상태일 가능성이 높아 데이터 분기 위험 없이 승격 가능

하이브리드 복제 설정

  • 내구성·지연·처리량 균형을 위해 하이브리드 복제 모델 채택
    leader pool의 스탠바이 노드는 동기식 복제에 참여, 리더가 지정 동기 스탠바이의 확인 후 쓰기 커밋
    read replica는 비동기식 복제 유지, 읽기 전용 트래픽만 처리하고 페일오버 대상이 아니므로 리더 풀 복제 부담 제한

  • 이를 통해 읽기 복제본에 동일한 지연 비용을 부과하지 않으면서 페일오버 후보에만 엄격한 내구성 보장 적용

안전한 페일오버를 위한 PostgreSQL·Patroni 튜닝

  • 동기식 복제 활성화를 위해 PostgreSQL과 Patroni 양쪽에서 파라미터 조정

조정한 주요 파라미터

synchronous_mode

: Patroni 동기식 복제 활성화, true

synchronous_node_count

에 따라 동기 스탠바이 확인 후 커밋 (기본값 false → true, Patroni 관리, 필수)
synchronous_node_count

: 동기 스탠바이 노드 수, synchronous_standby_names

목록 생성에 사용 (기본값 1 → 1, Patroni 관리, 선택)
synchronous_mode_strict

: 엄격 동기 모드 강제, true

이고 가용 복제본이 없으면 비동기 전환 대신 쓰기 차단 (기본값 false → true, Patroni 관리, 선택)
synchronous_commit

: PostgreSQL 커밋 내구성 설정 (기본값 on → remote_apply, PostgreSQL 관리, 선택)

  • 적용 후 리더는 동기 스탠바이가 데이터 수신·적용을 확인한 뒤에만 클라이언트에 트랜잭션 응답 전송

내구성과 지연 시간의 균형

  • 동기식 복제는 내구성을 개선하나, 리더가 동기 스탠바이의 확인을 기다리므로 쓰기 지연 증가, 지속 부하 시 처리량 영향 가능
  • 성능 영향은 동기 스탠바이 수(
    synchronous_node_count

)와 synchronous_commit

로 설정한 내구성 수준에 좌우

synchronous_commit

내구성 단계별 트레이드오프

remote_apply

: 복제본이 WAL을 쓰고 플러시하고 재생할 때까지 대기, 가장 강한 일관성·가장 높은 지연
on

(내부적으로 remote_flush): 복제본이 WAL을 디스크에 플러시할 때까지 대기, 강한 내구성이나 스탠바이에서 아직 읽기 불가
remote_write

: WAL이 복제본 OS 캐시(디스크 아님)에 도달할 때까지 대기, 낮은 지연이나 OS 크래시에 취약
local

: 스탠바이 대기 없이 로컬 디스크 플러시 후 커밋, 노드 간 내구성 보장 없음
off

: 로컬 WAL 플러시 전 커밋, 가장 낮은 지연·가장 높은 데이터 손실 위험

동기식 복제 성능 벤치마킹

  • 각 커밋이 하나 이상 스탠바이의 확인을 기다리므로 동기식 복제는 지연을 추가, 영향 정량화를 위해 PostgreSQL 표준 부하 테스트 도구
    pgbench로 벤치마크 수행 (Patroni 버전 3.2.1)

  • 단순 읽기·쓰기 혼합을 시뮬레이션하는
    TPC-B 트랜잭션 스위트 사용, 두 지표 측정

  • 평균 지연: 트랜잭션당 평균 처리 시간(ms)

  • 초당 트랜잭션 수(tps): 연결 설정 시간 제외 완료 트랜잭션 수

테스트 파라미터

  • 스케일 팩터(데이터베이스 크기), 클라이언트 수(동시 사용자 트래픽), 스레드 수(CPU·병렬성), 트랜잭션 수(워크로드 강도)를 변화시켜 운영 유사 조건 모사

  • 쿼럼 커밋 모드의 동기식 복제는 이번 벤치마크에서 테스트 미실시

벤치마크 결과

  • 쓰기 지연 증가율:
    remote_apply

53%, on

46%, remote_write

38%, local

32%

  • 처리량(tps) 감소율:
    remote_apply

34%, on

31%, remote_write

27%, local

23%
remote_apply

는 복제본의 WAL 재생·적용까지 대기해 일관되게 가장 높은 지연·가장 낮은 처리량을 보였으나, 가장 강한 일관성으로 안전한 페일오버에 적합

프로덕션 적용

  • 벤치마킹 후 여러 고쓰기 클러스터에
    remote_apply

배포, 지속적인 프로덕션 부하에서도 애플리케이션 수준 쓰기 지연·처리량에 유의미한 영향 없음

  • 성능 위험 완화를 위해 데이터센터·워크로드 계층별로 단계적 롤아웃, 단계 사이에 베이크인 기간과 지속 모니터링 적용
  • 예: 고처리량 리소스 처리 워크로드는 동기식 복제 활성화 후 DB 쓰기 지연 증가에도 처리 지연이나 하류 백로그 없이 계속 동작
    synchronous_commit

은 다운타임 없이 patronictl edit-config

로 즉시 조정 가능, 초고처리량 워크로드의 커밋 내구성을 신속히 낮출 유연성 제공

장애 시나리오를 통한 페일오버 검증

  • 동기식 복제와 엄격한 페일오버 제어가 데이터 무결성 보호, split-brain 방지, 자동 복구를 보장하는지 검증

시나리오 1: 동기 스탠바이 1개 손실

  • 동기 스탠바이 손실 시 Patroni가 다른 적격 스탠바이를 할당해 동기식 복제 유지 시도
  • 리더 노드의 Patroni가
    pg_stat_replication

으로 끊김·정체·지연 스트리밍 연결을 감지하고 ZooKeeper로 복제본 멤버십 추적

  • 정상·적격 스트리밍 복제본 목록을 재계산하고
    synchronous_node_count

에 따라 synchronous_standby_names

갱신, 동기식 복제 활성 상태로 계속 동작

시나리오 2: 모든 동기 스탠바이 손실

  • 동작은
    synchronous_mode_strict

값에 좌우

비엄격 모드: 쓰기 가용성 우선

  • Patroni가
    synchronous_standby_names

를 비워 동기식 복제를 일시 비활성화, 정상 복제본 재합류 전까지 리더가 비동기로 전환해 쓰기 계속 허용

엄격 모드: 안전을 위해 쓰기 차단

  • Patroni가
    synchronous_standby_names

*

로 설정, 명시적 동기 스탠바이가 없어도 PostgreSQL이 쓰기 트랜잭션을 수용·로컬 커밋하나 복제본이 WAL을 확인할 때까지 클라이언트 응답 차단

  • 동기식 복제에 합류 가능한 적합 복제본이 재연결되면 Patroni가 동기 스탠바이 역할 부여

시나리오 3: 모든 스탠바이·복제본 노드 불가용

  • 모든 복제본이 불가용하고
    synchronous_mode_strict = true

이면 PostgreSQL이 최소 1개 적격 복제본 복귀까지 트랜잭션 확인 보류

  • 데이터 일관성은 유지되나 애플리케이션 수준에서 일시적 쓰기 불가 발생

시나리오 4: 동기 커밋 중 리더 장애

  • 리더가 동기 스탠바이 확인을 기다리다 확인 수신 전 중단되는 엣지 케이스

  • 흔한 원인: 커밋 중 클라이언트의 트랜잭션 취소, 리더 PostgreSQL 프로세스 크래시·종료, 커밋 단계 중 네트워크 분할

  • PostgreSQL이 WAL을 로컬에 플러시했으나 스탠바이로 복제 실패 시, 확인이 없어 트랜잭션이 복제본에 보이지 않음

  • 리더가 동기 스탠바이로 WAL 복제 전 크래시하고 해당 스탠바이가 승격되면 트랜잭션 손실 가능, 기존 리더와 신규 프라이머리의 히스토리 분기

  • 기존 리더는
    pg_rewind로 타임라인 분기 지점을 식별하고 데이터 디렉터리를 신규 프라이머리 타임라인에 맞춰 되감아, 복제되지 않은 로컬 변경을 폐기 후 스탠바이로 재합류

  • 이 동작은 Patroni가 아닌 PostgreSQL의 동기 커밋 내부 처리 결과, 쿼럼 설정과 확인 메커니즘의 신중한 튜닝·모니터링 필요성 부각

시나리오 5: ZooKeeper 불가용

  • ZooKeeper 불가용 시 Patroni가 리더십 확인·신규 선출 불가, 데이터 불일치 방지를 위해 보수적 동작으로 전환

failsafe 모드 비활성화 시

  • ZooKeeper 도달 불가여도 리더가 접근 가능하고 모든 노드가 정상이면 쓰기 계속, 단 리더 락 TTL 만료까지만 유지

  • 리더 키 갱신 루프 시간이 지나고 락 갱신 불가 시 Patroni가 리더를 강등하고 클러스터를 읽기 전용으로 전환

failsafe 모드 활성화 시

  • 리더가 ZooKeeper 연결을 잃으면 Patroni가 REST API로 모든 클러스터 멤버 도달 가능 여부를 지속 확인
  • 모든 멤버가 접근 가능할 때만 쓰기 계속, 그렇지 않으면 읽기 전용으로 강등

동기식 복제하의 수동 페일오버·스위치오버

  • Patroni는 헬스 체크와 ZooKeeper 조율 기반 자동 페일오버·스위치오버 외에
    patronictl

명령으로 수동 작업도 지원, 동기식 복제 활성 시 모든 스탠바이가 유효 후보는 아니므로 데이터 무결성 보호용 가드레일 적용

비동기 스탠바이로의 페일오버

patronictl failover

: 선택 노드가 비동기면 실패
patronictl switchover

: 선택 노드가 비동기면 실패

  • 동기식 복제 활성 중 비동기 노드로 페일오버를 강제하면 내구성 보장을 우회해 데이터 손실 가능

동기 스탠바이를 대상으로 할 때

patronictl failover

: 성공, 리더가 동기 스탠바이로 전환
patronictl switchover

: 성공, 리더와 동기 스탠바이 간 우아한 핸드오프 수행

  • 다양한
    synchronous_commit

모드 동작과 Patroni 가드레일 검증 후, 고쓰기·고읽기·혼합 워크로드 프로덕션 클러스터에 동기식 복제 활성화, 지연·처리량에 측정 가능한 영향 없음

  • 문제가 생기면
    synchronous_mode: false

설정으로 다운타임 없이 비동기 복제로 안전하게 되돌리기 가능

DRBD를 선택하지 않은 이유

  • 고가용성 평가에서 블록 수준 복제 시스템
    DRBD(Distributed Replicated Block Device) 도 검토, PostgreSQL 데이터 디렉터리와 WAL 파일을 포함한 전체 볼륨을 서버 간 미러링해 거의 실시간 스탠바이 복제본 생성
  • DRBD는 PostgreSQL 내장 스트리밍 복제보다 낮은 지연을 제공할 수 있으나, 신규 인프라·모니터링·운영 플레이북을 포함한 상당한 아키텍처 전환 필요
  • 성숙한 Kubernetes 기반 설정과 PostgreSQL 동기식 복제의 세밀한 제어를 고려해, 가시성·유연성·운영 신뢰가 더 나은 데이터베이스 수준 복제 선택

동기식 복제 모니터링

  • 동기식 복제 활성화 후 복제 상태와 페일오버 준비도를 면밀히 모니터링, 특히 두 신호가 대규모 안정성 유지에 기여

SyncRep 대기 이벤트

  • 프라이머리가 커밋 완료·상태 반환 전 동기 스탠바이의 확인을 기다릴 때 발생, 일부는 정상이나 길거나 잦은 대기는 복제본 성능 문제나 노드 간 네트워크 지연을 시사
  • 중요한 이유: 장기 대기는 쓰기 지연 증가·처리량 감소 유발
  • 추적 대상:
    SyncRep

·WalSenderWaitForReply

대기 이벤트의 지속 시간·빈도, wait_event:SyncRep

태그로 필터링한 postgresql.activity.waits

Datadog 메트릭(내부적으로 pg_stat_activity

테이블 쿼리)에서 수집

동기 스탠바이 미감지

  • Patroni가 정상 동기 스탠바이를 장기간 감지하지 못하면 클러스터가 안전한 페일오버 능력 상실
  • 중요한 이유: 동기 스탠바이가 없으면 페일오버 시 데이터 손실에 취약
  • 알림 기준:
    patroni_sync_standby

가 비어 있는 상태가 지속되면 고가용성(HA) 헬스 알림 발생, OpenMetrics 데이터에서 수집하며 네이티브 Datadog 통합 없음

  • 동기식 복제는 내구성을 개선하나 복제본이 비정상·도달 불가일 때 가용성·성능 저하, 대기 시간과 스탠바이 가용성 모니터링이 부하 상황에서 가용성·성능 유지에 필수

설계 단계부터 안전한 페일오버

  • 시뮬레이션된 AZ 장애가 PostgreSQL 아키텍처의 치명적 약점을 드러냄, 복제본이 리더보다 뒤처져 네트워크 장애를 기다리거나 데이터 분기를 감수하는 양자택일 강요, 프로덕션에서 수용 불가한 트레이드오프
  • Patroni 기반 동기식 복제 채택과 내구성·지연 튜닝으로 저하된 네트워크 조건에서도 페일오버를 가능하고 안전하게 구현, 벤치마킹과 반복 장애 시뮬레이션으로 대규모 성능 훼손 없이 예측 가능한 복구 확인
  • 동기식 복제 장애 중 쓰기를 차단함으로써 실패를 상류 서비스에 명시적으로 노출, 비동기 복제처럼 쓰기가 조용히 손실되지 않고 재시도·큐잉 등으로 대응 가능해 장애 모드가 더 가시적이고 복구 가능
  • 향후 쿼럼 기반 커밋 모드와 복제 상태에 대한 더 깊은 관측성 탐색 중

댓글과 토론

AI 자동 생성 콘텐츠

본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0