PostgreSQL HA 구성 - 2. PGPool을 활용한 Load Balance 구현
PGPool Overview
PostgreSQL의 기능 확장을 위해 많이 사용되는 Middle Ware로 Pool이라는 이름에서 알 수 있듯이 최초 개발 목적은 Connection Pooling을 위해 만들어 졌지만, 이후 기능이 확장되면서 PostgreSQL DB Clustering을 위해 자주 사용된다. PGPool이 제공하는 기능들을 대략적으로 요약하자면 다음과 같다.
- Connection Pool 관리 : PostgreSQL은 하나의 명령을 수행할 떄마다 별도로 Connection을 만들어서 사용하게 되는데, 이 때 사용하는 Resource가 상대적으로 크다. PGPool은 이런 Connection들을 재사용하게끔 해서 전체 성능을 향상시킨다. 또, 동시에 지원 가능한 Connection 수의 최대치를 넘는 요청에 대해 무조건 Reject하지 않고 Queue에서 대기하고 있다가 처리될 수 있도록 한다.
- Replication : PGPool에서 자체적으로 Replication 기능을 제공한다. 하지만, 최신 문서를 보면 자기네가 제공하는 것보다 PostgreSQL에서 자체적으로 제공하는 Streaming Replication 사용을 권장한다.
- Load Balancing : 여러 대의 DB Server가 Clustering 되어 있고, 이들이 Replication 기능을 통해 같은 Data를 가지고 있을 때 Data 조회 명령을 여러 Server에 걸쳐 분산시킴으로써 전체 Server에 부하를 나눌 수 있다.
- Auto Failover & Failback : Master-Slave Mode에서 Master Server에 문제가 생겼을 때 Slave Server 중 1대가 Master 역할을 수행하는 Fail-over 기능을 제공하고, 그 역인 Fail-Back 기능도 제공한다.
2018년 10월 5일 기준으로 4.0이 Release되어 있는데 4.0은 공식 문서가 Release되지 않은 것 같고, 공식 문서는 3.7.5가 가장 최신 버전이다. 아울러 3.3.x까지는 PDF문서가 있었고, 3.5.x까지는 한 번에 볼 수 있는 HTML 문서가 있어서 한 눈에 내용을 파악하기가 쉬었는데 그 이후에는 웹에서 한 페이지씩 읽어야 하는 형태로 제공되고 있어서 다소 불편하다. 그리고 한국에서 PostgreSQL이 많이 사용되지 않아서 그런지 PGPool 한국어 자료가 그리 많지 않다. 의외로 일본에서 많이 사용되는 지 일본어 자료는 많이 보인다.
PostgreSQL로 HA를 구성하는데 여러 Tool이 있는데 PGPool 밖에 사용하지 않아 다른 제푸들과 비교는 못하겠고, PGPool을 사용하면서 정리한 장단점은 다음과 같다.
장점 |
단점 |
|
|
Installing PGPool
PGPool은 설치 및 환경 설정 시에 사용자 친화적이라 할 수는 없지만, 매우 다행히 Redhat 계열의 Linux 사용자들은 Yum repository를 활용해서 다소 쉽게 설치할 수 있다. YUM을 이용한 설치에 대한 내용을 PGPool Wiki와 공식 문서를 참고하면 된다. 그리고 Release된 PGPool 버전은 PGPool Yum Repository를 확인하면 되고, 2018년 10월 5일 기준으로 4.0이 최신 버전이다. 필자는 좀 이전에 환경을 설정해서 3.7.5를 사용하였고, 혹시 Debug 정보가 필요할 지도 몰라서 debuginfo pacakge를 설치하였다.
... [root@ha-test-1 /]# yum install http://www.pgpool.net/yum/rpms/3.7/redhat/rhel-7-x86_64/pgpool-II-pg96-debuginfo-3.7.5-1pgdg.rhel7.x86_64.rpm ... ... ================================================================================================================================================ Package Arch Version Repository Size ================================================================================================================================================ Installing: pgpool-II-pg96-debuginfo x86_64 3.7.5-1pgdg.rhel7 /pgpool-II-pg96-debuginfo-3.7.5-1pgdg.rhel7.x86_64 9.7 M Transaction Summary ================================================================================================================================================ Install 1 Package ... ... Installing : pgpool-II-pg96-debuginfo-3.7.5-1pgdg.rhel7.x86_64 1/1 Verifying : pgpool-II-pg96-debuginfo-3.7.5-1pgdg.rhel7.x86_64 1/1 Installed: pgpool-II-pg96-debuginfo.x86_64 0:3.7.5-1pgdg.rhel7 Complete!
그리고 PGPool-Extension도 설치한다. 아래 EXTENSION은 PostgreSQL의 EXTENSION 기능 추가로 활용하면 되는데 대략적인 기능은 다음과 같고, 현 시점에서는 그냥 설치만 하고, 이런게 있다 정도만 알아두자. 여러 문서들을 보고 추정하기에 이후에 사용할 것 같다.
- pgpool-recovery : Online Recovery를 위한 Extension.
- pgpool-adm : PCP Command들을 실행하기 위한 Extention.
- pgpool-regclass : 필자가 설치한 PostgreSQL환경이 9.6이라 그런지 PGPool 설치시 설치가 되지는 않았다. 이 Extension은 9.4 이하 버젼의 PostgreSQL을 PGPool로 연결할 때 Table명 중복 시 예외 처리를 위한 Extension이다.
... [root@ha-test-2 /]# yum install http://www.pgpool.net/yum/rpms/3.7/redhat/rhel-7-x86_64/pgpool-II-pg96-extensions-3.7.5-1pgdg.rhel7.x86_64.rpm ... ... ================================================================================================================================================ Package Arch Version Repository Size ================================================================================================================================================ Installing: pgpool-II-pg96-extensions x86_64 3.7.5-1pgdg.rhel7 /pgpool-II-pg96-extensions-3.7.5-1pgdg.rhel7.x86_64 35 k Installing for dependencies: pgpool-II-96 x86_64 3.7.5-1.rhel7 pgdg96 552 k Transaction Summary ================================================================================================================================================ Install 1 Package (+1 Dependent package) ... Installed: pgpool-II-pg96-extensions.x86_64 0:3.7.5-1pgdg.rhel7 Dependency Installed: pgpool-II-96.x86_64 0:3.7.5-1.rhel7 Complete!
여담으로 공식 문서를 보면 이렇게 되어 있다 - "pg96 means PostgreSQL
9.5." . 마치 PostgreSQL 9.6을 위해 pgpool-II-pg97이 있을 것처럼 생각하게 만드는 문구지만... repository를 보면 확인할 수 있듯이 'pg97' 따위는 없다. 몇몇 분들이 PGPool도 공식 문서에 대해 꽤나 힐난을 했는데 이유를 쉽게 알 수 있다.
rpm 명령어를 이용해 설치된 내용들을 확인하면 다음과 같다. 추후에 기능 확장을 위해 수정이 필요할 수 있기 때문에 해당 파일들의 위치를 확인해 놓는 것이 좋다.
... [root@ha-test-2 /]# rpm -ql pgpool-II-96 /etc/pgpool-II-96/pcp.conf.sample /etc/pgpool-II-96/pgpool.conf.sample /etc/pgpool-II-96/pgpool.conf.sample-logical /etc/pgpool-II-96/pgpool.conf.sample-master-slave /etc/pgpool-II-96/pgpool.conf.sample-replication /etc/pgpool-II-96/pgpool.conf.sample-stream /etc/pgpool-II-96/pool_hba.conf.sample /etc/sysconfig/pgpool-II-96 /usr/lib/systemd/system/pgpool-II-96.service /usr/lib/tmpfiles.d/pgpool-II-96.conf /usr/pgpool-9.6 /usr/pgpool-9.6/bin/pcp_attach_node /usr/pgpool-9.6/bin/pcp_detach_node /usr/pgpool-9.6/bin/pcp_node_count /usr/pgpool-9.6/bin/pcp_node_info /usr/pgpool-9.6/bin/pcp_pool_status /usr/pgpool-9.6/bin/pcp_proc_count /usr/pgpool-9.6/bin/pcp_proc_info /usr/pgpool-9.6/bin/pcp_promote_node /usr/pgpool-9.6/bin/pcp_recovery_node /usr/pgpool-9.6/bin/pcp_stop_pgpool /usr/pgpool-9.6/bin/pcp_watchdog_info /usr/pgpool-9.6/bin/pg_md5 /usr/pgpool-9.6/bin/pgpool /usr/pgpool-9.6/bin/pgpool_setup /usr/pgpool-9.6/bin/watchdog_setup /usr/pgpool-9.6/lib/libpcp.so.1 /usr/pgpool-9.6/lib/libpcp.so.1.0.0 /usr/pgpool-9.6/share/pgpool-II-pg96-libs.conf /usr/pgpool-9.6/share/pgpool-II/insert_lock.sql /usr/pgpool-9.6/share/pgpool-II/pgpool.pam /usr/share/doc/pgpool-II-96-3.7.5 /usr/share/doc/pgpool-II-96-3.7.5/AUTHORS /usr/share/doc/pgpool-II-96-3.7.5/ChangeLog /usr/share/doc/pgpool-II-96-3.7.5/INSTALL /usr/share/doc/pgpool-II-96-3.7.5/NEWS /usr/share/doc/pgpool-II-96-3.7.5/README /usr/share/doc/pgpool-II-96-3.7.5/TODO /usr/share/licenses/pgpool-II-96-3.7.5 /usr/share/licenses/pgpool-II-96-3.7.5/COPYING /var/run/pgpool-II-96 ... [root@ha-test-2 /]# rpm -ql pgpool-II-pg96-extensions /usr/pgsql-9.6/lib/pgpool-recovery.so /usr/pgsql-9.6/lib/pgpool_adm.so /usr/pgsql-9.6/share/extension/pgpool-recovery.sql /usr/pgsql-9.6/share/extension/pgpool_adm--1.0.sql /usr/pgsql-9.6/share/extension/pgpool_adm.control /usr/pgsql-9.6/share/extension/pgpool_recovery--1.1.sql /usr/pgsql-9.6/share/extension/pgpool_recovery.control
pgpool.conf Configuration
... [root@ha-test-1 /]# cp /etc/pgpool-II-96/pgpool.conf.sample-streaming /etc/pgpool-II-96/pgpool.conf [root@ha-test-1 /]# cp /etc/pgpool-II-96/pool_hba.conf.sample /etc/pgpool-II-96/pool_hba.conf ...
이제는 pgpool.conf를 수정해야 한다. 보시면 알겠지만 기능을 많이 제공하는 대신 설정 사항이 무지막지 하게 많다. 전체 파일 중 수정한 내용은 아래와 같다. 그리고 현 시점에서 PCP 설정은 하지 않았다.
... #------------------------------------------------------------------------------ # CONNECTIONS #------------------------------------------------------------------------------ # - pgpool Connection Settings - listen_addresses = '*' port = 5433 socket_dir = '/var/run/postgresql' ... # - Backend Connection Settings - backend_hostname0 = '16.8.35.227' backend_port0 = 5432 backend_weight0 = 1 backend_data_directory0 = '/var/lib/pgsql/9.6/data' backend_flag0 = 'ALLOW_TO_FAILOVER' backend_hostname1 = '16.8.35.228' backend_port1 = 5432 backend_weight1 = 1 backend_data_directory1 = '/var/lib/pgsql/9.6/data' backend_flag1 = 'ALLOW_TO_FAILOVER' ... #------------------------------------------------------------------------------ # FILE LOCATIONS #------------------------------------------------------------------------------ pid_file_name = '/var/run/pgpool-II-96/pgpool.pid' logdir = '/usr/pgpool-9.6/log' ... #------------------------------------------------------------------------------ # LOAD BALANCING MODE #------------------------------------------------------------------------------ load_balance_mode = on ... #------------------------------------------------------------------------------ # MASTER/SLAVE MODE #------------------------------------------------------------------------------ master_slave_mode = on master_slave_sub_mode = 'stream' ... # - Streaming - sr_check_period = 5 sr_check_user = 'postgres' sr_check_password = 'postgres' ...
- pgpool Connection Settings : 외부에서 pgpool로 접속할 때 사용할 접속 정보. PGPool을 통해 접속할 떄는 5433을 사용하게 했고, Unix Domain Socket을 사용할 때는 Default Path를 통해 통신이 이루어지게 했다
- Backend Connection Setting : Clustering에 포함된 PostgreSQL Server Connection 정보와 Data File path를 알린다. 뒤에 붙는 Postfix 숫자에 의해 서버들을 구분한다. 여기서 설정하는 backend-weight 값에 의해 Load Balance 시에 Request 들이 분산 비율이 결정된다. 필자는 0번 서버와 1번 서버를 동일하게 1로 설정했기 때문에 각 서버는 1:1로 Request를 받게 된다. 그리고, 추후 Failover 기능을 추가하기 위해 backend_flag을 'ALLOW_TO_FAILOVER'로 설정했다.
- FILE LOCATIONS : RHEL7에서는 pid file 이름은 기본값을 설정하면 되고, Log Folder은 각자 편한 위치에 설정하면 된다. 단, Log Folder는 직접 만들어 줘야 한다. (자동으로 만들어지지 않는다.) 그리고 이 Log Folder에는 pgpool_status 라는 파일 1개만 기본적으로 생성될 뿐이다.
- LOAD BALANCING MODE : load balance 기능 사용을 위해 load_balance_mode를 'on'으로 변경한다.
- MASTER/SLAVE MODE : 현재 Streaming Replication을 사용하고 있기 때문에 master_slave_mode는 'on'으로, master_slave_sub_mode는 'stream'으로 한다.
- Streaming : Streaming Replication 상태 체크를 위한 설정이다. 5초마다 postgres 계정으로 상태 Check할 수 있게 하였다.
... [root@ha-test-1 /]$ firewall-cmd --zone=public --add-port=5433/tcp --permanent // 5433 Port에 대해 방화벽 예외 설정 success [root@ha-test-1 /]$ firewall-cmd --reload // 수정된 방화벽 설정 내용 반영 success [root@ha-test-2 /]$ mkdir /usr/pgpool-9.6/log // Log Folder 생성 ... [root@ha-test-2 /]$ systemctl enable pgpool-II-96.service Created symlink from /etc/systemd/system/multi-user.target.wants/pgpool-II-96.service to /usr/lib/systemd/system/pgpool-II-96.service. [root@ha-test-2 /]$ systemctl start pgpool-II-96.service [root@ha-test-2 log]$ systemctl status pgpool-II-96.service ● pgpool-II-96.service - PGPool-II Middleware Between PostgreSQL Servers And PostgreSQL Database Clients Loaded: loaded (/usr/lib/systemd/system/pgpool-II-96.service; enabled; vendor preset: disabled) Active: active (running) since 수 2018-10-10 13:19:17 KST; 4s ago Process: 2100 ExecStop=/usr/pgpool-9.6/bin/pgpool -f /etc/pgpool-II-96/pgpool.conf -m fast stop (code=exited, status=0/SUCCESS) Main PID: 2215 (pgpool) CGroup: /system.slice/pgpool-II-96.service ├─2215 /usr/pgpool-9.6/bin/pgpool -f /etc/pgpool-II-96/pgpool.conf -n ├─2225 pgpool: wait for connection request ... ├─2255 pgpool: wait for connection request ├─2256 pgpool: wait for connection request ├─2257 pgpool: wait for connection request ├─2260 pgpool: PCP: wait for connection request ├─2261 pgpool: worker process ├─2263 pgpool: health check process(0) └─2264 pgpool: health check process(1) 10월 10 13:19:17 ha-test-2 systemd[1]: Started PGPool-II Middleware Between PostgreSQL Servers And PostgreSQL Database Clients. 10월 10 13:19:17 ha-test-2 systemd[1]: Starting PGPool-II Middleware Between PostgreSQL Servers And PostgreSQL Database Clients... 10월 10 13:19:17 ha-test-2 pgpool[2215]: 2018-10-10 13:19:17: pid 2215: LOG: Backend status file /usr/pgpool-9.6/log/pgpool_status ...ot exist 10월 10 13:19:17 ha-test-2 pgpool[2215]: 2018-10-10 13:19:17: pid 2215: LOG: Setting up socket for 0.0.0.0:5433 10월 10 13:19:17 ha-test-2 pgpool[2215]: 2018-10-10 13:19:17: pid 2215: LOG: Setting up socket for :::5433 10월 10 13:19:17 ha-test-2 pgpool[2215]: 2018-10-10 13:19:17: pid 2215: LOG: find_primary_node_repeatedly: waiting for finding a primary node 10월 10 13:19:17 ha-test-2 pgpool[2215]: 2018-10-10 13:19:17: pid 2215: LOG: find_primary_node: checking backend no 0 10월 10 13:19:17 ha-test-2 pgpool[2215]: 2018-10-10 13:19:17: pid 2215: LOG: find_primary_node: primary node id is 0 10월 10 13:19:17 ha-test-2 pgpool[2215]: 2018-10-10 13:19:17: pid 2215: LOG: pgpool-II successfully started. version 3.7.5 (amefuriboshi) Hint: Some lines were ellipsized, use -l to show in full.
systemctl status를 통해 pgpool service 상태를 확인해보면 정상적으로 서비스가 시작된 것을 확인할 수 있다. (참고로 했던 다른 사례들을 보면 위의 Log 중에서 standby node도 찾았다는 Message가 나오던데 이상하게 그 내용을 확인할 수는 없었다. 그래서 설정이 잘못 됐는 지 확인을 여러 번 했는데, Test 결과는 정상적으로 나와서 위와 같은 로그도 별 문제 없다고 스스로 납득 시키고 있다.)
Test
pgpool에서 제공하는 'show pool_node' 명령어를 실행시켜 보면 설정한 Load Balance 상태를 확인할 수 있다. psql을 통해 pgpool에 접속해서 명령뮨을 실행 시켰을 때 아래와 같은 결과를 보여주고 있다. 여기서 lb_weight Column이 각 서버의 Load Balance 비중을 나타내는 값이고 각각 0.5씩 할당되고 있는 것을 확인할 수 있다. (Remark : 'select_cnt' coulmn의 값은 이 비율과 상이할 수 있다.)
... [brown@ha-test-1 ~]$ psql -h localhost -p 5433 -U postgres psql (9.6.10) 도움말을 보려면 "help"를 입력하십시오. postgres=# show pool_nodes; node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay ---------+-------------+------+--------+-----------+---------+------------+-------------------+------------------- 0 | 16.8.35.227 | 5432 | up | 0.500000 | primary | 0 | false | 0 1 | 16.8.35.228 | 5432 | up | 0.500000 | standby | 0 | true | 0 (2개 행)
주의할 사항은 위의 결과는 pgpool에 접속해서 얻은 결과라는 사실이다. 만약 개별 Postgresql Server에 접속해서 'show pool_nodes' 결과를 조회하려고 하면 실행되지 않는다. (접속하려는 Port Number에 주목하자.)
... [brown@ha-test-1 ~]$ psql -h localhost -p 5432 -U postgres psql (9.6.10) 도움말을 보려면 "help"를 입력하십시오. postgres=# show pool_nodes; 오류: 알 수 없는 환경 매개 변수 이름: "pool_nodes" ...
Debugging 사례
위에 언급된 'show pool_nodes;' 결과값 중 status field 값이 unused나 down으로 나오게 되면 Standby Server가 Down이나 Unused로 나올 떄가 있었다. 하지만 Standby Server는 정상 동작 중이었고, Streaming Replication도 문제 없었다. 여러 사례들을 찾던 중 PGPool log 폴더에 생성되는 pgpool_status 값이 갱신이 안되면서 이러한 현상이 발생한다고 하는 경험담이 있어, 해당 파일을 삭제한 후에 다시 Restart하니 정상적으로 Load Balancing이 적용되었다.