[PostgreSQL] PostgreSQL15 Streaming Replication 구성

1. Install Environment

1) Master Node

* OS : CentOS 7.9

* Engine : PostgreSQL 15.1

* port : 5432 (Default)

2) Slave Node

* OS : CentOS 7.9

* Engine : PostgreSQL 15.1

* port : 5432 (Default)

 

2. Config Procedure

1) Master Node

(1) Replication 유저 생성

postgres=# create role repl with replication password 'repl' login;
CREATE ROLE

postgres=# \du
                                   List of roles
Role name |                        Attributes                          | Member of
-----------+------------------------------------------------------------+-----------
postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
repl      | Replication                                                | {}

- 생성 후 \du 명령어를 통해 유저를 조회하면, Replication용 유저 'repl'이 생성됨을 확인할 수 있습니다.

 

(2) Replication용 Slot 생성

postgres=# select * from pg_create_physical_replication_slot('repl_slot_01');
 slot_name   | lsn
--------------+-----
repl_slot_01 |
(1 row)

postgres=# select slot_name, slot_type, active from pg_replication_slots;
 slot_name   | slot_type | active
--------------+-----------+--------
repl_slot_01 | physical  | f
(1 row)

- PostgreSQL에서는 Function을 사용할 때 Select문을 이용합니다.

- Physical Replication Slot은 Slave Node로 넘길 WAL 파일을 보관하는 용도로 사용됩니다.

- 또한 Master -> Slave로 basebackup 할 때 사용하게 됩니다.

- 생성된 slot은 pg_replication_slots에서 조회할 수 있습니다.

- 해당 과정에서는 Master / Slave 이중화 구성을 다루기에 slot은 1개만 생성합니다.

- 만약 여러 개의 Slave Node를 추가하고 싶다면, physical_replication_slot을 추가하면 됩니다.

(Node 1개 당 1개의 slot)

 

(3) postgresql.conf 수정

listen_addresses = '*' 

wal_level = replica
max_wal_senders = 10
max_replication_slots = 10

hot_standby = on
archive_mode = on
archive_command = 'cp %p /pg_archive/%f'

- 이전 버전의 PostgreSQL에서 Streaming Replication을 설정할 때 wal_keep_segments 파라미터를 설정했습니다.

- 하지만 wal_keep_segments는 PostgreSQL 13부터 사라진 파라미터 입니다.

- PostgreSQL 13 이후 버전에서 wal_keep_segments를 설정하고 DB를 재기동 할 경우 FATAL ERROR가 발생합니다.

- 파라미터 별 기능

  * listen_addresses : 외부에서의 접근을 가능하도록 합니다. ( *의 의미는 어디에서나 접근이 가능하다는 의미 )

  * wal_level : Slave Node에서 Read only 작업이 가능하도록 설정합니다.

  * max_wal_senders : WAL 파일을 전송할 수 있는 최대 서버 수를 지칭합니다.

  * max_replication_slots : Replication Slot 최대 개수를 설정합니다.

  * hot_standby : Slave Node에서 Read only 작업이 가능하도록 설정합니다.

  * archive_mode : 아카이브 모드를 활성화 합니다.

  * archive_command : %p는 경로, %s는 파일을 의미합니다.

     즉, %p /pg_archive/%f의 의미는 /pg_archive 디렉토리 아래의 파일들을 복사한다는 의미입니다.

 

(4) pg_hba.conf 수정

# "local" is for Unix domain socket connections only
...

# IPv4 local connections:
host all all 0.0.0.0/0 trust

# Allow replication connections from localhost, by a user with the
# replication privilege.
host replication repl ***.***.***.135/32 trust
host replication repl ***.***.***.139/32 trust

- 기존 설정 내용은 제외하고, 위의 항목들을 추가합니다.

- Replication privilege 항목 아래에 Master, Slave Node의 내용을 추가합니다.

- 만약, 여러 개의 Slave Node를 구성하고자 할 경우, 각 Node의 정보를 추가하면 됩니다.

 

(5) PostgreSQL Master Node 재기동

[postgres@localhost ~]$ pg_ctl restart -D /postgres/pgsql/data
waiting for server to shut down.... done
server stopped
waiting for server to start....2023-**-** 00:06:56.759 EST [7299] LOG: redirecting 
log output to logging collector process
2023-**-** 00:06:56.759 EST [7299] HINT: Future log output will appear in directory 
"/pg_log".
done
server started

 

2) Slave Node 공통 (Master Node 복제)

(1) 데이터 파일 삭제

[postgres@localhost pgsql]$ pwd
/postgres/pgsql

[postgres@localhost pgsql]$ rm -rf data

- 여기서 '데이터'란 $PG_HOME 아래의 conf 파일 들이 위치한 디렉토리를 의미합니다.

