It has long been known that creating backups in SQL dumps (using pg_dump või pg_dumpall) is not the best idea. For backing up PostgreSQL databases, it is better to use the command pg_basebackup, which creates a binary copy of the WAL logs. However, when you start exploring the whole process of backup and recovery, you will realize that you need to write at least a couple of three-wheeled bicycles to make everything work without causing you pain both above and below. To alleviate the suffering, WAL-G was developed.
is a tool written in Go for backing up and recovering PostgreSQL databases (and recently also MySQL/MariaDB, MongoDB, and FoundationDB). It supports operations with Amazon S3 storage (and analogs, such as Yandex Object Storage), as well as Google Cloud Storage, Azure Storage, Swift Object Storage, and simply with the file system. All setup boils down to simple steps, but since articles about it are scattered across the internet - there is no complete how-to manual that includes all the steps from start to finish (there are several posts on Habr, but many points are missed there).

See artikkel on kirjutatud eelkõige selleks, et süsteemida oma teadmisi. Ma ei ole DBA ja seetõttu võib mõnes kohas kasutada kergelt arendajakeelt, seega oodatakse kõiki parandusettepanekuid!
Erakordselt märgin, et kõik allpooltoodud on ajakohane ja kinnitatud PostgreSQL 12.3 puhul Ubuntu 18.04-l, kõik käsud tuleb täita privileegidega kasutajalt.
Installeerimine
Käesoleva artikli kirjutamise hetkel on stabiilne versioon WAL-G – . Just seda me ka kasutame (kuid kui soovite selle ise master-harust koguda, on GitHubi repos kõik juhised selleks). Allalaadimiseks ja installimiseks tuleb täita:
#!/bin/bash
curl -L "https://github.com/wal-g/wal-g/releases/download/v0.2.15/wal-g.linux-amd64.tar.gz" -o "wal-g.linux-amd64.tar.gz"
tar -xzf wal-g.linux-amd64.tar.gz
mv wal-g /usr/local/bin/
Pärast seda tuleb esmalt konfigureerida WAL-G ja seejärel PostgreSQL.
WAL-G konfigureerimine
Näidisena kasutatakse varukoopiate säilitamiseks Amazon S3 (sest see on minu serveritele lähemal ja selle kasutamine on väga odav). Selleks on vajalik "s3-bucket" ja juurdepääsuvõtmed.
Kõigis eelnevates artiklites WAL-G kohta on kasutatud konfigureerimist keskkonnamuutujate abil, kuid alates sellest versioonist on seadeid nüüd võimalik paigutada kasutaja postgres kodudirektoris. Selle loomiseks sooritame järgmise bash-skripti:
#!/bin/bash
cat > /var/lib/postgresql/.walg.json << EOF
{
"WALG_S3_PREFIX": "s3://your_bucket/path",
"AWS_ACCESS_KEY_ID": "key_id",
"AWS_SECRET_ACCESS_KEY": "secret_key",
"WALG_COMPRESSION_METHOD": "brotli",
"WALG_DELTA_MAX_STEPS": "5",
"PGDATA": "/var/lib/postgresql/12/main",
"PGHOST": "/var/run/postgresql/.s.PGSQL.5432"
}
EOF
# обязательно меняем владельца файла:
chown postgres: /var/lib/postgresql/.walg.json
Selgitan natuke kõiki parameetreid:
- WALG_S3_PREFIX – tee teie S3-bucket'ini, kuhu varukoopiad saadetakse (saab olla nii juures kui ka kaustas);
- AWS_ACCESS_KEY_ID – ligipääsuvõti S3-sse (testserveris taastamise korral – need võtmed peavad olema ReadOnly Policy! Sellest on rohkem kirjutatud taastamise jaotises.);
- AWS_SECRET_ACCESS_KEY – saladusvõti S3-s;
- WALG_COMPRESSION_METHOD – tihendamismeetod, parim on kasutada Brotli (kuna see on kullast kesktee lõpliku suuruse ja tihendamise/avamise kiirusest);
- WALG_DELTA_MAX_STEPS – «delta» arv enne täisvarukoopia loomist (aitavad säästa aega ja laaditavate andmete suurust, kuid võivad taastamisprotsessi veidi aeglustada, seega ei tohiks kasutada suuri väärtusi);
- PGDATA – tee teie andmebaasi andmete kausta (saab teada, sooritades käsu pg_lsclusters);
- PGHOST – ühendus andmebaasiga, kohaliku varukoopia tegemisel on parem kasutada unix-socket'i nagu antud näites.
Ülejäänud parameetreid saab vaadata dokumentatsioonist: .
PostgreSQL seadistamine
Kuna arhiivija saaks automaatselt üles laadida WAL-logid pilve ja vajadusel neist taastuda, tuleb konfigureerimisfailis määrata mõned parameetrid. /etc/postgresql/12/main/postgresql.confAga kõigepealt peate veenduma, et allpool loetletud seadeid pole määratud mingiteks muuks väärtuseks, et konfigureerimise taaskäivitamisel – andmebaas ei kukuks. Nende parameetrite määramiseks saate kasutada:
#!/bin/bash
echo "wal_level=replica" >> /etc/postgresql/12/main/postgresql.conf
echo "archive_mode=on" >> /etc/postgresql/12/main/postgresql.conf
echo "archive_command='/usr/local/bin/wal-g wal-push "%p" >> /var/log/postgresql/archive_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.conf
echo “archive_timeout=60” >> /etc/postgresql/12/main/postgresql.conf
echo "restore_command='/usr/local/bin/wal-g wal-fetch "%f" "%p" >> /var/log/postgresql/restore_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.conf
# перезагружаем конфиг через отправку SIGHUP сигнала всем процессам БД
killall -s HUP postgres
Määratletud parameetrite kirjeldus:
- wal_level – kui palju teavet kirjutada WAL-logidesse; „replica” – kirjutada kõik;
- archive_mode – WAL-logide üleslaadimise lubamine määratud käsu abil archive_command;
- archive_command – käsk lõpetatud WAL-logi arhiveerimiseks;
- archive_timeout – logide arhiveerimine toimub ainult siis, kui see on lõpetatud, kuid kui teie serveris muudetakse/õigatakse andmeid harva, siis tasub seada siia sekundite piirmäär, mille möödudes hüvitise käsk kutsutakse sunniviisiliselt esile (mul on intensiivne kirje andmebaasi igal sekundil, seetõttu loobusin selle parameetri seadmisest tootmises.);
- restore_command – WAL-žurnali varukoopiast taastamise käsk, mida kasutatakse juhul, kui 'täis varukoopias' (base backup) puuduvad viimased muudatused andmebaasis.
Kõiki neid parameetreid saab lugeda ametliku dokumentatsiooni tõlkest: .
Varukoopiate ajastamise seadistamine
Kuidas iganes, kõige mugavam viis käivitamiseks on cron. Just seda me seadistame varukoopiate loomiseks. Alustame täis varukoopia loomise käsust: wal-g-s on see käivituse argument backup-push. Kuid kõigepealt on parem käivitada see käsk käsitsi kasutaja postgres'ena, et veenduda, et kõik on korras (ja pole mingeid ligipääsu vigu):
#!/bin/bash
su - postgres -c '/usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main'
Käivituse argumentides on määratud teeandmete kaustani – meenutan, et seda saab teada täidesaatmisega pg_lsclusters.
Kui kõik läks ilma vigadeta ja andmed laaditi S3 salvestusse, siis saab edasi seadistada perioodilise käivitamise crontabis:
#!/bin/bash
echo "15 4 * * * /usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main >> /var/log/postgresql/walg_backup.log 2>&1" >> /var/spool/cron/crontabs/postgres
# задаем владельца и выставляем правильные права файлу
chown postgres: /var/spool/cron/crontabs/postgres
chmod 600 /var/spool/cron/crontabs/postgres
Selles näites käivitub varukoopiate protsess iga päev kell 4:15 hommikul.
Vanade varukoopiate kustutamine
Tõenäoliselt ei pea te kõiki mesosoika ajast pärit varukoopiaid säilitama, seega on kasulik aeg-ajalt oma salvestusruumi "puhtaks teha" (nii "täielikud varukoopiad" kui ka WAL-logid). Teeme seda samuti cron-ülesande kaudu:
#!/bin/bash
echo "30 6 * * * /usr/local/bin/wal-g delete before FIND_FULL $(date -d '-10 days' '+%FT%TZ') --confirm >> /var/log/postgresql/walg_delete.log 2>&1" >> /var/spool/cron/crontabs/postgres
# ещё раз задаем владельца и выставляем правильные права файлу (хоть это обычно это и не нужно повторно делать)
chown postgres: /var/spool/cron/crontabs/postgres
chmod 600 /var/spool/cron/crontabs/postgres
Cron täidab seda ülesannet iga päev kell 6:30 hommikul, kustutades kõik (täielikud varukoopiad, delta ja WAL-id) peale viimase 10 päeva koopiate, kuid jätab vähemalt ühe varukoopia kuni mugandatud kuupäevast, et iga punkt pärast kuupäeva jõuaks PITR-i.
Varukoopiast taastamine
Ei ole kellegile saladus, et terve andmebaasi aluseks on andmete regulaarne taastamine ja terviklikkuse kontrollimine. Kuidas taastuda WAL-G abil – räägin selles lõigus, ning kontrollidest räägime hiljem.
Erakordselt tuleks märkida et testkeskkonna (kõik, mis ei ole production) taastamiseks – tuleks kasutada Read Only kontot S3-s, et juhuslikult varukoopiaid mitte üle kirjutada. WAL-G puhul tuleb S3 kasutajale määrata järgmised õigused Group Policy-s:Effect: Allow): s3:GetObject, s3:ListBucket, s3:GetBucketLocation. Ja, loomulikult, ärge unustage eelnevalt seadistada archive_mode=off failis seadistustes postgresql.conf, et teie testbaas ei soovi vaikselt varundada.
Taastamine toimub hõlpsa liigutusega, kui kustutatakse kõik PostgreSQL andmed (sealhulgas kasutajad), seega palun olge äärmiselt ettevaatlikud, kui käivitate järgmisi käske.
#!/bin/bash
# если есть балансировщик подключений (например, pgbouncer), то вначале отключаем его, чтобы он не нарыгал ошибок в лог
service pgbouncer stop
# если есть демон, который перезапускает упавшие процессы (например, monit), то останавливаем в нём процесс мониторинга базы (у меня это pgsql12)
monit stop pgsql12
# или останавливаем мониторинг полностью
service monit stop
# останавливаем саму базу данных
service postgresql stop
# удаляем все данные из текущей базы (!!!); лучше предварительно сделать их копию, если есть свободное место на диске
rm -rf /var/lib/postgresql/12/main
# скачиваем резервную копию и разархивируем её
su - postgres -c '/usr/local/bin/wal-g backup-fetch /var/lib/postgresql/12/main LATEST'
# помещаем рядом с базой специальный файл-сигнал для восстановления (см. https://postgrespro.ru/docs/postgresql/12/runtime-config-wal#RUNTIME-CONFIG-WAL-ARCHIVE-RECOVERY ), он обязательно должен быть создан от пользователя postgres
su - postgres -c 'touch /var/lib/postgresql/12/main/recovery.signal'
# запускаем базу данных, чтобы она инициировала процесс восстановления
service postgresql start
Neile, kes soovivad taastamisprotsessi kontrollida — allpool on ette valmistatud väike bash-maagia, et taastamise probleemide korral skript kukuks välja mitte-null tagasi laadimisooduvärdiga. Antud näites tehakse 120 kontrolli 5-sekundilise aegumisega (kokku 10 minutit taastamiseks), et teada saada, kas signaalifail on eemaldatud (see tähendaks, et taastamine on läinud edukalt):
#!/bin/bash
CHECK_RECOVERY_SIGNAL_ITER=0
while [ ${CHECK_RECOVERY_SIGNAL_ITER} -le 120 ]
do
if [ ! -f "/var/lib/postgresql/12/main/recovery.signal" ]
then
echo "recovery.signal removed"
break
fi
sleep 5
((CHECK_RECOVERY_SIGNAL_ITER+1))
done
# если после всех проверок файл всё равно существует, то падаем с ошибкой
if [ -f "/var/lib/postgresql/12/main/recovery.signal" ]
then
echo "recovery.signal still exists!"
exit 17
fi
Pärast eduka taastamise lõpetamist ärge unustage tagastada kõik protsessid (pgbouncer/monit jne).
Andmete kontrollimine pärast taastamist
Pärast taastamist on vajalik andmebaasi terviklikkust kontrollida, et vältida rikutud või vale varukoopia olukorda. Ja parem on seda teha iga loodud arhiivi puhul, kuid kus ja kuidas – sõltub ainult teie kujutlusvõimest (saate kasutada tunni alusel eraldi servereid või käivitada kontrolli CI-s). Kuid vähemalt – on vajalik andmete ja indeksite kontrollimine andmebaasis.
Andmete kontrollimiseks on piisav andmed dumpide kaudu läbi lasta, kuid parem oleks, kui andmebaasi loomise ajal oleksid kontrollsummad sisse lülitatud ():
#!/bin/bash
if ! su - postgres -c 'pg_dumpall > /dev/null'
then
echo 'pg_dumpall failed'
exit 125
fi
Indeksite kontrollimiseks – on olemas , sql-päring sellele saame ja ümber ehitame väikese loogika:
#!/bin/bash
# добавляем sql-запрос для проверки в файл во временной директории
cat > /tmp/amcheck.sql << EOF
CREATE EXTENSION IF NOT EXISTS amcheck;
SELECT bt_index_check(c.oid), c.relname, c.relpages
FROM pg_index i
JOIN pg_opclass op ON i.indclass[0] = op.oid
JOIN pg_am am ON op.opcmethod = am.oid
JOIN pg_class c ON i.indexrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE am.amname = 'btree'
AND c.relpersistence != 't'
AND i.indisready AND i.indisvalid;
EOF
chown postgres: /tmp/amcheck.sql
# добавляем скрипт для запуска проверок всех доступных баз в кластере
# (обратите внимание что переменные и запуск команд – экранированы)
cat > /tmp/run_amcheck.sh << EOF
for DBNAME in $(su - postgres -c 'psql -q -A -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;" ')
do
echo "Database: ${DBNAME}"
su - postgres -c "psql -f /tmp/amcheck.sql -v 'ON_ERROR_STOP=1' ${DBNAME}" && EXIT_STATUS=$? || EXIT_STATUS=$?
if [ "${EXIT_STATUS}" -ne 0 ]
then
echo "amcheck failed on DB: ${DBNAME}"
exit 125
fi
done
EOF
chmod +x /tmp/run_amcheck.sh
# запускаем скрипт
/tmp/run_amcheck.sh > /tmp/amcheck.log
# для проверки что всё прошло успешно можно проверить exit code или grep’нуть ошибку
if grep 'amcheck failed' "/tmp/amcheck.log"
then
echo 'amcheck failed: '
cat /tmp/amcheck.log
exit 125
fi
Kokkuvõtteks
Soovin tänada Andreid Borodini abi eest publitsatsiooni ettevalmistamisel ja eraldi tänu tema panuse eest WAL-G arendamisse!
Käesolev märkus jõudis oma lõppu. Loodan, et olen suutnud edastada seadistamise lihtsuse ja selle tööriista rakendamise tohutu potentsiaali teie ettevõttes. Olen WAL-G-st palju kuulnud, aga aega selle ümber istuda ja aru saada ei olnud. Ja pärast selle rakendamist enda juures – tuli minust see artikkel.
Erinevates andmetes on oluline märkida, et WAL-G suudab töötada ka järgmiste andmebaasidega:
- ;
- ;
- ;
- Ja tundub, et varsti on oodata veel mõnda!
Allikas: habr.com
