WAL-G: a PostgreSQL DBMS biztonsági mentése és helyreállítása

Régóta köztudott, hogy a biztonsági mentések SQL kiíratásokba készítése (a pg_dump vagy pg_dumpall) nem jó ötlet. A PostgreSQL DBMS biztonsági mentéséhez jobb a parancs használata pg_basebackup, amely a WAL-naplók bináris másolatát készíti. De amikor elkezdi tanulmányozni a másolat létrehozásának és helyreállításának teljes folyamatát, megérti, hogy legalább néhány triciklit kell írnia ahhoz, hogy ez működjön, és ne okozzon fájdalmat fent és lent egyaránt. A szenvedés enyhítésére fejlesztették ki a WAL-G-t.

WAL-G egy Go programban írt eszköz PostgreSQL adatbázisok biztonsági mentésére és visszaállítására (és újabban a MySQL/MariaDB, a MongoDB és a FoundationDB). Támogatja az Amazon S3 tárhelyekkel (és analógjaival, például a Yandex Object Storageval), valamint a Google Cloud Storage, Azure Storage, a Swift Object Storage és egyszerűen a fájlrendszerrel való munkát. A teljes beállítás egyszerű lépésekből áll, de mivel az erről szóló cikkek szétszórva vannak az interneten, nincs teljes használati útmutató, amely az elejétől a végéig tartalmazná az összes lépést (több bejegyzés található a Habrén, de ott sok pont kimarad).

WAL-G: a PostgreSQL DBMS biztonsági mentése és helyreállítása

Ez a cikk elsősorban tudásom rendszerezése céljából készült. Nem vagyok DBA és valahol laikus nyelven is ki tudom fejezni magam, szóval minden javítást szívesen fogadok!

Külön megjegyzem, hogy az alábbiakban leírtak relevánsak és a PostgreSQL 12.3-ra tesztelve Ubuntu 18.04-en, minden parancsot privilegizált felhasználóként kell végrehajtani.

Telepítés

A cikk írásakor a WAL-G stabil verziója az v0.2.15 (2020. március). Ezt fogjuk használni (de ha saját kezűleg szeretnéd felépíteni a fő ágból, akkor a github repository minden utasítást tartalmaz ehhez). A letöltéshez és telepítéshez a következőket kell tennie:

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

Ezt követően először be kell állítani a WAL-G-t, majd magát a PostgreSQL-t.

A WAL-G beállítása

A biztonsági mentések tárolására példaként az Amazon S3 lesz használva (mert közelebb van a szervereimhez és nagyon olcsó a használata). A használatához szükség van egy „s3 vödörre” és a hozzáférési kulcsokra.

A WAL-G-ről szóló összes korábbi cikk környezeti változók segítségével történő konfigurációt használt, de ebben a kiadásban a beállítások megtalálhatók .walg.json fájl a postgres felhasználó kezdőkönyvtárában. Létrehozásához futtassa a következő bash szkriptet:

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

Hadd magyarázzam el egy kicsit az összes paramétert:

  • WALG_S3_PREFIX – az S3 tároló elérési útja, ahová a biztonsági másolatokat feltölti (akár a gyökérbe, akár egy mappába);
  • AWS_ACCESS_KEY_ID – hozzáférési kulcs az S3-ban (tesztszerveren történő helyreállítás esetén ezeknek a kulcsoknak csak olvasható szabályzattal kell rendelkezniük! Ezt részletesebben a helyreállításról szóló részben ismertetjük.);
  • AWS_SECRET_ACCESS_KEY – titkos kulcs az S3 tárolóban;
  • WALG_COMPRESSION_METHOD – tömörítési módszer, jobb a Brotli használata (mivel ez az arany középút a végső méret és a tömörítési/dekompressziós sebesség között);
  • WALG_DELTA_MAX_STEPS – a „delták” száma a teljes biztonsági mentés előtt (időt és a letöltött adatok méretét takarítják meg, de kissé lelassíthatják a helyreállítási folyamatot, ezért nem célszerű nagy értékeket használni);
  • PGDATA - az adatbázis adatait tartalmazó könyvtár elérési útja (parancs futtatásával megtudhatja pg_lsclusters);
  • PGHOST – csatlakozni az adatbázishoz, helyi mentéssel célszerű unix-socket-en keresztül megtenni, mint ebben a példában.

További paraméterek a dokumentációban találhatók: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

A PostgreSQL beállítása

Ahhoz, hogy az adatbázison belüli archiváló WAL-naplókat tölthessen fel a felhőbe és visszaállíthassa belőlük (ha szükséges), több paramétert be kell állítania a konfigurációs fájlban /etc/postgresql/12/main/postgresql.conf. Csak kezdetnek meg kell győződnie arrólhogy az alábbi beállítások egyike sincs más értékre állítva, így a konfiguráció újratöltésekor a DBMS nem omlik össze. Ezeket a paramétereket a következő használatával adhatja hozzá:

#!/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ítandó paraméterek leírása:

  • wal_level – mennyi információt kell beírni a WAL-naplókba, „replikába” – írjon mindent;
  • archív_mód – engedélyezze a WAL-naplók letöltését a paraméter parancsával archív_parancs;
  • archív_parancs – parancs a kitöltött WAL-napló archiválására;
  • archív_időtúllépés – a naplók archiválása csak akkor történik meg, ha ez befejeződött, de ha a szervered módosít/kevés adatot ad hozzá az adatbázishoz, akkor itt érdemes beállítani egy korlátot másodpercekben, ami után az archiválási parancsot kényszerből hívják (Minden másodpercben intenzíven írok az adatbázisba, ezért úgy döntöttem, hogy nem állítom be ezt a paramétert a termelésben);
  • Restore_command – a WAL-napló biztonsági másolatból történő visszaállítására szolgáló parancs akkor kerül felhasználásra, ha a „teljes biztonsági másolatból” (alap biztonsági másolat) hiányoznak az adatbázis legfrissebb módosításai.

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

Biztonsági mentés ütemezésének beállítása

Bármit is mondjunk, a futtatásának legkényelmesebb módja a cron. Ezt fogjuk konfigurálni biztonsági mentések létrehozásához. Kezdjük a teljes biztonsági másolat létrehozásának parancsával: a wal-g-ben ez az indítási argumentum backup-push. Először azonban jobb, ha manuálisan futtatja ezt a parancsot a postgres felhasználótól, hogy megbizonyosodjon arról, hogy minden rendben van (és nincs hozzáférési hiba):

#!/bin/bash

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

Az indítási argumentumok jelzik az adatkönyvtár elérési útját - emlékeztetem, hogy futással megtudhatja pg_lsclusters.

Ha minden hiba nélkül ment, és az adatok az S3 tárolóba kerültek, akkor a crontabban beállíthatja az időszakos indítást:

#!/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 folyamat minden nap 4:15-kor kezdődik.

Régi biztonsági másolatok törlése

Valószínűleg nem kell feltétlenül megőriznie az összes mezozoikum korszak biztonsági másolatát, ezért hasznos lesz rendszeres időközönként „megtisztítani” a tárhelyét (mind a „teljes biztonsági másolatokat”, mind a WAL-naplókat). Mindezt egy cron feladaton keresztül fogjuk megtenni:

#!/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 ezt a feladatot minden nap reggel 6:30-kor futtatja, és mindent töröl (teljes biztonsági másolatokat, deltákat és WAL-okat), kivéve az elmúlt 10 nap másolatait, de legalább egy biztonsági másolatot hagy. a meghatározott dátumot úgy, hogy bármely ponton után dátumok szerepeltek a PITR-ben.

Visszaállítás biztonsági másolatból

Nem titok, hogy az egészséges adatbázis kulcsa az időszakos helyreállítás és a benne lévő adatok integritásának ellenőrzése. Ebben a részben elmondom, hogyan lehet helyreállítani a WAL-G használatával, az ellenőrzésekről pedig később fogunk beszélni.

Külön meg kell jegyezni hogy a tesztkörnyezetben történő visszaállításhoz (minden, ami nem éles) csak olvasható fiókot kell használnia az S3-ban, nehogy véletlenül felülírja a biztonsági másolatokat. WAL-G esetén a következő jogosultságokat kell beállítania az S3 felhasználó számára a Csoportházirendben (Hatás: Engedélyezés): s3: GetObject, s3:ListBucket, s3:GetBucketLocation. És természetesen ne felejtse el beállítani archive_mode=off a beállítási fájlban postgresql.conf, így a tesztadatbázis nem akar csendben biztonsági másolatot készíteni.

A helyreállítás enyhe kézmozdulattal történik az összes PostgreSQL adat törlése (beleértve a felhasználókat is), ezért kérjük, legyen rendkívül óvatos a következő parancsok futtatásakor.

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

Azok számára, akik szeretnék ellenőrizni a helyreállítási folyamatot, alább készült egy kis bash varázslat, hogy helyreállítási problémák esetén a szkript egy nem nulla kilépési kóddal lefagyjon. Ebben a példában 120 ellenőrzés történik 5 másodperces időkorláttal (összesen 10 perc a helyreállításhoz), hogy megtudják, hogy a jelfájlt törölték-e (ez azt jelenti, hogy a helyreállítás sikeres volt):

#!/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 felejtsen el minden folyamatot visszaindítani (pgbouncer/monit stb.).

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

A visszaállítás után feltétlenül ellenőrizni kell az adatbázis sértetlenségét, hogy ne fordulhasson elő törött/görbült biztonsági mentés. És jobb, ha ezt minden egyes létrehozott archívumnál megteszi, de az, hogy hol és hogyan, csak a fantázián múlik (óránként emelheti az egyes szervereket, vagy ellenőrizheti a CI-t). De legalább ellenőrizni kell az adatbázisban lévő adatokat és indexeket.

Az adatok ellenőrzéséhez elegendő egy dump-on keresztül futtatni, de jobb, ha az adatbázis létrehozásakor engedélyezi az ellenőrző összegeket (adatellenőrző összegek):

#!/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 amcheck modul, vegyük a hozzá tartozó sql lekérdezést innen WAL-G tesztek és építs rá 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

Összegezve

Szeretném kifejezni köszönetemet Andrey Borodinnak a kiadvány elkészítésében nyújtott segítségéért és külön köszönetemet fejezem ki a WAL-G fejlesztéséhez való hozzájárulásáért!

Ezzel a jegyzet lezárul. Remélem, sikerült átadnom a könnyű beállítást és az eszköz használatában rejlő hatalmas lehetőségeket az Ön cégében. Sokat hallottam a WAL-G-ről, de soha nem volt elég időm leülni és kitalálni. És miután itthon megvalósítottam, ez a cikk jött ki belőlem.

Külön érdemes megjegyezni, hogy a WAL-G a következő DBMS-ekkel is működik:

Forrás: will.com

Hozzászólás