Database/PostgreSQL

PostgreSQL HA 구성 - 2. PGPool을 활용한 Load Balance 구현

갈색왜성 2018. 10. 5. 14:06
반응형

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을 사용하면서 정리한 장단점은 다음과 같다.


장점

단점

  • 무료. MIT License.
  • 다양한 기능 제공 (위에서 언급)

  • 매우 부실한 문서 관리 ; 몇몇 사용자 말에 따르면 필수적으로 들어가야 하는 설명도 누락되어 있다고 한다.
  • 설정이 어려움. (문서 부실화로 인한 부수적인 현상)
  • Linux 환경 제약.


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

PGPool Package를 설치하면 Config file의 Boilermake Code가 제공되고, 기존에 PostgreSQL 설정 환경에 따라 여러개를 제공하기 때문에 이 중에 하나를 복사한 후에 수정해서 사용하는 것이 좋다. 여기 를 참고하면 되고, 필자는 이전 Post에서 Streaming Replication 환경을 구축했기 때문에 pgpool.conf.sample-streaming을 pgpool.conf로 변경해서 사용했다. pool_hba.conf는 미래에 수정할 일이 생길 수도 있어 동일한 방법으로 만들어만 놨다.
...
[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할 수 있게 하였다.
설정 변경이 끝나고 pgpool service를 systemctl을 통해 시작시키면 되는데 그 전에 두 가지 일을 해야한다. 하나는 pgpool을 외부에서 접속할 때 사용하는 5433 Port에 대해 방화벽을 풀어야 하는 것이고, 다른 하나는 pgpool Log가 저장될 폴더를 만드는 일이다.
...
[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이 적용되었다.


참조