WAL-G: biztonsági másolatok és PostgreSQL adatbázisok helyreállítása

Már régóta ismert, hogy SQL dumpokba történő biztonsági másolat készítés (használva a pg_dump vagy pg_dumpall) – nem a legjobb ötlet. PostgreSQL adatbázisok biztonsági másolatának készítéséhez érdemes a pg_basebackupparancsot használni, amely bináris másolatot készít a WAL naplókról. De amikor elkezdi tanulmányozni az egész másolási és helyreállítási folyamatot, megérti, hogy legalább egy pár háromkerekű kerékpárt kell írni ahhoz, hogy mindez működjön és ne okozzon fájdalmat sem felül, sem alul. A szenvedés enyhítése érdekében kifejlesztették a WAL-G-t.

WAL-G – egy Go nyelven írt eszköz PostgreSQL adatbázisok biztonsági másolatának készítésére és helyreállítására (és nemrégiben MySQL/MariaDB, MongoDB és FoundationDB). Támogatja az Amazon S3 tárolók használatát (és az analógokat, például a Yandex Object Storage-t), valamint a Google Cloud Storage-t, Azure Storage-t, Swift Object Storage-t és egyszerűen a fájlrendszert. Az egész beállítás egyszerű lépésekre korlátozódik, de mivel az interneten széttagolt cikkek találhatók róla – nincs teljes how-to kézikönyv, amely minden lépést tartalmazna elejétől a végéig (a Habr-on van néhány bejegyzés, de sok szempontot kihagytak ott).

WAL-G: biztonsági másolatok és PostgreSQL adatbázisok helyreállítása

Ez a cikk elsősorban annak érdekében íródott, hogy a saját tudásomat rendszerezze. Nem vagyok DBA, és valahol laikus fejlesztői nyelven fogalmazhatok, ezért minden javítást szívesen fogadok!

Külön kiemelem, hogy az alább felsorolt minden információ érvényes és ellenőrzött a PostgreSQL 12.3 verzióján Ubuntu 18.04 alatt, minden parancsot privilegizált felhasználóként kell végrehajtani.

Telepítés

A cikk írásakor a WAL-G stabil verziója – v0.2.15 (2020 március). Ezt fogjuk használni (de ha szeretné saját magának összeállítani a master ágból, akkor a github tárolóban megtalálhatja az összes utasítást ehhez). A letöltéshez és telepítéshez a következőt kell végrehajtani:

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

Ezután először a WAL-G-t, majd magát a PostgreSQL-t kell konfigurálni.

WAL-G beállítása

A biztonsági másolatok tárolásához az Amazon S3-at fogjuk példaként használni (mivel közelebb áll a szervereimhez, és nagyon olcsón elérhető). A használatához szükség van egy 's3-vödörre' és hozzáférési kulcsokra.

Minden korábbi WAL-G-ról szóló cikkben környezeti változók használatával történt a konfigurálás, de ettől a verziótól kezdve a beállításokat elhelyezhetjük a .walg.json fájlban a postgres felhasználó otthoni könyvtárában. Ennek létrehozásához a következő bash-scriptet kell végrehajtani:

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

Egy kicsit magyarázok az összes paraméterről:

  • WALG_S3_PREFIX – a S3 tárolóhoz vezető útvonal, ahova a biztonsági mentések kerülnek (lehet a gyökérbe vagy mappába is);
  • AWS_ACCESS_KEY_ID – S3 hozzáférési kulcs (tesztkiszolgálóra történő visszaállítás esetén – ezeknek a kulcsoknak ReadOnly Policy-vel kell rendelkezniük! Erről bővebben a visszaállítási szakaszban olvashat.));
  • AWS_SECRET_ACCESS_KEY – titkos kulcs az S3 tárolóban;
  • WALG_COMPRESSION_METHOD – tömörítési módszer, érdemes Brotli-t használni (mivel ez az arany középút a végső méret és a tömörítési/kitömörítési sebesség között);
  • WALG_DELTA_MAX_STEPS – a „delták” száma a teljes biztonsági mentés létrehozásáig (időt és a feltöltendő adatok méretét takarítják meg, de kissé lelassíthatják a visszaállítás folyamatát, ezért nem ajánlott nagy értékeket használni);
  • PGDATA – a tárolt adatainak könyvtárának az útvonala (ezt a parancs végrehajtásával tudhatja meg: pg_lsclusters);
  • PGHOST – adatbázis csatlakozása, helyi biztonsági mentés esetén jobb unix-socket-en keresztül csatlakozni, ahogy ebben a példában is.

