使用Patroni、etcd、HAProxy构建高可用的PostgreSQL集群

碰巧的是,在问题提出时,我没有足够的经验来单独开发和推出这个解决方案。 然后我开始谷歌搜索。

我不知道问题是什么,但我无数次面临这样的事实:即使我按照教程中的步骤一步步完成所有操作,准备与作者相同的环境,但仍然没有任何效果。 我不知道出了什么问题,但是当我再次遇到这种情况时,我决定等一切顺利后我会编写自己的教程。 一款绝对有效的产品。

互联网上的指南

恰巧互联网并不缺乏各种指南、教程、分步教程等。 碰巧,我的任务是开发一个解决方案,以便方便地组织和构建故障转移 PostgreSQL 集群,其主要要求是从主服务器到所有副本的流式复制,以及在主服务器发生时自动配置保留失败。

在这个阶段,所使用的技术堆栈已经确定:

  • PostgreSQL 作为 DBMS
  • 帕特罗尼 作为集群解决方案
  • etcd 作为 Patroni 的分布式存储
  • HAproxy 用于使用数据库组织应用程序的单个入口点

安装

请注意 - 使用 Patroni、etcd、HAProxy 构建高度可用的 PostgreSQL 集群。

所有操作均在安装了 Debian 10 操作系统的虚拟机上进行。

我不建议将 etcd 安装在 patoni 和 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 地址都应该有效。 列表节点、客户端等应设置为主机的 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 + 守护者

您需要做的第一件事是设置三个虚拟机并在其上安装必要的软件。 安装机器后,如果您遵循我的教程,您可以运行这个简单的脚本,它将(几乎)为您完成所有操作。 以 root 身份运行。

请注意,该脚本使用 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 秒,然后在集群中的其余计算机上运行此命令。

代理

我们使用出色的 HAproxy 来提供单点入口。 主服务器将始终在部署 HAproxy 的计算机的地址上可用。

为了不让带有HAproxy的机器出现单点故障,我们将它启动在Docker容器中;将来它可以启动到K8的集群中,使我们的故障转移集群更加可靠。

创建一个可以存储两个文件的目录 - Dockerfile 和 haproxy.cfg。 去吧。

Dockerfile

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 官方文档,特别是与 patonictl 实用程序相关的部分,它提供了管理集群的便捷访问。

恭喜!

来源: habr.com

添加评论