#1671: Как настроить Swarmica в режиме повышенной отказоустойчивости?
Отредактирована: 81 день назадСимптомы
Все системы у нас в компании должны быть развернуты в режиме повышенной отказоустойчивости, можем ли мы вынести базу данных на отдельный сервер?
Можем ли мы использовать отказоустойчивый кластер БД для Swarmica?
Можно ли настроить Swarmica в режиме active-active cluser?
Решение
Рекомендуемое решение
Наиболее оптимальным решением, с точки зрения стоимости обслуживания, влияния на производительность системы, а так же показателей восстановления RTO (Recovery Time Objective, целевое время восстановления работы) / RPO (Recovery Point Objective, максимальный допустимый объем потерянных данных) является размещение Swarmica внутри единой виртуальной машины, виртуальный диск которой расположен на сетевом хранилище с необходимыми настройками репликации и отказоустойчивости.
Таким образом, минимизируются накладные расходы на развертывание и обслуживание системы и обеспечиваются целевые показатели отказоустойчивости.
Вынос БД в отдельный сервер с репликацией
Данная конфигурация не является рекомендованной и поддерживаемой: такая схема не проходит регулярное тестирование командой Swarmica. Особенности и риски:
- Данная конфигурация не обеспечивает отказоустойчивости сервера БД в полной мере, т.к. в режиме репликации если Мастер станет недоступен, то Реплика не станет Мастером автоматически - ее надо будет сделать Мастером вручную.
- Стоит учитывать ухудшение производительности за счет появления сетевого лага между сервером приложения Swarmica и сервером БД.
- Добавляется потенциальная точка отказа.
Для данной конфигурации нужны 2 сервера:
-Сервер Swarmica (Ubuntu 24)
-Сервер Postgresql-1 (Ubuntu 24)
-Сервер Postgresql-2 (Ubuntu 24)
Postgresql-1 выступает в роли Мастер сервера, а Postgresql-2 в роли реплики.
1. На сервере Swarmica установите Swarmica по инструкции
2. После установки создайте резервную копию БД как описано здесь
3. Остановите Swarmica:
cd /root/swarmica
docker compose down
4. Создайте резервную копию файла /root/swarmica/docker-compose.yml
cp /root/swarmica/docker-compose.yml{,.orig}
5. Закомментируйте спецификацию сервиса postgres и строки описывающие зависимость от сервиса postgres в файле /root/swarmica/docker-compose.yml:
volumes:
swarmica_ai_assistant: {}
swarmica_logs: {}
# swarmica_postgres_data_backups: {}
# swarmica_postgres_data: {}
swarmica_runtime: {}
<...>
django: &django
image: reg.gl.swd.im/swarmica/backend:${SW_BACKEND_VERSION}
depends_on:
# - postgres
<...>
# postgres:
# image: postgres:14.2-bullseye
# container_name: swarmica-postgres
# shm_size: 1gb
# command: postgres -N 200 -c work_mem=8MB -c temp_buffers=16MB -c shared_buffers=1GB -c track_activity_query_size=16384
# restart: always
# volumes:
# - swarmica_postgres_data:/var/lib/postgresql/data:Z
# - swarmica_postgres_data_backups:/backups:z
# env_file:
# - .env
<...>
celeryworker:
<<: *django
depends_on:
# - postgres
- redis
<...>
celerybeat:
<<: *django
restart: always
depends_on:
# - postgres
- redis
<...>
6. В файле /root/swarmica/.env измените:
POSTGRES_HOST=postgres
на
POSTGRES_HOST=<IP_ADDRESS>
где <IP_ADDRESS> - IP адрес сервера Postgresql
и запустите Swarmica:
docker compose pull && docker compose up -d
7. На обоих Postgresql серверах установите postgresql-14:
sudo apt install curl ca-certificates -y
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo sh -c 'echo "deb [arch=amd64 signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sudo apt update
sudo apt install postgresql-14 postgresql-contrib-14 -y
8. На обоих серверах авторизуйтесь как пользователь postgres и создайте пользователя и БД для Swarmica:
su - postgres
psql
CREATE USER swarmica_user WITH PASSWORD '<PASSWORD>';
CREATE DATABASE swarmica_app OWNER swarmica_user;
GRANT ALL PRIVILEGES ON DATABASE swarmica_app TO swarmica_user;
quit
exit
где <PASSWORD> - пароль БД из файла /root/swarmica/.env с сервера Swarmica.
9. На Postgresql-1 загрузите резервную копию БД из шага 2 и восстановите ее:
pg_restore --if-exists --clean -U swarmica_user -d swarmica_app <PATH-TO-BACKUP.sql>
где <PATH-TO-BACKUP.sql> - путь до загруженной резервной копии БД.
10. На Postgresql-1 измените файл конфигурации /etc/postgresql/14/main/postgresql.conf, чтобы postgresql был доступен извне и добавьте конфигурацию Мастер сервера:
listen_addresses = '*'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 5
hot_standby = on
11. Добавьте в файл /etc/postgresql/14/main/pg_hba.conf строку:
host swarmica_app swarmica_user <IP>/<MASK> md5
host replication repuser <REPLICA_IP>/<REPLICA_MASK> md5
где <IP> - IP адрес Swarmica сервера, <MASK> - маска подсети, <REPLICA_IP> - IP адрес сервера Postgresql-2 и <REPLICA_MASK> - его маска подсети.
12. Создайте пользователя для репликации:
sudo -u postgres psql -c "CREATE ROLE repuser REPLICATION LOGIN PASSWORD 'your_secure_password';"
13. Перезапустите postgresql на Postgresql-1:
systemctl restart postgresql@14-main
14. На Postgresql-2 остановите postgresql:
systemctl stop postgresql@14-main
15. Очистите папку с данными:
sudo rm -rf /var/lib/postgresql/14/main/*
16. Скопируйте данные с Postgresql-1:
sudo -u postgres pg_basebackup -h <IP_Мастера> -U repuser -D /var/lib/postgresql/14/main/ -P -R -v
17. Запустите posgresql на Postgresql-2:
systemctl start postgresql@14-main
Вынос БД в отдельный сервер + отказоустойчивость
Данная конфигурация не является рекомендованной и поддерживаемой: такая схема не проходит регулярное тестирование командой Swarmica. Особенности и риски:
- Стоит учитывать ухудшение производительности за счет появления сетевого лага между сервером приложения Swarmica и сервером БД
- Увеличение энтропии системы и, как следствие, увеличение сложности обслуживания
- Добавление потенциальных точек отказа
Для данной конфигурации нужны 4 сервера:
-Сервер swarmica-master-1 (Ubuntu 24)
-Сервер swarmica-postgres-1 (Ubuntu 24)
-Сервер swarmica-postgres-2 (Ubuntu 24)
-Сервер swarmica-pgbouncer-1 (Ubuntu 24)
swarmica-master-1
Повторите шаги 1-6 этой секции, но на 6 шаге измените строки:
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
на:
POSTGRES_HOST=<PGBOUNCER_IP>
POSTGRES_PORT=6432
где <PGBOUNCER_IP> - IP адрес сервера swarmica-pgbouncer-1
swarmica-pgbouncer-1
На данном сервере настраивается приложение pgbouncer + haproxy. Данная связка позволяет реализовать механизм failover, когда Мастер сервер базы данных станет недоступным.
1. Установите docker:
apt install docker.io docker-compose-v2
2. Создайте папку /root/swarmica-pgbouncer и перейдите в нее:
mkdir /root/swarmica-pgbouncer
cd /root/swarmica-pgbouncer
3. Создайте файл /root/swarmica-pgbouncer/docker-compose.yml со следующим содержимым:
version: "3.8"
services:
haproxy:
image: haproxy:2.9
container_name: haproxy
restart: always
ports:
- "5433:5433"
- "8404:8404"
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
pgbouncer:
image: edoburu/pgbouncer
container_name: pgbouncer
restart: always
ports:
- "6432:6432"
volumes:
- ./pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro
- ./users/userlist.txt:/etc/pgbouncer/userlist.txt:ro
4. Создайте файл /root/swarmica-pgbouncer/haproxy.cfg со следующим содержимым:
global
maxconn 10000
defaults
mode tcp
timeout connect 5s
timeout client 1m
timeout server 1m
# =========================
# Patroni API checks
# =========================
frontend pgsql_write
bind *:5433
default_backend pg_primary
backend pg_primary
option httpchk GET /master
http-check expect status 200
server pg1 <swarmica-postgres-1_IP>:5432 check port 8008
server pg2 <swarmica-postgres-2_IP>:5432 check port 8008
# =========================
# metrics
# =========================
listen stats
bind *:8404
stats enable
stats uri /
где <swarmica-postgres-1_IP> IP адрес swarmica-postgres-1 и <swarmica-postgres-2_IP> - IP адрес swarmica-postgres-2.
5. Создайте файл /root/swarmica-pgbouncer/pgbouncer.ini со следующим содержимым:
[databases]
swarmica_app = host=<swarmica-pgbouncer-1_IP> port=5433 dbname=swarmica_app
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 2000
default_pool_size = 50
ignore_startup_parameters = extra_float_digits
6. Создайте файл /root/swarmica-pgbouncer/users/userlist.txt со следующим содержимым:
"swarmica_user" "<DB_PASSWORD>"
где <DB_PASSWORD> - пароль БД из файла /root/swarmica/.env с сервера swarmica-master-1
7. Запустите приложение:
docker compose pull && docker compose up -d
swarmica-postgres-1 и swarmica-postgres-2
На этих серверах устанавливаются postgresql-14, etcd и patroni. Один из серверов выступает в роли Мастера, второй в роли Реплики. Связка etcd + patroni обеспечивает механизм failover. Если Мастер сервер вдруг станет недоступен, то patroni сделает Реплику Мастером, а старый Мастер станет Репликой, когда вернется в рабочее состояние.
1. Установите на обоих серверах postgresql-14 (п.7-11 этой секции)
2. На swarmica-postgres-1 установите пароль для пользователя postgres и создайте пользователя для репликации:
su - postgres
psql -c "ALTER ROLE postgres PASSWORD '<POSTGRES_PASSWORD>';"
psql -C "CREATE ROLE replication_user WITH REPLICATION LOGIN PASSWORD 'REPLICATION_PASSWORD';"
exit
3. На swarmica-postgres-1 восстановите резервную копию БД (п.12 этой секции). На swarmica-postgres-2 восстанавливать резервную копию не надо.
4. На обоих серверах остановите и выключите postgresql:
systemctl stop postgresql@14-main && systemctl disable postgresql@14-main
Это необходимо поскольку дальше управлять БД будет patroni.
5. На обоих серверах установите etcd:
apt install etcd-server etcd-client
6. Создайте файл /etc/systemd/system/etcd.service со следующим содержимым:
swarmica-postgres-1:
[Unit]
Description=etcd
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=notify
User=etcd
ExecStart=/usr/bin/etcd \
--name pg1 \
--data-dir /var/lib/etcd \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://<swarmica-postgres-1_IP>:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://<swarmica-postgres-1_IP>:2380 \
--initial-cluster pg1=http://<swarmica-postgres-1_IP>:2380,pg2=http://<swarmica-postgres-2_IP>:2380 \
--initial-cluster-state new \
--initial-cluster-token postgres-cluster
Restart=always
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
swarmica-postgres-2:
[Unit]
Description=etcd
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=notify
User=etcd
ExecStart=/usr/bin/etcd \
--name pg2 \
--data-dir /var/lib/etcd \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://<swarmica-postgres-2_IP>:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://<swarmica-postgres-2_IP>:2380 \
--initial-cluster pg1=http://<swarmica-postgres-1_IP>:2380,pg2=http://<swarmica-postgres-2_IP>:2380 \
--initial-cluster-state existing \
--initial-cluster-token postgres-cluster
Restart=always
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Замените <swarmica-postgres-1_IP> и <swarmica-postgres-2_IP> соответственно.
7. Запустите etcd сначала на swarmica-postgres-1, потом на swarmica-postgres-2:
systemctl daemon-reload
systemctl enable etcd --now
И проверьте, что кластер etcd запустился:
etcdctl member list
Пример ожидаемого вывода:
$ etcdctl member list
c9104917e339b5d, started, pg1, http://10.130.0.33:2380, http://10.130.0.33:2379, false
e8205d05fd4e969, started, pg2, http://10.130.0.27:2380, http://10.130.0.27:2379, false
8. Установите необходимые пакеты для patroni на обоих серверах:
apt install python3 python3-pip python3-dev pipx -y
9. Авторизуйтесь под пользователем postgres и установите patroni на обоих серверах:
su - postgres
pipx ensurepath
source ~/.bashrc
pipx install patroni[psycopg2-binary,etcd]
exit
10. Создайте файл /etc/systemd/system/patroni.service на обоих серверах с содержимым:
[Unit]
Description=High availability PostgreSQL cluster
After=syslog.target network.target etcd.service
[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/var/lib/postgresql/.local/bin/patroni /etc/patroni/patroni.yml
KillMode=process
TimeoutSec=30
Restart=no
[Install]
WantedBy=multi-user.target
11. Создайте файл конфигурации /etc/patroni/patroni.yml на обоих серверах.
swarmica-postgres-1:
scope: pg-cluster
namespace: /db/
name: pg1
restapi:
listen: 0.0.0.0:8008
connect_address: <swarmica-postgres-1_IP>:8008 # здесь надо указать соответствующий IP
etcd3:
hosts: ["<swarmica-postgres-1_IP>:2379", "<swarmica-postgres-2_IP>:2379"] # здесь надо указать соответствующие IP
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
max_wal_senders: 10
max_replication_slots: 10
wal_keep_size: 1GB
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication replication_user <NETWORK>/<MASK> md5 # здесь указываем нужные сеть и маску подсети
- host all all 0.0.0.0/0 md5
postgresql:
listen: 0.0.0.0:5432
connect_address: <swarmica-postgres-1_IP>:5432 # здесь надо указать соответствующий IP
data_dir: /var/lib/postgresql/14/main
bin_dir: /usr/lib/postgresql/14/bin
authentication:
replication:
username: replication_user
password: <REPLICATION_PASSWORD>
superuser:
username: postgres
password: <POSTGRES_PASSWORD>
pg_hba:
- host replication replication_user <NETWORK>/<MASK> md5 # здесь указываем нужные сеть и маску подсети
# Keep your other existing pg_hba lines below
- host all all 0.0.0.0/0 md5
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
swarmica-postgres-2:
scope: pg-cluster
namespace: /db/
name: pg2
restapi:
listen: 0.0.0.0:8008
connect_address: <swarmica-postgres-2_IP>:8008 # здесь надо указать соответствующий IP
etcd3:
hosts: ["<swarmica-postgres-1_IP>:2379", "<swarmica-postgres-2_IP>:2379"] # здесь надо указать соответствующие IP
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
max_wal_senders: 10
max_replication_slots: 10
wal_keep_size: 1GB
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication replication_user <NETWORK>/<MASK> md5 # здесь указываем нужные сеть и маску подсети
- host all all 0.0.0.0/0 md5
postgresql:
listen: 0.0.0.0:5432
connect_address: <swarmica-postgres-2_IP>:5432 # здесь надо указать соответствующий IP
data_dir: /var/lib/postgresql/14/main
bin_dir: /usr/lib/postgresql/14/bin
authentication:
replication:
username: replication_user
password: <REPLICATION_PASSWORD>
superuser:
username: postgres
password: <POSTGRES_PASSWORD>
pg_hba:
- host replication replication_user <NETWORK>/<MASK> md5 # здесь указываем нужные сеть и маску подсети
# Keep your other existing pg_hba lines below
- host all all 0.0.0.0/0 md5
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
Будьте внимательны при создании конфигурационных файлов. Вместо <REPLICATION_PASSWORD> и <POSTGRES_PASSWORD> укажите пароли из п. 2
12. Запустите patroni сначала на swarmica-postgres-1 и через 5-10 секунд на swarmica-postgres-2:
systemctl daemon-reload
systemctl enable patroni --now
13. Проверьте работоспособность patroni:
sudo -u postgres -i patronictl -c /etc/patroni/patroni.yml list
Ожидаемый вывод команды:
+ Cluster: pg-cluster (7644156829524943409) -+----+-------------+-----+------------+-----+
| Member | Host | Role | State | TL | Receive LSN | Lag | Replay LSN | Lag |
+--------+-------------+---------+-----------+----+-------------+-----+------------+-----+
| pg1 | 10.130.0.33 | Leader | running | 6 | | | | |
| pg2 | 10.130.0.27 | Replica | streaming | 6 | 0/F742FF0 | 0 | 0/F742FF0 | 0 |
+--------+-------------+---------+-----------+----+-------------+-----+------------+-----+
Active-active кластер Swarmica
Кластер с двумя активными инстансами Swarmica не поддерживается