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 << EOF > /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-аутсорсинга!