Construindo um cluster PostgreSQL altamente disponível usando Patroni, etcd, HAProxy

Acontece que no momento em que o problema foi colocado eu não tinha experiência suficiente para desenvolver e lançar esta solução sozinho. E então comecei a pesquisar no Google.

Não sei qual é o problema, mas pela enésima vez me deparo com o fato de que mesmo que eu faça tudo passo a passo como no tutorial, prepare o mesmo ambiente do autor, nada funciona. Não tenho ideia do que está acontecendo, mas quando me deparei com isso novamente, decidi que escreverei meu próprio tutorial quando tudo der certo. Um que definitivamente funcionará.

Guias na Internet

Acontece que a Internet não sofre com a falta de diversos guias, tutoriais, passo a passo e afins. Acontece que fui encarregado de desenvolver uma solução para organizar e construir convenientemente um cluster PostgreSQL de failover, cujos principais requisitos eram o streaming de replicação do servidor Master para todas as réplicas e o provisionamento automático de uma reserva no caso de um servidor Master falha.

Nesta fase, foi determinada a pilha de tecnologias utilizadas:

  • PostgreSQL como SGBD
  • Patroni como uma solução de cluster
  • etcd como armazenamento distribuído para Patroni
  • HAproxy para organizar um único ponto de entrada para aplicativos que usam o banco de dados

Instalação

Para sua atenção - construindo um cluster PostgreSQL altamente disponível usando Patroni, etcd, HAProxy.

Todas as operações foram realizadas em máquinas virtuais com sistema operacional Debian 10 instalado.

etc.

Eu não recomendo instalar o etcd nas mesmas máquinas onde o patroni e o postgresql estarão localizados, pois a carga do disco é muito importante para o etcd. Mas, para fins educacionais, faremos exatamente isso.
Vamos instalar o etcd.

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

Adicione conteúdo ao arquivo /etc/default/etcd

[membro]

ETCD_NAME=datanode1 # nome do host da sua máquina
ETCD_DATA_DIR=”/var/lib/etcd/default.etcd”

TODOS OS ENDEREÇOS IP DEVEM SER VÁLIDOS. LISTER PEER, CLIENTE, etc. DEVEM SER CONFIGURADOS PARA O ENDEREÇO ​​IP DO HOST

ETCD_LISTEN_PEER_URLS="http://192.168.0.143:2380»# endereço do seu carro
ETCD_LISTEN_CLIENT_URLS="http://192.168.0.143:2379,http://127.0.0.1:2379»# endereço do seu carro

[conjunto]

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.0.143:2380»# endereço do seu carro
ETCD_INITIAL_CLUSTER=»datanode1=http://192.168.0.143:2380,datanode2=http://192.168.0.144:2380,datanode3=http://192.168.0.145:2380»# endereços de todas as máquinas no cluster etcd
ETCD_INITIAL_CLUSTER_STATE = "novo"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-1″
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.0.143:2379»# endereço do seu carro

Execute o comando

systemctl restart etcd

PostgreSQL 9.6 + patronos

A primeira coisa que você precisa fazer é configurar três máquinas virtuais para instalar o software necessário nelas. Depois de instalar as máquinas, se você seguir meu tutorial, poderá executar este script simples que fará (quase) tudo por você. Executa como root.

Observe que o script utiliza PostgreSQL versão 9.6, isso se deve aos requisitos internos de nossa empresa. A solução não foi testada em outras versões do 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

A seguir, no arquivo /etc/patroni.yml que você acabou de criar, você precisa colocar o seguinte conteúdo, é claro, alterando os endereços IP em todos os lugares para os endereços que você usa.
Preste atenção aos comentários neste yaml. Altere os endereços para seus próprios endereços em cada máquina do cluster.

/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

O script deve ser executado em todas as três máquinas do cluster, e a configuração acima também deve ser colocada no arquivo /etc/patroni.yml em todas as máquinas.

Depois de concluir essas operações em todas as máquinas do cluster, execute o seguinte comando em qualquer uma delas

systemctl start patroni
systemctl start postgresql

Aguarde cerca de 30 segundos e execute este comando nas máquinas restantes do cluster.

HAproxy

Usamos o maravilhoso HAproxy para fornecer um único ponto de entrada. O servidor mestre estará sempre disponível no endereço da máquina na qual o HAproxy está implantado.

Para não tornar a máquina com HAproxy um ponto único de falha, vamos lançá-la em um contêiner Docker; no futuro ela poderá ser lançada no cluster do K8 e tornar nosso cluster de failover ainda mais confiável.

Crie um diretório onde você possa armazenar dois arquivos - Dockerfile e haproxy.cfg. Vá.

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

Cuidado, as três últimas linhas do arquivo haproxy.cfg devem listar os endereços de suas máquinas. O HAproxy entrará em contato com o Patroni, nos cabeçalhos HTTP o servidor mestre sempre retornará 200, e a réplica sempre retornará 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

Estando no diretório onde “estão” nossos dois arquivos, vamos executar sequencialmente os comandos para empacotar o container, bem como iniciá-lo com encaminhamento das portas necessárias:

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

Agora, abrindo o endereço da sua máquina com HAproxy no navegador e especificando a porta 7000, você verá estatísticas do seu cluster.

O servidor mestre estará no estado UP e as réplicas estarão no estado DOWN. Isso é normal, na verdade funcionam, mas aparecem assim porque retornam 503 para solicitações do HAproxy. Isso nos permite saber sempre exatamente qual dos três servidores é o mestre atual.

Conclusão

Você é maravilhosa! Em apenas 30 minutos você implantou um cluster de banco de dados excelente, tolerante a falhas e de alto desempenho, com replicação de streaming e fallback automático. Se você está planejando usar esta solução, confira com documentação oficial do Patroni, e especialmente com sua parte relativa ao utilitário patronictl, que fornece acesso conveniente para gerenciar seu cluster.

Parabéns!

Fonte: habr.com

Adicionar um comentário