A többi paraméter az dokumentációban megtekinthető: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL beállítása

Ahhoz, hogy az adatbázis belsejében az archiváló automatikusan feltöltse a WAL naplókat a felhőbe és szükség esetén visszaálljon belőlük – néhány paramétert be kell állítani a konfigurációs fájlban. /etc/postgresql/12/main/postgresql.confElőször azonban biztosítania kell,hogy a lent említett beállítások ne legyenek más értékekre állítva, hogy a konfiguráció újratöltésekor az SGBD ne álljon le. Ezeket a paramétereket a következőképpen lehet hozzáadni:

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

A beállított paraméterek leírása:

  • wal_level – mennyi információ kerüljön a WAL naplókba, a „replica” – mindent írni;
  • archive_mode – a WAL naplók feltöltésének engedélyezése a paraméterben megadott parancs használatával; archive_command;
  • archive_command – a befejezett WAL napló archiválásához szükséges parancs;
  • archive_timeout – a naplók archiválása csak akkor történik, amikor befejeződtek, de ha a szervere nem túl gyakran változtat/ad hozzá adatokat az adatbázishoz, érdemes itt másodpercekben limitet beállítani, amelynek lejárta után az archiválási parancs kényszerítve lesz végrehajtva (nekem másodpercenként intenzív írásom van az adatbázisba, ezért lemondtam ennek a paraméternek a beállításáról éles környezetben.);
  • restore_command – WAL napló helyreállító parancs a biztonsági mentésből, akkor fogja használni, ha a „teljes biztonsági mentésben” (base backup) hiányoznak a legutolsó módosítások az adatbázisból.

Bővebben minden paraméterről a hivatalos dokumentáció fordításában olvashat: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

A biztonsági mentési ütemezés beállítása

Akárhogy is nézzük, a legkényelmesebb módja a futtatásnak a cron. Ezt fogjuk beállítani a biztonsági mentések létrehozásához. Kezdjük a teljes biztonsági mentés létrehozásával: a wal-g esetében ez a parancs backup-push. De először jobb ezt a parancsot manuálisan végrehajtani a postgres felhasználótól, hogy megbizonyosodjunk róla, hogy minden rendben van (és nincsenek hozzáférési hibák):

#!/bin/bash

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

A futtatási argumentumokban a megadott könyvtár elérési útja van - emlékeztetem, hogy ezt megtudhatjuk, ha végrehajtjuk pg_lsclusters.

Ha minden hiba nélkül zajlott, és az adatok feltöltődtek az S3 tárolóba, akkor beállíthatjuk a periodikus futtatást a crontab-ban:

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

Ebben a példában a biztonsági mentési folyamatot minden nap reggel 4:15-kor indítjuk.

Régi biztonsági mentések törlése

Valószínűleg nem szükséges megőrözni minden biztonsági mentést a középkorból, ezért hasznos lesz időnként "kitakarítani" a tárolóját (mind a "teljes biztonsági mentések", mind a WAL naplók). Ezt szintén cron feladat segítségével fogjuk végrehajtani:

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

