WAL-G: backups en herstel fan PostgreSQL DBMS

It is al lang bekend dat backups meitsje yn SQL-dumps (gebrûk fan pg_dump of pg_dumpall) is gjin goed idee. Om de PostgreSQL DBMS te backupjen, is it better om it kommando te brûken pg_basebackup, dy't in binêre kopy makket fan WAL-logs. Mar as jo begjinne te bestudearjen it hiele proses fan it meitsjen fan in kopy en weromsette, sille jo begripe dat jo moatte skriuwe op syn minst in pear trijewielers foar dit te wurkjen en net feroarsaakje pine boppe en ûnder. Om lijen te ferleegjen waard WAL-G ûntwikkele.

WAL-G is in ark skreaun yn Go foar reservekopy en weromsette fan PostgreSQL-databases (en mear resint MySQL / MariaDB, MongoDB en FoundationDB). It stipet wurkjen mei Amazon S3-opslach (en analogen, bygelyks Yandex Object Storage), lykas Google Cloud Storage, Azure Storage, Swift Object Storage en gewoan mei it bestânsysteem. De heule opset komt del op ienfâldige stappen, mar troch it feit dat artikels deroer oer it ynternet ferspraat binne, is d'r gjin folsleine how-to-hantlieding dy't alle stappen fan begjin oant ein soe befetsje (d'r binne ferskate berjochten op Habré, mar in protte punten wurde dêr mist).

WAL-G: backups en herstel fan PostgreSQL DBMS

Dit artikel is primêr skreaun om myn kennis te systematisearjen. Ik bin gjin DBA en ik kin my earne yn 'e lekentaal útdrukke, dus alle korreksjes binne wolkom!

Apart, ik merk op dat alles hjirûnder relevant is en testen foar PostgreSQL 12.3 op Ubuntu 18.04, alle kommando's moatte wurde útfierd as in befoarrjochte brûker.

ynstelling

Op it momint fan it skriuwen fan dit artikel is de stabile ferzje fan WAL-G v0.2.15 (maart 2020). Dit is wat wy sille brûke (mar as jo it sels bouwe wolle fan 'e mastertûke, dan hat it github-repository alle ynstruksjes foar dit). Om te downloaden en te ynstallearjen moatte jo dwaan:

#!/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/

Hjirnei moatte jo earst WAL-G konfigurearje, en dan PostgreSQL sels.

WAL-G ynstelle

Foar in foarbyld fan it opslaan fan backups sil Amazon S3 brûkt wurde (om't it is tichter by myn tsjinners en it gebrûk is hiel goedkeap). Om dêrmei te wurkjen, hawwe jo in "s3 bucket" en tagongstoetsen nedich.

Alle eardere artikels oer WAL-G brûkte konfiguraasje mei omjouwingsfariabelen, mar mei dizze útjefte kinne de ynstellings lizze yn .walg.json triem yn de thúsmap fan de postgres-brûker. Om it te meitsjen, útfiere it folgjende bash-skript:

#!/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

Lit my in bytsje útlizze oer alle parameters:

  • WALG_S3_PREFIX - it paad nei jo S3-emmer wêr't backups sille wurde upload (jo kinne of nei de root of nei in map);
  • AWS_ACCESS_KEY_ID - tagongskaai yn S3 (yn gefal fan herstel op in test tsjinner, dizze kaaien moatte hawwe ReadOnly Policy! Dit wurdt yn mear detail beskreaun yn 'e seksje oer herstel.);
  • AWS_SECRET_ACCESS_KEY - geheime kaai yn S3 opslach;
  • WALG_COMPRESSION_METHOD - kompresjemetoade, it is better om Brotli te brûken (om't dit de gouden gemiddelde is tusken de definitive grutte en kompresje- / dekompresjesnelheid);
  • WALG_DELTA_MAX_STEPS - it oantal "delta's" foardat jo in folsleine reservekopy meitsje (se besparje tiid en de grutte fan ynladen gegevens, mar kinne it herstelproses in bytsje fertrage, dus it is net oan te rieden om grutte wearden te brûken);
  • PGDATA - paad nei de map mei jo databankgegevens (jo kinne útfine troch it kommando út te fieren pg_lsclusters);
  • PGHOST - ferbining mei de databank, mei in lokale reservekopy is it better om it te dwaan fia in unix-socket lykas yn dit foarbyld.

Oare parameters kinne fûn wurde yn 'e dokumintaasje: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL ynstelle

Om de argivator yn 'e databank WAL-logs nei de wolk te uploaden en se fan har te herstellen (as nedich), moatte jo ferskate parameters ynstelle yn it konfiguraasjetriem /etc/postgresql/12/main/postgresql.conf. Krekt foar starters jo moatte der wis fan wêzedat gjin fan 'e ynstellings hjirûnder is ynsteld op oare wearden, sadat as de konfiguraasje opnij laden wurdt, de DBMS net crasht. Jo kinne dizze parameters tafoegje mei:

#!/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

Beskriuwing fan de yn te stellen parameters:

  • wal_level - hoefolle ynformaasje te skriuwen yn WAL logs, "replika" - skriuw alles;
  • argyf_modus - ynskeakelje it downloaden fan WAL-logboeken mei it kommando fan 'e parameter argyf_kommando;
  • argyf_kommando - kommando foar it argivearjen fan in foltôge WAL-log;
  • argyf_timeout - argivearjen fan logboeken wurdt allinich útfierd as it foltôge is, mar as jo tsjinner in bytsje gegevens feroaret / tafoeget oan 'e databank, dan hat it sin om hjir in limyt yn te stellen yn sekonden, wêrnei't it argivearjen kommando mei geweld oproppen wurdt (Ik skriuw yntinsyf nei de databank elke sekonde, dus ik besleat dizze parameter net yn produksje te setten);
  • restore_command - it kommando om it WAL-logboek te herstellen fan in reservekopy sil brûkt wurde as de "folsleine reservekopy" (basis-backup) de lêste wizigingen yn 'e databank mist.

Jo kinne mear lêze oer al dizze parameters yn 'e oersetting fan' e offisjele dokumintaasje: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

It opsetten fan in reservekopy skema

Wat men ek kin sizze, de maklikste manier om it út te fieren is cron. Dit is wat wy sille konfigurearje om backups te meitsjen. Litte wy begjinne mei it kommando om in folsleine reservekopy te meitsjen: yn wal-g is dit it startargumint backup-push. Mar earst is it better om dit kommando manuell út te fieren fan 'e postgres-brûker om te soargjen dat alles goed is (en d'r binne gjin tagongsflaters):

#!/bin/bash

su - postgres -c '/usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main'

De startarguminten jouwe it paad nei de gegevensmap oan - ik herinner jo dat jo it kinne fine troch te rinnen pg_lsclusters.

As alles gie sûnder flaters en de gegevens waarden laden yn S3 opslach, dan kinne jo dan konfigurearje periodike lansearring yn crontab:

#!/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

Yn dit foarbyld begjint it backupproses elke dei om 4:15 oere.

Alde backups wiskje

Meast wierskynlik hoege jo net absolút alle reservekopyen út it Mesozoïkum te bewarjen, dus it sil nuttich wêze om jo opslach periodyk "opromje" (sawol "folsleine backups" as WAL-logs). Wy sille dit alles dwaan troch in cron-taak:

#!/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 sil dizze taak elke dei om 6:30 oere útfiere, alles wiskje (folsleine backups, delta's en WAL's) útsein kopyen foar de lêste 10 dagen, mar op syn minst ien reservekopy litte до oantsjutte datum sadat elk punt после dates waarden opnaam yn PITR.

Weromsette fan in reservekopy

It is gjin geheime dat de kaai foar in sûne databank is periodike restauraasje en ferifikaasje fan de yntegriteit fan de gegevens binnen. Ik sil jo fertelle hoe't jo kinne herstellen mei WAL-G yn dizze seksje, en wy sille letter oer kontrôles prate.

It is de muoite wurdich opskriuwen apart dat om te herstellen yn in test omjouwing (alles dat is net produksje) jo moatte brûke in Read Only account yn S3 om net per ûngelok te oerskriuwe backups. Yn it gefal fan WAL-G moatte jo de folgjende rjochten ynstelle foar de S3-brûker yn Groepsbelied (Effekt: tastean): s3: GetObject, s3: list, s3: GetBucketLocation. En, fansels, ferjit net te setten archive_mode=út yn it ynstellingsbestân postgresql.conf, sadat jo testdatabase net rêstich reservekopy wurde wol.

Restauraasje wurdt útfierd mei in lichte beweging fan 'e hân wiskje alle PostgreSQL-gegevens (ynklusyf brûkers), dus wês ekstreem foarsichtich as jo de folgjende kommando's útfiere.

#!/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

Foar dyjingen dy't it herstelproses wolle kontrolearje, is in lyts stikje bash-magy hjirûnder taret, sadat yn gefal fan problemen yn herstel it skript sil crashe mei in net-nul útgongskoade. Yn dit foarbyld wurde 120 kontrôles makke mei in time-out fan 5 sekonden (yn totaal 10 minuten foar herstel) om út te finen oft it sinjaalbestân is wiske (dit sil betsjutte dat it herstel suksesfol wie):

#!/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

Nei suksesfol herstel, ferjit net om alle prosessen (pgbouncer/monit, ensfh.) werom te begjinnen.

Kontrolearje gegevens nei herstel

It is ymperatyf om de yntegriteit fan 'e databank nei restauraasje te kontrolearjen, sadat in situaasje mei in brutsen / kromme reservekopy net ûntstiet. En it is better om dit te dwaan mei elke makke argyf, mar wêr en hoe hinget allinich ôf fan jo ferbylding (jo kinne yndividuele tsjinners op oerebasis ferheegje of in sjek yn CI útfiere). Mar op syn minst is it nedich om de gegevens en yndeksen yn 'e databank te kontrolearjen.

Om de gegevens te kontrolearjen, is it genôch om it troch in dump te rinnen, mar it is better dat by it meitsjen fan de databank jo kontrôlesummen ynskeakele hawwe (gegevens checksums):

#!/bin/bash

if ! su - postgres -c 'pg_dumpall > /dev/null'
then
    echo 'pg_dumpall failed'
    exit 125
fi

Om te kontrolearjen yndeksen - bestiet amcheck module, litte wy de sql-query dêrfoar nimme fan WAL-G tests en bou der in bytsje logika omhinne:

#!/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

Gearfetsje

Ik soe graach útdrukke myn tankberens oan Andrey Borodin foar syn help by it tarieden fan de publikaasje en spesjale tank foar syn bydrage oan de ûntwikkeling fan WAL-G!

Dit konkludearret dizze notysje. Ik hoopje dat ik it gemak fan opset en it enoarme potensjeel foar it brûken fan dit ark yn jo bedriuw koe oerbringe. Ik hearde in protte oer WAL-G, mar hie noait genôch tiid om te sitten en it út te finen. En nei't ik it thús ymplementearre, kaam dit artikel út my.

Apart is it de muoite wurdich op te merken dat WAL-G ek kin wurkje mei de folgjende DBMS:

Boarne: www.habr.com

Add a comment