- 만약, Tablespace 등을 생성한 상태라면 해당 '데이터'도 모두 삭제해야 합니다.

     (삭제하지 않을 경우, basebackup 과정 중 데이터 디렉토리 관련 오류 발생)

 

(2) pg_basebackup 후 기동

[postgres@localhost bin]$ ./pg_basebackup -h ***.***.***.135 -D /postgres/pgsql/data 
-U repl -P -v -X stream -S repl_slot_01 -R
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/2000028 on timeline 1
pg_basebackup: starting background WAL receiver
22978/22978 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/2000138
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: syncing data to disk ...
pg_basebackup: renaming backup_manifest.tmp to backup_manifest
pg_basebackup: base backup completed

[postgres@localhost ~]$ postgres -D /postgres/pgsql/data &
[1] 3026
[postgres@localhost ~]$ 2023-**-** 00:59:10.509 EST [3026] LOG: redirecting log 
output to logging collector process
2023-02-07 00:59:10.509 EST [3026] HINT: Future log output will appear in directory 
"/pg_log"

- pg_basebackup 에 작성한 옵션들은 아래와 같습니다.

* -h : 접속 할 DB 서버 주소 (Master Node의 address)

* -D : PGDATA 경로 (관리의 용이성을 위해 Master Node와 동일하게 부여)

* -U : Master Node에 접속할 사용자 (Replication 유저를 사용)

* -v : 복제 과정을 자세히(verbose) 출력합니다.

* -P : 작업 진행과정을 출력합니다.

* -X : basebackup 진행 중 필요한 WAL파일을 백업하는 방법을 명시합니다.

     -> 복제 중 생성된 WAL 파일 포함

     -> 여기서 -X stream의 의미는, 복제 중 Master Node에 추가로 연결하여 병렬로 WAL 파일을 Streaming 한다는 의미

* -S : WAL Streaming을 위한 Replication Slot 설정 (-S 옵션을 사용하기 위해 -X 옵션이 선행되어야 함)

* -R : postgresql.auto.conf 파일 생성 여부

     -> PostgreSQL 12 이전 버전에서는 recovery.conf 파일이 생성됨

     -> PostgreSQL 12 이후 버전에서는 recovery.conf 파일이 사라지고 postgresql.auto.conf 파일로 대체됨

 

(3) postgresql.auto.conf 파일 확인

[postgres@localhost data]$ cat postgresql.auto.conf

# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=repl passfile=''/postgres/.pgpass'' channel_binding=disable 
host=***.***.***.135 port=5432 sslmode=disable sslcompression=0 sslsni=1 
ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres 
target_session_attrs=any'
primary_slot_name = 'repl_slot_01'

- Master Node에 관한 정보가 적혀있습니다.

- 해당 파일은 절대 수정하시면 안됩니다.

 

3) Replication 상태 조회

(1) Replication 상태 조회 (Master Node)

postgres=# select * from pg_stat_activity where usename='repl';
datid | datname | pid | leader_pid | usesysid | usename | application_name | 
client_addr | client_hostname | client_port | bac
kend_start | xact_start | query_start | 
state_change | wait_event_type | wait_event | state
| backend_xid | backend_xmin | query_id | query 
| backend_type
-------+---------+------+------------+----------+---------+------------------+------
----------+-----------------+-------------+------------
-------------------+------------+-------------------------------+-------------------
------------+-----------------+---------------+--------
+-------------+--------------+----------+-------------------------------------------
-----------------+--------------
 | | 2355 | | 24576 | repl | walreceiver | 
192.168.56.139 | | 40250 | 2023-**-**
00:59:11.742077-05 | | 2023-**-** 00:59:11.745696-05 | 2023-**-**
00:59:11.745746-05 | Activity | WalSenderMain | active
| | | | START_REPLICATION SLOT "repl_slot_01" 
0/3000000 TIMELINE 1 | walsender
(1 row)
postgres=# exit


[postgres@localhost ~]$ ps -ef | grep post
root 1644 1 0 00:54 ? 00:00:00 /usr/libexec/postfix/master -w
postfix 1660 1644 0 00:54 ? 00:00:00 pickup -l -t unix -u
postfix 1661 1644 0 00:54 ? 00:00:00 qmgr -l -t unix -u
root 2248 2193 0 00:56 pts/0 00:00:00 su - postgres
postgres 2249 2248 0 00:56 pts/0 00:00:00 -bash
postgres 2289 2249 0 00:56 pts/0 00:00:00 postgres -D /postgres/pgsql/data
postgres 2290 2289 0 00:56 ? 00:00:00 postgres: logger
postgres 2291 2289 0 00:56 ? 00:00:00 postgres: checkpointer
postgres 2292 2289 0 00:56 ? 00:00:00 postgres: background writer
postgres 2294 2289 0 00:56 ? 00:00:00 postgres: walwriter
postgres 2295 2289 0 00:56 ? 00:00:00 postgres: autovacuum launcher
postgres 2296 2289 0 00:56 ? 00:00:00 postgres: archiver last was 
000000010000000000000003.00000028.backup
postgres 2297 2289 0 00:56 ? 00:00:00 postgres: logical replication 
launcher
postgres 2355 2289 0 00:59 ? 00:00:00 postgres: walsender repl 
192.168.56.139(40250) streaming 0/4000148
postgres 2522 2249 0 01:04 pts/0 00:00:00 ps -ef
postgres 2523 2249 0 01:04 pts/0 00:00:00 grep --color=auto post

- Master Node에서는 pg_stat_activity 를 조회하거나, OS단에서 프로세스를 통해 Replication 상태를 확인할 수 있습니다.

     (추가, \x 옵션을 준 다음 pg_stat_activity를 조회한다면 가독성이 증가할 것입니다.)

 

(2) Replication 상태 조회 (Slave Node)

postgres=# select * from pg_stat_wal_receiver;
pid | status | receive_start_lsn | receive_start_tli | written_lsn | 
flushed_lsn | received_tli | last_msg_send_time |
last_msg_receipt_time | latest_end_lsn | latest_end_time | 
slot_name | sender_host | sender_port |
 
conninfo
------+-----------+-------------------+-------------------+-------------+-----------
--+--------------+-------------------------------+-----
--------------------------+----------------+-------------------------------+--------
------+----------------+-------------+-----------------
------------------------------------------------------------------------------------
-------------------------------------------------------
------------------------------------------------------------------------------------
------------------------------------------------
3031 | streaming | 0/3000000 | 1 | 0/4000060 | 0/4000060 
| 1 | 2023-**-** 00:59:42.008635-05 | 2023
-**-** 00:59:42.009887-05 | 0/4000060 | 2023-**-** 00:59:11.745986-05 | 
repl_slot_01 | ***.***.***.135 | 5432 | user=repl passfi
le=/postgres/.pgpass channel_binding=disable dbname=replication host=***.***.***.135 
port=5432 fallback_application_name=walreceiver sslmode
=disable sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 
gssencmode=disable krbsrvname=postgres target_session_attrs=any
(1 row)
postgres=# exit


[postgres@localhost ~]$ ps -ef | grep post
root 1661 1 0 00:54 ? 00:00:00 /usr/libexec/postfix/master -w
postfix 1688 1661 0 00:54 ? 00:00:00 pickup -l -t unix -u
postfix 1689 1661 0 00:54 ? 00:00:00 qmgr -l -t unix -u
root 2932 2887 0 00:56 pts/1 00:00:00 su - postgres
postgres 2933 2932 0 00:56 pts/1 00:00:00 -bash
postgres 3026 2933 0 00:59 pts/1 00:00:00 postgres -D /postgres/pgsql/data
postgres 3027 3026 0 00:59 ? 00:00:00 postgres: logger
postgres 3028 3026 0 00:59 ? 00:00:00 postgres: checkpointer
postgres 3029 3026 0 00:59 ? 00:00:00 postgres: background writer
postgres 3030 3026 0 00:59 ? 00:00:00 postgres: startup recovering 
000000010000000000000004
postgres 3031 3026 0 00:59 ? 00:00:00 postgres: walreceiver streaming 
0/4000148
postgres 3117 2933 0 01:03 pts/1 00:00:00 ps -ef
postgres 3118 2933 0 01:03 pts/1 00:00:00 grep --color=auto post

- Slave Node에서는 pg_stat_wal_receiver 를 조회하거나, OS단에서 프로세스를 통해 Replication 상태를 확인할 수 있습니다.

     (추가, \x 옵션을 준 다음 pg_stat_wal_receiver를 조회한다면 가독성이 증가할 것입니다.)

 

4) Replication 작동 검증

(1) Master Node에서 TEST용 유저 생성

postgres=# \du
                                   List of roles
Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
repl      | Replication                                                | {}

postgres=# create user test with superuser password 'test';
CREATE ROLE

postgres=# \du
                                   List of roles
Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
repl      | Replication                                                | {}
test      | Superuser                                                  | {}

 

(2) Slave Node에서 TEST 유저 확인

postgres=# \du
                                   List of roles
Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
repl      | Replication                                                | {}
test      | Superuser                                                  | {}

 

(3) Master Node에서 TEST 유저 드랍

postgres=# drop user test;
DROP ROLE

postgres=# \du
                                   List of roles
Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
repl      | Replication                                                | {}

 

(4) Slave Node에서 TEST 유저 드랍 확인

postgres=# \du
                                   List of roles
Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
repl      | Replication                                                | {}

Designed by JB FACTORY