Patroni, etcd, HAProxy를 사용하여 고가용성 PostgreSQL 클러스터 구축

문제가 제기된 당시에는 이 솔루션을 혼자서 개발하고 출시할 만큼 충분한 경험이 없었습니다. 그리고 구글링을 시작했습니다.

문제가 무엇인지는 모르겠지만, 튜토리얼처럼 차근차근 모든 것을 진행하고, 작성자와 동일한 환경을 준비하더라도 아무 일도 일어나지 않는다는 사실을 여러 번 마주하게 됩니다. 무슨 일인지는 모르겠지만 이 문제를 다시 접했을 때 모든 것이 잘되면 나만의 튜토리얼을 작성하기로 결정했습니다. 확실히 효과가 있을 것입니다.

인터넷 가이드

인터넷에는 다양한 가이드, 튜토리얼, 단계별 등이 부족하여 어려움을 겪지 않습니다. 우연히 장애 조치 PostgreSQL 클러스터를 편리하게 구성하고 구축하기 위한 솔루션을 개발하는 임무를 맡게 되었습니다. 이에 대한 주요 요구 사항은 마스터 서버에서 모든 복제본으로 복제를 스트리밍하고 마스터 서버가 발생할 경우 예약을 자동으로 프로비저닝하는 것이었습니다. 실패.

이 단계에서 사용되는 기술 스택이 결정되었습니다.

  • DBMS로서의 PostgreSQL
  • 패트로니 클러스터링 솔루션으로
  • Patroni용 분산 스토리지인 etcd
  • 데이터베이스를 사용하는 애플리케이션의 단일 진입점을 구성하기 위한 HAproxy

설치

주의 사항 - Patroni, etcd, HAProxy를 사용하여 고가용성 PostgreSQL 클러스터 구축.

모든 작업은 Debian 10 OS가 설치된 가상 머신에서 수행되었습니다.

etcd에서는 디스크 로드가 매우 중요하므로 Patori와 postgresql이 위치할 동일한 시스템에 etcd를 설치하지 않는 것이 좋습니다. 그러나 교육적인 목적으로는 그렇게 할 것입니다.
etcd를 설치해보자.

#!/bin/bash
apt-get update
apt-get install etcd

/etc/default/etcd 파일에 콘텐츠 추가

[회원]

ETCD_NAME=datanode1 # 머신의 호스트 이름
ETCD_DATA_DIR=”/var/lib/etcd/default.etcd”

모든 IP 주소는 유효해야 합니다. LISTER 피어, 클라이언트 등은 호스트의 IP 주소로 설정되어야 합니다.

ETCD_LISTEN_PEER_URLS="http://192.168.0.143:2380» # 자동차 주소
ETCD_LISTEN_CLIENT_URLS="http://192.168.0.143:2379,http://127.0.0.1:2379» # 자동차 주소

[무리]

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.0.143:2380» # 자동차 주소
ETCD_INITIAL_CLUSTER=»datanode1=http://192.168.0.143:2380,datanode2=http://192.168.0.144:2380,datanode3=http://192.168.0.145:2380» # etcd 클러스터에 있는 모든 머신의 주소
ETCD_INITIAL_CLUSTER_STATE="새"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-1″
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.0.143:2379» # 자동차 주소

명령을 실행하십시오.

systemctl restart etcd

PostgreSQL 9.6 + 후원자

가장 먼저 해야 할 일은 세 개의 가상 머신을 설정하여 필요한 소프트웨어를 설치하는 것입니다. 머신을 설치한 후 내 튜토리얼을 따르면 (거의) 모든 작업을 수행하는 이 간단한 스크립트를 실행할 수 있습니다. 루트로 실행됩니다.

스크립트는 PostgreSQL 버전 9.6을 사용하는데, 이는 당사 내부 요구 사항 때문입니다. 이 솔루션은 다른 버전의 PostgreSQL에서는 테스트되지 않았습니다.

#!/bin/bash
apt-get install gnupg -y
echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main" >> /etc/apt/sources.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
apt-get update
apt-get install postgresql-9.6 python3-pip python3-dev libpq-dev -y
systemctl stop postgresql
pip3 install --upgrade pip
pip install psycopg2
pip install patroni[etcd]
echo "
[Unit]
Description=Runners to orchestrate a high-availability PostgreSQL
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
" > /etc/systemd/system/patroni.service
mkdir -p /data/patroni
chown postgres:postgres /data/patroni
chmod 700 /data/patroniпо
touch /etc/patroni.yml

다음으로 방금 생성한 /etc/patroni.yml 파일에 다음 내용을 넣어야 합니다. 물론 모든 위치의 IP 주소를 사용하는 주소로 변경해야 합니다.
이 yaml의 주석에 주의하세요. 클러스터의 각 시스템에서 주소를 사용자 고유의 주소로 변경하십시오.

/etc/patroni.yml

scope: pgsql # должно быть одинаковым на всех нодах
namespace: /cluster/ # должно быть одинаковым на всех нодах
name: postgres1 # должно быть разным на всех нодах

restapi:
    listen: 192.168.0.143:8008 # адрес той ноды, в которой находится этот файл
    connect_address: 192.168.0.143:8008 # адрес той ноды, в которой находится этот файл