A cron minden nap reggel 6:30-kor végrehajtja ezt a feladatot, törölve mindent (teljes biztonsági mentések, delták és WAL-ok) az utolsó 10 napon kívül, de legalább egy mentést hagyva az adott dátumról, hogy bármely pont tól dátuma belekerüljön a PITR-be. a jelenlegi környezet parancsai után Biztonsági mentésből való helyreállítás

Senki számára nem titok, hogy az egészséges adatbázis kulcsa a rendszeres helyreállítás és az adatok integritásának ellenőrzése. Hogyan lehet helyreállni a WAL-G segítségével - erről fogok beszélni ebben a szakaszban, az ellenőrzésekről pedig később.

Külön meg kell említeni

hogy a tesztkörnyezetben (minden, ami nem produkció) a Read Only fiókot kell használni az S3-ban, hogy véletlenül ne felülírja a biztonsági mentéseket. A WAL-G esetében a következő jogokat kell megadni az S3 felhasználónak a Csoport Házirendben ( Hatás: Engedélyezves3:GetObject): s3:ListBucket, s3:GetBucketLocation, . És természetesen előzetesen ne felejtsük el beállítaniarchive_mode=off a beállítási fájlban postgresql.conf , hogy a tesztadatbázisunk ne akarjon csendesen biztosítékot létrehozni.A helyreállítás könnyed mozdulattal történik az

összes PostgreSQL adat (a felhasználók is beleértve) törlésével, ezért kérjük, legyetek rendkívül óvatosak, amikor a következő parancsokat futtatjátok. A parancsok futtatása előtt kérjük, legyetek rendkívül óvatosak! Senki számára nem titok, hogy az egészséges adatbázis kulcsa a rendszeres helyreállítás és az adatok integritásának ellenőrzése.

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

Aki a helyreállítási folyamatot szeretné ellenőrizni — alább egy kis bash-varázslat került előkészítésre, hogy problémák esetén a helyreállítás során a szkript nem nullás exit kóddal leálljon. Ebben a példában 120 ellenőrzést végezünk 5 másodperces időkorlát mellett (összesen 10 perc a helyreállításhoz), hogy megtudjuk, eltűnt-e a jelező fájl (ez azt jelenti, hogy a helyreállítás sikeresen megtörtént):

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

Sikeres helyreállítás után ne felejtsd el újraindítani az összes folyamatot (pgbouncer/monit stb.).

Adatok ellenőrzése a helyreállítás után

Mindig ellenőrizni kell az adatbázis épségét a helyreállítás után, hogy elkerüljük a hibás/rossz biztonsági másolat helyzetét. Jobb ezt minden egyes létrehozott archívumnál elvégezni, de hogy hol és hogyan, az csak a fantáziádon múlik (fel lehet állítani különálló szervereket óradíjas alapon, vagy CI-ban futtatni az ellenőrzést). De legalább szükséges ellenőrizni az adatokat és az indexeket az adatbázisban.

Az adatok ellenőrzéséhez elegendő átfuttatni őket egy dump-on, de jobb, ha a tárolás során ellenőrző összegek bekapcsolva vannak (data checksums):

#!/bin/bash

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

Az indexek ellenőrzéséhez létezik az amcheck modul, a hozzá tartozó sql lekérdezést a WAL-G tesztektől vesszük és köré építünk egy kis logikát:

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

Összefoglalva

Köszönetet szeretnék mondani Andrej Borodinnak a publikáció előkészítésében nyújtott segítségéért, és külön köszönet a WAL-G fejlesztésében végzett hozzájárulásáért!

Ezen a ponton a megjegyzés véget ért. Remélem, sikerült átadnom a beállítás könnyedségét és a hatalmas potenciált, amit ez az eszköz jelent a céged számára. Nagyon sokat hallottam a WAL-G-ról, de sosem volt időm, hogy leüljek és megértem. Miután bevezettük saját magunknál – ez a cikk született meg belőlem.

Külön megjegyzendő, hogy a WAL-G a következő DBMS-ekkel is működhet:

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster