LabHub
배우기 러닝패스 코스

PostgreSQL Replication and Promotion

Stand Up Replication and Promote It

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

주 서버와 대기 서버를 한 파드 안에서 직접 세우고, 복제를 붙이고, 승격까지 해 봅니다. 마지막에는 타임라인이 갈라지는 것을 눈으로 봅니다.

왜 중요한가

"HA 를 구축했다" 는 말은 대개 한 번도 장애 조치를 해 본 적 없다는 뜻입니다. 설정은 맞는데 막상 승격해 보면 대기 서버가 안 따라와 있거나, 승격은 됐는데 애플리케이션이 옛 주소를 보고 있거나, 옛 주 서버를 되붙이려다 데이터를 망칩니다.

이 실습은 그 한 바퀴를 미리 돌아 봅니다.

환경

이 파드는 postgres 계정으로 돕니다(실습 파드는 capability 가 없어서 su 로 사용자를 바꿀 수 없습니다). 그래서 susudo 없이 그냥 치면 됩니다.

psql                      주 서버(5432)에 바로 붙습니다
psql -h 127.0.0.1 -p 5433 대기 서버

대기 서버에는 -h 127.0.0.1 을 꼭 붙이세요. 이 환경은 유닉스 소켓 디렉터리를 홈 아래로 옮겨 두었습니다(컨테이너 런타임이 /run 을 tmpfs 로 덮어써서 기본 경로가 사라지기 때문입니다).

단계

  1. 주 서버를 복제 가능하게
  2. 복제 계정과 슬롯
  3. 베이스백업 → /var/lib/postgresql/standby
  4. 대기 서버를 5433 으로 기동
  5. 복제 확인 → /root/db/05-repl.txt
  6. 읽기 전용 확인 → /root/db/06-readonly.txt
  7. 승격
  8. 타임라인 비교 → /root/db/08-timeline.txt

참고

주 서버를 복제 가능하게

주 서버를 복제 가능하게

wal_level, max_wal_senders, max_replication_slots, hot_standbyalter system set 으로 바꾸고 재시작합니다. 재시작은 pg_ctl -D /var/lib/postgresql/data -w -t 40 restart -l /var/log/postgresql.log. show wal_level 이 replica 여야 합니다.

복제 계정과 슬롯

복제 계정과 슬롯

create role rep with replication login password 'rep' 로 계정을 만들고, select pg_create_physical_replication_slot('s1') 로 슬롯을 만듭니다. 슬롯이 없으면 대기 서버가 잠깐 끊겼다 돌아왔을 때 필요한 WAL 이 이미 사라져 복제가 깨집니다.

베이스백업

베이스백업 → /var/lib/postgresql/standby

PGPASSWORD=rep pg_basebackup -h 127.0.0.1 -U rep -D /var/lib/postgresql/standby -X stream -S s1 -R. -R 이 standby.signal 과 primary_conninfo 를 자동으로 만들어 줍니다 — 그 파일 하나가 '너는 대기 서버다' 라는 표시입니다.

대기 서버를 5433 으로

대기 서버를 5433 으로 기동

echo "port=5433" >> /var/lib/postgresql/standby/postgresql.auto.conf 뒤에 pg_ctl -D /var/lib/postgresql/standby -l /var/log/labhub/standby.log -w -t 40 start. 확인은 psql -h 127.0.0.1 -p 5433 -tAc "select pg_is_in_recovery()" 가 t 여야 합니다.\n\n**-h 127.0.0.1 을 꼭 붙이세요.** 이 환경은 유닉스 소켓 디렉터리를 옮겨 두어서, 포트만 바꾸면 소켓 경로를 못 찾습니다.

정말 복제되는지

복제 확인 → /root/db/05-repl.txt

주 서버에 create table if not exists ha(id int)insert into ha values (42) 를 하고, 2초 뒤 대기 서버에서 같은 행이 보이는지 확인합니다. 그리고 select state, replay_lag from pg_stat_replication 결과를 /root/db/05-repl.txt 에 저장하세요. state 가 streaming 이어야 합니다.

대기 서버는 왜 쓰기를 거부하나

읽기 전용 확인 → /root/db/06-readonly.txt

대기 서버에 insert into ha values (1) 을 해 보고 오류 메시지를 /root/db/06-readonly.txt 에 그대로 저장하세요. 대기 서버는 스스로 WAL 을 만들 수 없어서 쓰기를 받을 수 없습니다 — 설정이 아니라 구조입니다.

승격

승격

pg_ctl -D /var/lib/postgresql/standby promote 로 승격합니다. pg_is_in_recovery() 가 f 로 바뀌고 쓰기가 가능해집니다. 승격 뒤 insert 를 한 번 해 보세요.

타임라인이 갈라진다

타임라인 비교 → /root/db/08-timeline.txt

승격하면 새 서버는 타임라인 2로 갈라집니다. 두 서버의 WAL 파일 이름을 비교해 /root/db/08-timeline.txt 에 두 줄로 적으세요:\npsql -h 127.0.0.1 -p 5432 -tAc "select pg_walfile_name(pg_current_wal_lsn())" 와 5433 것. 파일 이름 앞 8자리가 타임라인입니다(00000001 / 00000002).\n\n이게 옛 주 서버를 그냥 되붙일 수 없는 이유입니다 — 두 서버가 같은 지점에서 서로 다른 역사를 쓰기 시작했습니다. 되붙이려면 pg_rewind 로 갈라진 지점까지 되감아야 합니다.