Использование WAL-G для: 1) s3 хранилища Yandex Cloud 2) NFS 3) совместно с Patroni
1. Настройка WAL-G для работы с s3 хранилищем Yandex Cloud
Данный блок настроек необходим для работы с S3 в качестве хранилища данных. В случае, если в качестве места хранения бэкапов используется файловая система - проделайте инструкции из соответствующего раздела.
Работа с YC
- Создаём сервисный аккаунт для работы с бакетом без дополнительных ролей в каталоге (имя произвольное):
- Создаём бакет для хранения бэкапов:
- Выдаём сервисному аккаунту, созданному ранее, права storage.uploader на созданный бакет:
На этом этапе работа с YC завершена.
Создаём конфигурационный файл для wal-g и выдаём права пользователю postgres на работу с ним:
wal-g s3 configuration
cat > /var/lib/postgresql/.walg.json <<EOF
{
"PGDATA":"/var/lib/postgresql/tantor-se-server-15/main/$(cat /etc/hostname)",
"AWS_ACCESS_KEY_ID":"xxx",
"AWS_SECRET_ACCESS_KEY": "yyy",
"WALE_S3_PREFIX":"s3://zzz",
"AWS_ENDPOINT":"https://storage.yandexcloud.net",
"AWS_S3_FORCE_PATH_STYLE":"True",
"AWS_REGION":"ru-central1"
}
EOF
chown postgres:postgres /var/lib/postgresql/.walg.json
Объяснение параметров из блока выше:
PGDATA - каталог, содержащий данные СУБД;
AWS_ACCESS_KEY_ID - идентификатор пользователя, созданного в YC (см инструкцию выше);
AWS_SECRET_ACCESS_KEY - пароль (ключ) пользователя, созданного в YC (см инструкцию выше);
WALE_S3_PREFIX - имя бакета, созданного в YC (см инструкцию выше), для сохранения данных при помощи утилиты wal-g;
AWS_ENDPOINT - указание конечного сервиса, на базе которого создан бакет
AWS_S3_FORCE_PATH_STYLE - параметр для включения адресации в стиле пути (например, http://s3.amazonaws.com/BUCKET/KEY) при подключении к S3-совместимому сервису, который не поддерживает URL-адреса бакетов в стиле поддомена (например, http://BUCKET.s3.amazonaws.com/KEY);
AWS_REGION - регион бакета, созданного в YC (см инструкцию выше);
2. Настройка WAL-G для работы с NFS
Данный блок настроек необходим для работы с NFS в качестве хранилища данных. В случае, если в качестве места хранения бэкапов используется s3 хранилище - проделайте инструкции из соответствующего раздела.
wal-g nfs configuration
cat > /var/lib/postgresql/.walg.json <<EOF
{
"WALG_FILE_PREFIX": "/mnt/wal-g/backups/",
"WALG_COMPRESSION_METHOD": "brotli",
"WALG_DELTA_MAX_STEPS": "1",
"PGHOST": "/var/run/postgresql/.s.PGSQL.5432",
"PGDATA": "/var/lib/postgresql/tantor-se-server-15/main/$(cat /etc/hostname)"
}
EOF
chown postgres:postgres /var/lib/postgresql/.walg.json
Объяснение параметров из блока выше:
WALG_FILE_PREFIX - каталог, примонтированный в систему из NFS сервера, в котором будут хранится бэкапы;
WALG_COMPRESSION_METHOD - определяет метод сжатия, который будет использоваться для резервных копий (поддерживаемые значения: lz4, brotli, gzip, xz, lzo)
WALG_DELTA_MAX_STEPS - определяет максимальное количество шагов (инкрементальных бэкапов) между полными резервными копиями
PGHOST - определяет хост PostgreSQL, с которым будет взаимодействовать WAL-G
PGDATA - определяет каталог, содержащий файлы данных СУБД
Особенности настройки WAL-G
В примерах выше были использованы ряд настроек (например, "PGHOST": "/var/run/postgresql/.s.PGSQL.5432", или "AWS_REGION":"ru-central1" и т.д.) . Это полностью настраиваемые параметры, которые необходимо выставить согласно конкретной инсталляции, типу и версии СУБД и т.д.
3. Настройка Patroni для работы с WAL-G
Для работы с кластером будет использован кастомный метод (в примере ниже - wal-g). Размещаем листинг из кода ниже в блоке bootstrap конфигурационного файла (в данном примере он располагается в каталоге /opt/tantor/etc/patroni/<имя узла>.yml) patroni:
patroni bootstrap configuration
method: wal-g
wal-g:
command: "/opt/tantor/etc/patroni/tantor-wal-g.sh"
recovery_conf:
restore_command: '/usr/local/bin/wal-g --config /var/lib/postgresql/.walg.json wal-fetch "%f" "%p" 2>&1 | tee -a /var/lib/postgresql/walg.log'
recovery_target_timeline: latest
recovery_target_action: promote
recovery_target_time: ''
В блок dsc > postgresql > parameters добавляем следующие настройки:
patroni dsc postgresql parameters configuration
parameters:
unix_socket_directories: /var/run/postgresql
archive_mode: 'on'
archive_timeout: 300s
archive_command: 'wal-g --config /var/lib/postgresql/.walg.json wal-push "%p" 2>&1 | tee -a /var/lib/postgresql/walg.log'
recovery_conf:
restore_command: 'wal-g --config /var/lib/postgresql/.walg.json wal-fetch "%f" "%p" 2>&1 |tee -a /var/lib/postgresql/walg.log'
Создаём скрипт для кастомной загрузки c содержимым:
patroni custom bootstrap script
touch /opt/tantor/etc/patroni/tantor-wal-g.sh
chmod +x /opt/tantor/etc/patroni/tantor-wal-g.sh
chown postgres:postgres /opt/tantor/etc/patroni/tantor-wal-g.sh
Добавляем в скрипт следующее содержимое:
patroni custom bootstrap script
#!/bin/bash
# Define WAL-G configuration path
config_path="/var/lib/postgresql/.walg.json"
pgdata_dir="/var/lib/postgresql/tantor-se-server-15/main/$(cat /etc/hostname)"
# Check if the base directory exists, create if it doesn't
if [ ! -d "$pgdata_dir" ]; then
echo "Creating base directory: $pgdata_dir"
mkdir -p "$pgdata_dir"
fi
# Check for existing backups and catchups
backup_list=$(wal-g --config "$config_path" backup-list 2>&1)
catchup_list=$(wal-g --config "$config_path" catchup-list 2>&1)
function get_latest_date() {
#echo "$1" | grep -v 'name' | awk '{print $2 "T" $3}' | sort | tail -n1
echo "$1" | tail -n +2 | awk '{print $2 " " $0}' | sort | tail -n 1 | cut -d' ' -f2-
# date -d "$1 | grep -v 'name' | awk '{print $2 "T" $4}' | sed 's/T$//')" "+%Y-%m-%d %H:%M:%S"
}
# Check for "No backups found"
if [[ "$backup_list" == *"No backups found"* && "$catchup_list" == *"No backups found"* ]]; then
# Standard DB init if no backups are found
echo "No backups found, initializing standard database..." >> /opt/tantor/var/log/patroni/patroni.log
/opt/tantor/db/15/bin/initdb -D $pgdata_dir
exit 0
else
# Determine latest backup and perform appropriate fetch
latest_backup_date=$(get_latest_date "$backup_list")
latest_catchup_date=$(get_latest_date "$catchup_list")
#latest_catchup_date=0
if [[ "$latest_backup_date" > "$latest_catchup_date" ]]; then
echo "Latest backup date: $latest_backup_date" >> /opt/tantor/var/log/patroni/patroni.log
wal-g --config "$config_path" backup-fetch "$pgdata_dir" LATEST
else
echo "Latest catchup date: $latest_catchup_date" >> /opt/tantor/var/log/patroni/patroni.log
wal-g --config "$config_path" catchup-fetch "$pgdata_dir" LATEST
fi
fi
Известные особенности, ошибки и необходимые доработки
- Кластер patroni всегда стартует с tl = 2;
- После запуска кластера wal-g начинает сразу же писать WAL-файлы , используя выбранный метод бэкапирования. В случае полного выхода из строя всего кластера (пример rm -rf по каталогу PGDATA) до создания полного бэкапа patroni не сможет собрать кластер с нуля, используя WAL файлы. Узлы будут находится в статусе ожидания лидера. В данном кейсе необходимо удаление WAL-файлов, после чего требуется повторный запуск patroni.
- В случае выхода из строя узла, имеющего роль "лидер" (пример выполнения функции переключения лидера при помощи patronictl switchover ) одна из реплик берёт на себя эту роль (ожидаемое поведение), в то время как другая переходит в состояние archive recovery (нестандартное поведение);
- Восстановление данных и наливка WAL-журналов всегда происходит при помощи wal-g (т.е. с NFS хранилища или S3 бакета), вне зависимости от доступности узла мастера.