Patroni — это автоматическая система аварийного переключения для PostgreSQL. Patroni обеспечивает автоматическое и ручное переключение при отказе и хранит все важные данные в распределенном хранилище конфигурации (DCS) на базе систем ETCD, Consul и т.д.. Соединения приложения и базы данных не осуществляются напрямую, а маршрутизируются через прокси-сервер соединения, такой как HAProxy. Прокси определяет активный/главный узел, который в данный момент времени готов обрабатывать соединения. Использования прокси-сервера сводит к 0 шансы встретить split-brain в кластере баз данных.
Для развертывания сервиса потребуется создать инфраструктуру из 3-х виртуальных машин. 2 ВМ для кластера Postgresql и 1 для организации точки входа в кластер на базе HAproxy. На все ВМ устанавливаем ОС Ubuntu 20.04 Server.
Для решения задачи потребуется предварительная подготовка:
- ВМ для ReverseProxy RAM: 1 GB CPU: 2 Core HDD: 20 GB
- ВМ для PostgreSQL RAM: 8 GB CPU: 4 Core HDD: 40 GB
Установка ETCD
ETCD — это отказоустойчивое распределенное хранилище ключей/значений, используемое для хранения состояния кластера Postgres. Используя Patroni все узлы Postgres обмениваются данными с etcd для поддержания работоспособности кластера Postgres. На момент составления инструкции актуальная версия ETCD 3.5.5.
ETCD_VER=v3.5.5
# URL для загрузки диструбутива
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GITHUB_URL}
# Удаляем прошлые установки если не первая попытка, и создаем новую папку для установки.
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test
# Скачиваем и распаковываем файлы приложения, удаляем временные файлы
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
# Проверяем корректность установки
/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
mv /tmp/etcd-download-test/etcd* /usr/local/bin/
Настраиваем службу ETCD
Создаем пользователя для работы со службой.
sudo groupadd --system etcd sudo useradd -s /sbin/nologin --system -g etcd etcd
Создаем и предоставляем права на каталога /var/lib/etcd пользователю etcd.
sudo mkdir -p /var/lib/etcd/ sudo mkdir /etc/etcd sudo chown -R etcd:etcd /var/lib/etcd/ sudo chmod -R 700 /var/lib/etcd/
Следующие операции необходимо выполнить на каждом сервере где будет установлен ETCD. Присваиваем переменным значения для формирования файлы автозапуска службы ETCD.
INT_NAME="eth1"
ETCD_HOST_IP=$(ip-адрес show $INT_NAME | grep "inetb" | awk '{print $2}' | cut -d/ -f1)
ETCD_NAME=$(hostname -s)
- INT_NAME — имя сетевого интерфейса, который будет использоваться для трафика кластера. У каждого сервера он может быть свой.
- ETCD_HOST_IP — внутренний IP-адрес указанного сетевого интерфейса. Он используется для обслуживания клиентских запросов и связи с узлами кластера etcd.
- ETCD_NAME — каждый элемент etcd должен иметь уникальное имя в пределах кластера etcd. Используемая команда установит имя etcd в соответствии с именем хоста текущего сервера.
Проверяем значения переменных. Если у какой-то из переменной не будет значения, служба автозапуска работать не будет.
echo $INT_NAME echo $ETCD_HOST_IP echo $ETCD_NAME
Создаем файл службы для сервиса ETCD.
cat /etc/systemd/system/etcd.service
[Unit]
Description=etcd service
Documentation=https://github.com/coreos/etcd
[Service]
User=etcd
Type=notify
ExecStart=/usr/local/bin/etcd \
--name ${ETCD_NAME} \
--enable-v2=true \
--data-dir /var/lib/etcd \
--initial-advertise-peer-urls http://${ETCD_HOST_IP}:2380 \
--listen-peer-urls http://${ETCD_HOST_IP}:2380 \
--listen-client-urls http://${ETCD_HOST_IP}:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://${ETCD_HOST_IP}:2379 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster revproxy=http://10.15.73.170:2380,postgresql1=http://10.15.73.176:2380,postgresql2=http://10.15.73.177:2380 \
--initial-cluster-state new \
--heartbeat-interval 1000 \
--election-timeout 5000
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
После создания службы на всех серверах, включаем её, первый сервер будет выполнять роль сервера начальной загрузки, после успешного запуска службы на всех серверах, будет выбран лидер.
systemctl daemon-reload systemctl enable etcd systemctl start etcd.service
Проверить состояние кластера после запуска.
systemctl status -l etcd.service etcdctl member list etcdctl endpoint status --write-out=table etcdctl endpoint health
Установка PostgreSQL
Подключаем дополнительный репозиторий с дистрибутивами PostgreSQL и добавляем ключ шифрования. Обновляем кеш пакетов:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/postgresql-pgdg.list > /dev/null sudo apt update
Устанавливаем PostgreSQL, проверяем наличие установленных пакетов.
sudo apt install postgresql-14 dpkg -l | grep postgresql
Останавливаем службу PostgreSQL если она сама запустилась. Управлением сервисом PostgreSQL будет заниматься Patroni.
sudo systemctl stop postgresql sudo systemctl disable postgresql
Установка Patroni
Устанавливаем необходимые пакеты.
sudo apt -y install python3 python3-pip sudo -H pip install --upgrade testresources sudo -H pip install --upgrade setuptools sudo -H pip install psycopg2 sudo -H pip install patroni sudo -H pip install python-etcd
Создаем файл конфигурации для кластера Patroni /etc/patroni.yml. Конфигурационный файл необходимо создать на всех ВМ с PostgreSQL.
scope: postgres
name: postgresql2
restapi:
listen: 0.0.0.0:8008
connect_address: 10.15.73.177:8008
etcd:
host: revproxy: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:
wal_level: replica
hot_standby: "on"
logging_collector: "on"
max_wal_senders: 5
max_replication_slots: 5
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication replicator 127.0.0.1/32 trust
- host replication replicator 10.15.73.177/24 md5
- host all all 10.15.73.1/24 md5
- host all all 0.0.0.0/0 md5
users:
admin:
password: ********************
options:
- createrole
- createdb
postgresql:
listen: 0.0.0.0:5432
connect_address: 10.15.73.177:5432
data_dir: "/data/patroni"
pgpass: /tmp/pgpass
authentication:
replication:
username: replicator
password: ********************
superuser:
username: postgres
password: ********************
parameters:
unix_socket_directories: '/var/run/postgresql'
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
Проверяем конфигурацию. На всех ВМ с PostgreSQL.
patroni --validate-config /etc/patroni.yml
Подготавливаем директорию для работы PostgreSQL.
sudo mkdir -p /data/patroni sudo chown postgres:postgres /data/patroni sudo chmod 700 /data/patroni
Создаем файл службы для автозапуска Patroni. На всех ВМ с PostgreSQL.
sudo nano /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.target
Запускаем Patroni. Проверяем состояние службы. На всех ВМ с PostgreSQL.
sudo systemctl start patroni sudo systemctl status patroni
Установка HAproxy
HAproxy предоставляет единую точку, к которой подключатся приложения работающие с базой данных. Контроль за узлами входа в кластер баз данных осуществляет HAProxy на основе информации от Patroni. Установка HAProxy.
sudo apt -y install haproxy
Настройка конфигурации для HAproxy
Создаем копии конфигурационного файла для изменения. Редактируем базовый конфигурационный файл под наши требованиями.
sudo cp -p /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg-orig sudo nano /etc/haproxy/haproxy.cfg
Содержимое файла конфигурации. IP-адреса используем свои.
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 patroni1 10.15.73.176:5432 maxconn 100 check port 8008
server patroni2 10.15.73.177:5432 maxconn 100 check port 8008
Проверяем конфигурационный файл на наличие ошибок.
sudo /usr/sbin/haproxy -c -V -f /etc/haproxy/haproxy.cfg
Запускаем службу. Проверяем состояние.
sudo systemctl restart haproxy sudo systemctl status haproxy
Переходим на WEB-интерфейс и проверяем корректность работы. WEB-интерфейс доступен по IP-адресу или имени ВМ на порту 7000.
Настройка кластера Postgresql Patroni завершена, для доступа в кластер используется прокси-сервер HAproxy, для хранения состояние кластера Patroni используется ETCD-хранилище, состоящее из 3-х нод. Patroni полностью управляет переключением и работой кластера Postgresql.
Мы можем помочь в настройке Patroni PostgreSQL кластера, а также его поддержке в рамках DevOps-аутсорсинга!
