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).
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ä:
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:
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.);
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);
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ä:
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.
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:
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: