Patroni 및 HAProxy를 사용하는 고가용성 PostgreSQL 클러스터

이 기사는 처음에 JFrog 블로그에 게시되었습니다.

소개:



고가용성은 오늘날의 아키텍처와 최신 시스템의 중요한 부분입니다. 이 블로그 게시물은 Patroni 및 HAProxy를 사용하여 고가용성 PostgreSQL 클러스터를 생성하는 가능한 접근 방식을 설명합니다. 고가용성은 PostgreSQL DB 노드가 오류 발생 시 사용 가능한 다른 PostgreSQL DB 노드로 작업을 자동으로 다시 라우팅할 수 있도록 합니다. 이 블로그는 어떤 제품과도 연결되어 있지 않고 제 개인적인 경험과 연결되어 있다는 점에 유의하는 것이 중요합니다.

설명:



이 문서는 Patroni 및 HAProxy를 사용하여 고가용성 PostgreSQL 클러스터 아키텍처를 생성하는 방법에 대한 단계별 가이드입니다.

Patroni는 Postgres 구성을 관리하는 오픈 소스 Python 패키지입니다. 복제, 백업 및 복원과 같은 작업을 처리하도록 구성할 수 있습니다.

Etcd는 Postgres 클러스터의 상태를 저장하는 데 사용되는 내결함성 분산 키-값 저장소입니다. Patroni를 사용하면 모든 Postgres 노드가 etcd를 사용하여 Postgres 클러스터를 가동 및 실행합니다. 프로덕션에서는 etcd 노드 하나가 실패해도 Postgres 서버에 영향을 미치지 않도록 더 큰 etcd 클러스터를 사용하는 것이 좋습니다.

Postgres 클러스터가 설정되면 클러스터의 어떤 서버가 마스터인지에 관계없이 마스터에 연결할 방법이 필요합니다. 여기에서 HAProxy가 개입합니다. 모든 Postgres 클라이언트/응용 프로그램은 클러스터의 마스터 노드에 대한 연결을 제공하는 HAProxy에 연결됩니다.

HAProxy는 TCP 및 HTTP 애플리케이션을 위한 오픈 소스 고성능 로드 밸런서 및 역방향 프록시입니다. HAProxy는 로드를 분산하고 웹 사이트 및 애플리케이션의 성능을 향상시키는 데 사용할 수 있습니다.

개요:





건축물:



OS: 우분투 20.04

포스트그레스 버전: 12

머신: node1 IP: 역할: Postgresql, Patroni

머신: node2 IP: 역할: Postgresql, Patroni

머신: node3 IP: 역할: Postgresql, Patroni

시스템: etcdnode IP: 역할: etcd

머신: haproxynode IP: 역할: HA 프록시

단계별 지침 가이드





1단계 - node1, node2, node3 설정:




sudo apt update

sudo hostnamectl set-hostname nodeN

sudo apt install net-tools

sudo apt install postgresql postgresql-server-dev-12

sudo systemctl stop postgresql

sudo ln -s /usr/lib/postgresql/12/bin/* /usr/sbin/

sudo apt -y install python python3-pip

sudo apt install python3-testresources   

sudo pip3 install --upgrade setuptools 

sudo pip3 install psycopg2

sudo pip3 install patroni

sudo pip3 install python-etcd


2단계 – etcdnode 설정:




sudo apt update

sudo hostnamectl set-hostname etcdnode

sudo apt install net-tools

sudo apt -y install etcd 


3단계 – haproxynode 설정:




sudo apt update

sudo hostnamectl set-hostname haproxynode

sudo apt install net-tools

sudo apt -y install haproxy


4단계 – etcdnode에서 etcd를 구성합니다.




sudo vi /etc/default/etcd   

ETCD_LISTEN_PEER_URLS="http://<etcdnode_ip>:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://<etcdnode_ip>:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://<etcdnode_ip>:2380"
ETCD_INITIAL_CLUSTER="default=http://<etcdnode_ip>:2380,"
ETCD_ADVERTISE_CLIENT_URLS="http://<etcdnode_ip>:2379"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

sudo systemctl restart etcd 

sudo systemctl status etcd

curl http://<etcdnode_ip>:2380/members


5단계 – node1, node2 및 node3에서 Patroni를 구성합니다.




sudo vi /etc/patroni.yml

scope: postgres
namespace: /db/
name: node1

restapi:
    listen: <nodeN_ip>:8008
    connect_address: <nodeN_ip>:8008

etcd:
    host: <etcdnode_ip>:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      use_pg_rewind: true
      use_slots: true
      parameters:

  initdb:
  - encoding: UTF8
  - data-checksums

  pg_hba:
  - host replication replicator 127.0.0.1/32 md5
  - host replication replicator <node1_ip>/0 md5
  - host replication replicator <node2_ip>/0 md5
  - host replication replicator <node3_ip>/0 md5
  - host all all 0.0.0.0/0 md5

  users:
    admin:
      password: admin
      options:
        - createrole
        - createdb

postgresql:
  listen: <nodeN_ip>:5432
  connect_address: <nodeN_ip>:5432
  data_dir: /data/patroni
  pgpass: /tmp/pgpass
  authentication:
    replication:
      username: replicator
      password: ************
    superuser:
      username: postgres
      password: ************
  parameters:
      unix_socket_directories: '.'

tags:
    nofailover: false
    noloadbalance: false
    clonefrom: false
    nosync: false


sudo mkdir -p /data/patroni

sudo chown postgres:postgres /data/patroni

sudo chmod 700 /data/patroni 

sudo vi /etc/systemd/system/patroni.service

[Unit]
Description=High availability PostgreSQL Cluster
After=syslog.target network.target

[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/usr/local/bin/patroni /etc/patroni.yml
KillMode=process
TimeoutSec=30
Restart=no

[Install]
WantedBy=multi-user.targ


6단계 – node1, node2 및 node3에서 Patroni 서비스를 시작합니다.




sudo systemctl start patroni

sudo systemctl status patroni

dmi@node1:~$ sudo systemctl status patroni

●  patroni.service - High availability PostgreSQL Cluster

     Loaded: loaded (/etc/systemd/system/patroni.service; disabled; vendor preset: enabled)

     Active: active (running) since Tue 2022-06-28 06:20:08 EDT; 24min ago

   Main PID: 3430 (patroni)

      Tasks: 13 (limit: 2319)

     Memory: 95.9M

     CGroup: /system.slice/patroni.service

             ├─3430 /usr/bin/python3 /usr/local/bin/patroni /etc/patroni.yml

             ├─4189 postgres -D /data/patroni --config-file=/data/patroni/postgresql.conf --listen_addresses=192.168.1.139 --port=5432 --cluster_name=postgres --wal_level=replica --h>

             ├─4197 postgres: postgres: checkpointer

             ├─4198 postgres: postgres: background writer

             ├─4199 postgres: postgres: walwriter

             ├─4200 postgres: postgres: autovacuum launcher

             ├─4201 postgres: postgres: stats collector

             ├─4202 postgres: postgres: logical replication launcher

             └─4204 postgres: postgres: postgres postgres 192.168.1.139(50256) idle

Jun 28 06:43:46 node1 patroni[3430]: 2022-06-28 06:43:46,405 INFO: Lock owner: node1; I am node1
Jun 28 06:43:46 node1 patroni[3430]: 2022-06-28 06:43:46,410 INFO: no action. i am the leader with the lock
Jun 28 06:43:56 node1 patroni[3430]: 2022-06-28 06:43:56,450 INFO: Lock owner: node1; I am node1
Jun 28 06:43:56 node1 patroni[3430]: 2022-06-28 06:43:56,455 INFO: no action. i am the leader with the lock
Jun 28 06:44:06 node1 patroni[3430]: 2022-06-28 06:44:06,409 INFO: Lock owner: node1; I am node1
Jun 28 06:44:06 node1 patroni[3430]: 2022-06-28 06:44:06,414 INFO: no action. i am the leader with the lock
Jun 28 06:44:16 node1 patroni[3430]: 2022-06-28 06:44:16,404 INFO: Lock owner: node1; I am node1
Jun 28 06:44:16 node1 patroni[3430]: 2022-06-28 06:44:16,407 INFO: no action. i am the leader with the lock
Jun 28 06:44:26 node1 patroni[3430]: 2022-06-28 06:44:26,404 INFO: Lock owner: node1; I am node1
Jun 28 06:44:26 node1 patroni[3430]: 2022-06-28 06:44:26,408 INFO: no action. i am the leader with the lock


7단계 – 노드 haproxynode에서 HA 프록시 구성:




sudo vi /etc/haproxy/haproxy.cfg

Replace its context with this:

global

        maxconn 100
        log     127.0.0.1 local2

defaults
        log global
        mode tcp
        retries 2
        timeout client 30m
        timeout connect 4s
        timeout server 30m
        timeout check 5s

listen stats
    mode http
    bind *:7000
    stats enable
    stats uri /

listen postgres
    bind *:5000
    option httpchk
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server node1 <node1_ip>:5432 maxconn 100 check port 8008
    server node2 <node2_ip>:5432 maxconn 100 check port 8008
    server node3 <node3_ip>:5432 maxconn 100 check port 8008

sudo systemctl restart haproxy

sudo systemctl status haproxy

● haproxy.service - HAProxy Load Balancer 
      Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; vendor preset: enabled) 
      Active: active (running) since Tue 2022-06-28 06:54:22 EDT; 7s ago 
        Docs: man:haproxy(1) 
              file:/usr/share/doc/haproxy/configuration.txt.gz 
     Process: 1736 ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS (code=exited,status=0/SUCCESS)   Main PID: 1751 (haproxy) 
     Tasks: 3 (limit: 2319) 
   Memory: 2.1M 
   CGroup: /system.slice/haproxy.service
            ├─1751 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock             
            └─1753 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock 
Jun 28 06:54:22 haproxynode systemd[1]: Starting HAProxy Load Balancer... 
Jun 28 06:54:22 haproxynode haproxy[1751]: [NOTICE] 254/065422 (1751) : New worker #1 (1753) forked 
Jun 28 06:54:22 haproxynode systemd[1]: Started HAProxy Load Balancer. 
Jun 28 06:54:23 haproxynode haproxy[1753]: [WARNING] 254/065423 (1753) : Server postgres/node2 is DOWN, reason: Layer7 wrong status, code: 503, info: 
"HTTP status check returned code <3C>503<3E>">
 Jun 28 06:54:24 haproxynode haproxy[1753]: [WARNING] 254/065424 (1753) : Server postgres/node3 is DOWN, reason: Layer7 wrong status, code: 503, info: 
"HTTP status check returned code <3C>503<3E>">


8단계 – PostgreSQL의 고가용성 클러스터 설정 테스트:




http://<haproxynode_ip>:7000/>




node1 충돌 시뮬레이션:

sudo systemctl stop patroni


이 경우 두 번째 Postgres 서버가 마스터로 승격됩니다.



9단계 – Postgres 클라이언트를 HAProxy IP 주소에 연결합니다.




psql -h <haproxynode_ip> -p 5000 -U postgres

dmi@dmi-mac ~ % psql -h 192.168.1.115 -p 5000 -U postgres
Password for user postgres: 
psql (12.4)
Type "help" for help.

postgres=# 

dmi@dmi-mac ~ % psql -h 192.168.1.115 -p 5000 -U some_db
Password for user some_user: 
psql (12.4)
Type "help" for help.

some_db=>

dmi@node1:~$ patronictl -c /etc/patroni.yml list
+ Cluster: postgres (6871178537652191317) ---+----+-----------+
| Member | Host          | Role    | State   | TL | Lag in MB |
+--------+---------------+---------+---------+----+-----------+
| node1  | 192.168.1.139 | Replica | running |  2 |         0 |
| node2  | 192.168.1.110 | Leader  | running |  2 |           |
| node3  | 192.168.1.146 | Replica | running |  2 |         0 |
+--------+---------------+---------+---------+----+-----------+
dmi@node1:~$ 


10단계 - 장애 복구 테스트:



노드 중 하나에서 다음을 실행합니다.

sudo systemctl stop patroni




요약:



이 게시물에서는 Patroni 및 HAProxy를 사용하여 고가용성 PostgreSQL 클러스터를 배포하는 방법을 시연했습니다. HAProxy IP 주소에 PostgreSQL 클라이언트를 연결하는 고가용성 PostgreSQL 클러스터 설정을 검사하고 장애 조치를 테스트했습니다. 핵심 개념은 PostgreSQL 클러스터의 더 많은 수의 노드에 쉽게 적용될 수 있습니다. 시스템의 가용성을 개선하기 위한 추가 가능한 단계는 etcd에 노드를 추가하고 IP 장애 복구를 위해 HAProxy 서버를 추가하는 것입니다.

좋은 웹페이지 즐겨찾기