WAL-G: PostgreSQL DBMS:n varmuuskopiointi ja palautus

On ollut pitkään tiedossa, että varmuuskopioiden tekeminen SQL-vedosteksteihin (käyttäen pg_dump tai pg_dumpall) ei ole hyvä idea. PostgreSQL DBMS:n varmuuskopioimiseksi on parempi käyttää komentoa pg_basebackup, joka tekee binäärikopion WAL-lokeista. Mutta kun alat tutkia koko kopion luomis- ja palautusprosessia, ymmärrät, että sinun on kirjoitettava vähintään pari kolmipyörää, jotta tämä toimisi eikä aiheuta kipua sekä ylä- että alapuolella. WAL-G kehitettiin kärsimyksen lievittämiseksi.

WAL-G on Goissa kirjoitettu työkalu PostgreSQL-tietokantojen varmuuskopiointiin ja palauttamiseen (ja viime aikoina MySQL/MariaDB, MongoDB ja FoundationDB). Se tukee työtä Amazon S3 -tallennustilan (ja analogien, esimerkiksi Yandex Object Storage) kanssa sekä Google Cloud Storagen, Azure Storagen, Swift Object Storagen ja yksinkertaisesti tiedostojärjestelmän kanssa. Koko asennus koostuu yksinkertaisista vaiheista, mutta koska sitä koskevat artikkelit ovat hajallaan Internetissä, ei ole täydellistä ohjekirjaa, joka sisältäisi kaikki vaiheet alusta loppuun (Habréssa on useita julkaisuja, mutta monet kohdat jäävät huomaamatta).

WAL-G: PostgreSQL DBMS:n varmuuskopiointi ja palautus

Tämä artikkeli on kirjoitettu ensisijaisesti tietoni systematisoimiseksi. En ole DBA ja voin ilmaista itseäni maallikon kielellä jossain, joten kaikki korjaukset ovat tervetulleita!

Huomaan erikseen, että kaikki alla oleva on relevanttia ja testattu PostgreSQL 12.3:lle Ubuntu 18.04:ssä, kaikki komennot on suoritettava etuoikeutetulla käyttäjällä.

Asennus

Tätä artikkelia kirjoitettaessa WAL-G:n vakaa versio on v0.2.15 (maaliskuu 2020). Tätä aiomme käyttää (mutta jos haluat rakentaa sen itse päähaaralta, niin github-arkistossa on kaikki ohjeet tähän). Ladataksesi ja asentaaksesi sinun on tehtävä:

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

Tämän jälkeen sinun on ensin määritettävä WAL-G ja sitten itse PostgreSQL.

WAL-G:n asetukset

Esimerkkinä varmuuskopioiden tallentamisesta käytetään Amazon S3:a (koska se on lähempänä palvelimiani ja sen käyttö on erittäin halpaa). Sen kanssa työskentelemiseen tarvitaan "s3-ämpäri" ja käyttöavaimet.

Kaikki aiemmat WAL-G:tä käsittelevät artikkelit käyttivät konfigurointia ympäristömuuttujien avulla, mutta tässä julkaisussa asetukset voidaan paikantaa .walg.json-tiedosto postgres-käyttäjän kotihakemistossa. Luo se suorittamalla seuraava 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

Selitän hieman kaikkia parametreja:

  • WALG_S3_PREFIX – polku S3-säilöisi, johon varmuuskopiot ladataan (voit joko juureen tai kansioon);
  • AWS_ACCESS_KEY_ID – pääsyavain S3:ssa (jos palautus tapahtuu testipalvelimella, näillä avaimilla on oltava vain luku -käytäntö! Tämä on kuvattu tarkemmin palautusta käsittelevässä osiossa.);
  • AWS_SECRET_ACCESS_KEY – salainen avain S3-muistissa;
  • WALG_COMPRESSION_METHOD - pakkausmenetelmä, on parempi käyttää Brotlia (koska tämä on kultainen keskitie lopullisen koon ja puristus-/dekompressionopeuden välillä);
  • WALG_DELTA_MAX_STEPS - "deltojen" lukumäärä ennen täyden varmuuskopion luomista (ne säästävät aikaa ja ladattujen tietojen kokoa, mutta voivat hidastaa palautusprosessia hieman, joten suuria arvoja ei suositella);
  • PGDATA - polku tietokantatietojesi sisältävään hakemistoon (voit selvittää suorittamalla komennon pg_lsclusters);
  • PGHOST – yhteys tietokantaan, paikallisella varmuuskopiolla on parempi tehdä se unix-socketin kautta kuten tässä esimerkissä.

