PostgreSQL

PostgreSQL: 쉘 스크립트로 PostgreSQL 고가용성(HA) 구현

dewstream 2024. 12. 11. 15:10

※ Implement PostgreSQL High Availability with a shell script.

 

안녕하세요. 듀스트림입니다.

 

이번 포스팅에서는 오픈 소스 HA 도구를 사용하기 전에 고가용성의 기본 원리를 학습하기 위해, 간단한 쉘 스크립트로 고가용성(HA) 로직을 구현해보겠습니다.

 

※ Primary 서버와 Standby 서버의 각 로컬에서 동작하는 쉘 스크립트로 백그라운드 수행을 염두에 두고 작성하였습니다.

※ 이중화 구성은 이전 포스팅 참고 부탁드립니다.

 

PostgreSQL DBMS 이중화 구성하기

※ Setting up PostgreSQL DBMS Replication Configuration.※ Version: Linux 8.10 (Rocky), PostgreSQL 16.4.이전 포스팅에서 우리는 주요 파라미터 설정을 하고 PostgreSQL 싱글 서버 구성을 완료했습니다. 이번 글에서는 DBM

dewstream.tistory.com


목적은 아래와 같습니다.

1. 네트워크 단절, DBMS 장애를 모니터링

2. Standby 장애 발생 시 Primary는 장애 조치 없이 그대로 운영

3. Primary 장애 시 Standby Promote

4. 장애 처리가 완료되면, 쉘 스크립트를 종료


1. Primary 서버 쉘 스크립트

[그림 1] Primary 서버 쉘 스크립트 프로세스

 

▸ 쉘 스크립트: primary_monitor.sh

→ 스탠바이 노드 정보, 로그 파일 위치 변수 수정이 필요합니다.

#!/bin/bash

# --------------------------
# Primary 서버 모니터링 스크립트
# --------------------------

# 스탠바이 노드 정보
STANDBY_HOST="standby_host"

# 로그 파일 위치
LOG_FILE="/log_path/primary_monitor.log"

# 실패 카운트 초기화
FAIL_COUNT=0
PING_FAIL_COUNT=0

# --------------------------
# 로그 기록 함수
# --------------------------
log() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> $LOG_FILE
}

# --------------------------
# PostgreSQL 서비스 중지 함수
# --------------------------
stop_postgresql() {
  log "INFO: Stopping PostgreSQL service on primary node."
  pg_ctl stop
  if [ $? -eq 0 ]; then
    log "INFO: PostgreSQL service stopped successfully."
  else
    log "ERROR: Failed to stop PostgreSQL service."
  fi
}

# --------------------------
# 메인 모니터링 루프
# --------------------------
while true; do
  # 네트워크 연결 체크 (ping)
  ping -c 1 -W 2 $STANDBY_HOST > /dev/null 2>&1
  if [ $? -eq 0 ]; then
    PING_FAIL_COUNT=0
    log "INFO: Network ping to standby node is successful."
  else
    ((PING_FAIL_COUNT++))
    log "WARN: Network ping to standby node failed. Fail count: $PING_FAIL_COUNT"
  fi

  # PostgreSQL 프로세스 상태 체크
  pg_isready -h 127.0.0.1 -p 5432 > /dev/null 2>&1
  if [ $? -eq 0 ]; then
    FAIL_COUNT=0
    log "INFO: Primary PostgreSQL is healthy."
  else
    ((FAIL_COUNT++))
    log "WARN: Primary PostgreSQL health check failed. Fail count: $FAIL_COUNT"
  fi

  # 네트워크 단절 및 프라이머리 장애 조건 확인
  if [ $PING_FAIL_COUNT -ge 3 ]; then
    log "ERROR: Network isolation detected. Stopping PostgreSQL on primary node."
    stop_postgresql
    log "Terminating current script."
    exit 1
  elif [ $FAIL_COUNT -ge 3 ]; then
    log "ERROR: Primary PostgreSQL service failure detected. Stopping PostgreSQL on primary node."
    stop_postgresql
    log "Terminating current script."
    exit 1
  fi

  # 3초 대기
  sleep 3
done

 

▸ 실행 권한 추가: primary_monitor.sh

chmod +x primary_monitor.sh

 

▸ 백그라운드에서 쉘 실행: primary_monitor.sh

nohup ./primary_monitor.sh &

 

▸ 쉘 프로세스 확인: primary_monitor.sh

ps aux | grep primary_monitor.sh

 

2. Standby 서버 쉘 스크립트

[그림 2] Standby 서버 쉘 스크립트 프로세스

 

▸ 쉘 스크립트: standby_monitor.sh

→ 스탠바이 노드 정보, 로그 파일 위치 변수 수정이 필요합니다.

#!/bin/bash

# --------------------------
# Standby 서버 모니터링 스크립트
# --------------------------

# 프라이머리 노드 정보
PRIMARY_HOST="primary_host"
PRIMARY_PORT="5432"
PG_USER="replicator"

# 로그 파일 위치
LOG_FILE="/log_path/standby_monitor.log"

# 실패 카운트 초기화
FAIL_COUNT=0

# --------------------------
# 로그 기록 함수
# --------------------------
log() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> $LOG_FILE
}

# --------------------------
# Standby를 Primary로 프로모트하는 함수
# --------------------------
promote_standby() {
  log "INFO: Promoting Standby to Primary."
  pg_ctl promote
  if [ $? -eq 0 ]; then
    log "INFO: Successfully promoted Standby to Primary."
  else
    log "ERROR: Failed to promote Standby to Primary."
    exit 1
  fi
}

# --------------------------
# 메인 모니터링 루프
# --------------------------
while true; do
  # 프라이머리 노드에 간단한 쿼리 실행 (상태 확인)
  psql -h $PRIMARY_HOST -p $PRIMARY_PORT -U $PG_USER -c 'SELECT 1;' > /dev/null 2>&1
  
  if [ $? -eq 0 ]; then
    # 쿼리 성공 시 실패 카운트 초기화
    FAIL_COUNT=0
    log "INFO: Connection to primary node successful."
  else
    # 쿼리 실패 시 실패 카운트 증가
    ((FAIL_COUNT++))
    log "WARN: Connection to primary node failed. Fail count: $FAIL_COUNT"
  fi

  # 실패 횟수가 3번을 초과하면 스탠바이 노드를 프라이머리로 프로모트
  if [ $FAIL_COUNT -ge 3 ]; then
    log "ERROR: Failed to connect to primary node 3 times. Promoting standby to primary."
    promote_standby
    log "Terminating current script."
    exit 1
  fi

  # 5초 대기
  sleep 5
done

 

▸ 실행 권한 추가: standby_monitor.sh

chmod +x standby_monitor.sh

 

▸ 백그라운드에서 쉘 실행: standby_monitor.sh

nohup ./standby_monitor.sh &

 

▸ 쉘 프로세스 확인: standby_monitor.sh

ps aux | grep standby_monitor.sh

 

+ pg_hba.conf에서 trust가 아닌 경우 인증을 위해 .pgpass 생성이 필요합니다.

# Host:Port:Database:User:Password
echo "<primary_Host>:5432:postgres:replicator:replicator_password" >> ~/.pgpass
chmod 600 ~/.pgpass

 

3. 쉘 스크립트 테스트

▸ case 1: 네트워크 장애

[그림 3] 네트워크 장애 시 로그

 

▸ case 2: DBMS 장애

[그림 4] DBMS 장애 시 로그


이상으로 쉘 스크립트를 활용한 PostgreSQL 고가용성(HA) 구현에 대해 알아보았습니다. 이번 포스팅에서는 단순하지만 핵심적인 고가용성의 원리를 직접 구현해보며 Primary-Standby 구조의 장애 감지 및 처리 프로세스를 체험했습니다.

 

실제 운영 환경에서는 Patroni, repmgr과 같은 고급 HA 도구를 사용하는 것이 일반적입니다.

하지만, 이번 실습을 통해 HA의 핵심 원리를 이해하셨을 거라 생각합니다.


앞으로도 PostgreSQL과 관련된 심화된 내용들을 다룰 예정이니, 많은 관심과 응원 부탁드립니다.
감사합니다!