etcd:
    hosts: 192.168.0.143:2379,192.168.0.144:2379,192.168.0.145:2379 # перечислите здесь все ваши ноды, в случае если вы устанавливаете etcd на них же

# this section (bootstrap) will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
# and all other cluster members will use it as a `global configuration`
bootstrap:
    dcs:
        ttl: 100
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 1048576
        postgresql:
            use_pg_rewind: true
            use_slots: true
            parameters:
                    wal_level: replica
                    hot_standby: "on"
                    wal_keep_segments: 5120
                    max_wal_senders: 5
                    max_replication_slots: 5
                    checkpoint_timeout: 30

    initdb:
    - encoding: UTF8
    - data-checksums
    - locale: en_US.UTF8
    # init pg_hba.conf должен содержать адреса ВСЕХ машин, используемых в кластере
    pg_hba:
    - host replication postgres ::1/128 md5
    - host replication postgres 127.0.0.1/8 md5
    - host replication postgres 192.168.0.143/24 md5
    - host replication postgres 192.168.0.144/24 md5
    - host replication postgres 192.168.0.145/24 md5
    - host all all 0.0.0.0/0 md5

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

postgresql:
    listen: 192.168.0.143:5432 # адрес той ноды, в которой находится этот файл
    connect_address: 192.168.0.143:5432 # адрес той ноды, в которой находится этот файл
    data_dir: /data/patroni # эту директорию создаст скрипт, описанный выше и установит нужные права
    bin_dir:  /usr/lib/postgresql/9.6/bin # укажите путь до вашей директории с postgresql
    pgpass: /tmp/pgpass
    authentication:
        replication:
            username: postgres
            password: postgres
        superuser:
            username: postgres
            password: postgres
    create_replica_methods:
        basebackup:
            checkpoint: 'fast'
    parameters:
        unix_socket_directories: '.'

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

스크립트는 클러스터의 세 시스템 모두에서 실행되어야 하며 위 구성은 모든 시스템의 /etc/patroni.yml 파일에도 배치되어야 합니다.

클러스터의 모든 머신에서 이러한 작업을 완료한 후에는 그 중 하나에서 다음 명령을 실행하십시오.

systemctl start patroni
systemctl start postgresql

30초 정도 기다린 후 클러스터의 나머지 머신에서 이 명령을 실행합니다.

HA프록시

우리는 단일 진입점을 제공하기 위해 멋진 HAproxy를 사용합니다. 마스터 서버는 HAproxy가 배포된 머신의 주소에서 항상 사용할 수 있습니다.

HAproxy가 있는 시스템을 단일 실패 지점으로 만들지 않기 위해 우리는 이를 Docker 컨테이너에서 시작할 것이며, 향후에는 K8 클러스터로 시작하여 장애 조치 클러스터를 더욱 안정적으로 만들 수 있습니다.

Dockerfile과 haproxy.cfg라는 두 개의 파일을 저장할 수 있는 디렉터리를 만듭니다. 그것으로 가십시오.

도커 파일

FROM ubuntu:latest

RUN apt-get update 
    && apt-get install -y haproxy rsyslog 
    && rm -rf /var/lib/apt/lists/*

RUN mkdir /run/haproxy

COPY haproxy.cfg /etc/haproxy/haproxy.cfg

CMD haproxy -f /etc/haproxy/haproxy.cfg && tail -F /var/log/haproxy.log

haproxy.cfg 파일의 마지막 세 줄에는 컴퓨터의 주소가 나열되어야 하므로 주의하세요. HAproxy는 Patroni에 연락하고 HTTP 헤더에서 마스터 서버는 항상 200을 반환하고 복제본은 항상 503을 반환합니다.

haproxy.cfg

global
    maxconn 100

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 postgresql1 192.168.0.143:5432 maxconn 100 check port 8008
    server postgresql2 192.168.0.144:5432 maxconn 100 check port 8008
    server postgresql3 192.168.0.145:5432 maxconn 100 check port 8008

두 파일이 모두 "있는" 디렉터리에서 컨테이너를 압축하고 필요한 포트를 전달하여 실행하는 명령을 순차적으로 실행해 보겠습니다.

docker build -t my-haproxy .
docker run -d -p5000:5000 -p7000:7000 my-haproxy 

이제 브라우저에서 HAproxy를 사용하여 머신의 주소를 열고 포트 7000을 지정하면 클러스터에 대한 통계를 볼 수 있습니다.

마스터인 서버는 UP 상태가 되고, 레플리카는 DOWN 상태가 됩니다. 이는 정상이며 실제로 작동하지만 HAproxy의 요청에 대해 503을 반환하기 때문에 이런 식으로 나타납니다. 이를 통해 세 서버 중 어느 서버가 현재 마스터인지 항상 정확히 알 수 있습니다.

결론

너는 아주 멋져! 단 30분 만에 스트리밍 복제 및 자동 대체 기능을 갖춘 탁월한 내결함성 및 고성능 데이터베이스 클러스터를 배포했습니다. 이 솔루션을 사용할 계획이라면 다음을 확인하세요. 공식 Patroni 문서 포함, 특히 클러스터 관리에 대한 편리한 액세스를 제공하는 Patronictl 유틸리티와 관련된 부분입니다.

축하해!

출처 : habr.com

코멘트를 추가