Muut parametrit löytyvät dokumentaatiosta: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL:n määrittäminen

Jotta tietokannan sisällä oleva arkistaattori voi ladata WAL-lokit pilveen ja palauttaa ne niistä (tarvittaessa), sinun on asetettava useita parametreja määritystiedostoon /etc/postgresql/12/main/postgresql.conf. Ihan alkuun sinun täytyy varmistaaettä mitään alla olevista asetuksista ei ole asetettu muihin arvoihin, jotta DBMS ei kaatu, kun kokoonpano ladataan uudelleen. Voit lisätä nämä parametrit käyttämällä:

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

Kuvaus asetettavista parametreista:

  • wal_level – kuinka paljon tietoa kirjoitetaan WAL-lokeihin, “replica” – kirjoita kaikki;
  • archive_mode – salli WAL-lokien lataaminen parametrin komennolla archive_command;
  • archive_command – komento valmiin WAL-lokin arkistointiin;
  • archive_timeout – lokien arkistointi suoritetaan vasta kun se on valmis, mutta jos palvelimesi muuttaa/lisää vähän dataa tietokantaan, niin tässä on järkevää asettaa raja sekunneissa, jonka jälkeen arkistointikomento kutsutaan pakotettuna (Kirjoitan tietokantaan intensiivisesti joka sekunti, joten päätin olla asettamatta tätä parametria tuotannossa);
  • return_command – komentoa WAL-lokin palauttamiseksi varmuuskopiosta käytetään, jos "täydestä varmuuskopiosta" (perusvarmuuskopiosta) puuttuvat viimeisimmät muutokset tietokannassa.

Voit lukea lisää kaikista näistä parametreista virallisen dokumentaation käännöksestä: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Varmuuskopiointiaikataulun määrittäminen

Sanotaanpa mitä tahansa, kätevin tapa käyttää sitä on cron. Tämän määritämme varmuuskopioiden luomiseksi. Aloitetaan komennolla luoda täydellinen varmuuskopio: wal-g:ssä tämä on käynnistysargumentti varmuuskopiointi-push. Mutta ensin on parempi suorittaa tämä komento manuaalisesti postgres-käyttäjältä varmistaaksesi, että kaikki on kunnossa (eikä käyttövirheitä ole):

#!/bin/bash

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

Käynnistysargumentit osoittavat polun tietohakemistoon - Muistutan, että voit selvittää sen suorittamalla pg_lsclusters.

Jos kaikki meni ilman virheitä ja tiedot ladattiin S3-tallennustilaan, voit määrittää säännöllisen käynnistyksen crontabissa:

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

Tässä esimerkissä varmuuskopiointi alkaa joka päivä klo 4.

Vanhojen varmuuskopioiden poistaminen

Todennäköisesti sinun ei tarvitse säilyttää ehdottomasti kaikkia mesozoisen aikakauden varmuuskopioita, joten on hyödyllistä "siivota" ajoittain tallennustila (sekä "täydet varmuuskopiot" että WAL-lokit). Teemme tämän kaiken cron-tehtävän kautta:

#!/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 suorittaa tämän tehtävän joka päivä klo 6 ja poistaa kaiken (täydet varmuuskopiot, deltat ja WAL:t) paitsi kopiot viimeisen 30 päivän ajalta, mutta jättää ainakin yhden varmuuskopion. до määritetty päivämäärä niin, että missä tahansa kohdassa jälkeen päivämäärät sisällytettiin PITR:ään.

Palauttaminen varmuuskopiosta

Ei ole mikään salaisuus, että avain terveeseen tietokantaan on säännöllinen palauttaminen ja sisällä olevien tietojen eheyden tarkistaminen. Kerron tässä osiossa, kuinka palautus tapahtuu WAL-G:n avulla, ja keskustelemme tarkistuksista myöhemmin.

Erikseen, se on huomion arvoinen että palauttaaksesi testiympäristössä (kaikki, mikä ei ole tuotantoa), sinun on käytettävä vain luku -tiliä S3:ssa, jotta varmuuskopioita ei vahingossa korvata. WAL-G:n tapauksessa sinun on asetettava seuraavat oikeudet S3-käyttäjälle ryhmäkäytännössä (Vaikutus: Salli): s3: GetObject, s3:ListBucket, s3:GetBucketLocation. Ja tietenkään älä unohda asettaa archive_mode=off asetustiedostossa postgresql.conf, jotta testitietokantaasi ei haluta varmuuskopioida hiljaa.

Restaurointi suoritetaan kevyellä käden liikkeellä poistamalla kaikki PostgreSQL-tiedot (mukaan lukien käyttäjät), joten ole erittäin varovainen suorittaessasi seuraavia komentoja.

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

Niille, jotka haluavat tarkistaa palautusprosessin, alla on valmistettu pieni pala bash magiaa, jotta palautusongelmien sattuessa komentosarja kaatuu nollasta poikkeavalla poistumiskoodilla. Tässä esimerkissä tehdään 120 tarkistusta 5 sekunnin aikakatkaisulla (yhteensä 10 minuuttia palautumiseen) sen selvittämiseksi, onko signaalitiedosto poistettu (tämä tarkoittaa, että palautus onnistui):

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

Onnistuneen palautuksen jälkeen älä unohda käynnistää kaikkia prosesseja takaisin (pgbouncer/monit jne.).

Tietojen tarkistaminen palautuksen jälkeen

Tietokannan eheys on ehdottomasti tarkistettava palautuksen jälkeen, jotta ei synny tilannetta, jossa varmuuskopio on rikki. Ja on parempi tehdä tämä jokaisen luodun arkiston kanssa, mutta missä ja miten se riippuu vain mielikuvituksestasi (voit kasvattaa yksittäisiä palvelimia tuntikohtaisesti tai suorittaa tarkistuksen CI:ssä). Mutta vähintään on tarpeen tarkistaa tietokannan tiedot ja indeksit.

Tietojen tarkistamiseksi riittää ajaa se kaatokirjan läpi, mutta on parempi, että tietokantaa luotaessa on tarkistussummat käytössä (tietojen tarkistussummat):

#!/bin/bash

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

Indeksien tarkistaminen - on olemassa amcheck-moduuli, otetaan sen sql-kysely osoitteesta WAL-G testit ja rakenna vähän logiikkaa sen ympärille:

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

yhteenveto

Haluan ilmaista kiitokseni Andrey Borodinille hänen avustaan ​​julkaisun valmistelussa ja erityiskiitokset hänen panoksestaan ​​WAL-G:n kehittämisessä!

Tämä päättää tämän huomautuksen. Toivon, että pystyin välittämään asennuksen helppouden ja valtavan potentiaalin käyttää tätä työkalua yrityksessäsi. Olen kuullut paljon WAL-G:stä, mutta minulla ei ollut tarpeeksi aikaa istua alas ja selvittää se. Ja kun otin sen käyttöön kotona, tämä artikkeli tuli minusta.

Erikseen on syytä huomata, että WAL-G voi toimia myös seuraavien DBMS-järjestelmien kanssa:

Lähde: will.com

Lisää kommentti