WAL-G: afrit og endurheimt PostgreSQL DBMS

Það hefur lengi verið vitað að gera öryggisafrit í SQL dumpa (með því að nota pg_dump eða pg_dumpall) er ekki góð hugmynd. Til að taka öryggisafrit af PostgreSQL DBMS er betra að nota skipunina pg_basebackup, sem gerir tvöfalda afrit af WAL logs. En þegar þú byrjar að kynna þér allt ferlið við að búa til afrit og endurheimta, muntu skilja að þú þarft að skrifa að minnsta kosti nokkra þríhjól til að þetta virki og valda þér ekki sársauka bæði fyrir ofan og neðan. Til að lina þjáningar var WAL-G þróað.

WAL-G er tól skrifað í Go til að taka öryggisafrit og endurheimta PostgreSQL gagnagrunna (og nýlega MySQL/MariaDB, MongoDB og FoundationDB). Það styður að vinna með Amazon S3 geymslu (og hliðstæðum, til dæmis, Yandex Object Storage), sem og Google Cloud Storage, Azure Storage, Swift Object Storage og einfaldlega með skráarkerfinu. Öll uppsetningin kemur niður á einföldum skrefum, en vegna þess að greinar um það eru á víð og dreif um internetið, er engin fullkomin leiðbeiningahandbók sem myndi innihalda öll skrefin frá upphafi til enda (það eru nokkrar færslur á Habré, en þar vantar marga punkta).

WAL-G: afrit og endurheimt PostgreSQL DBMS

Þessi grein var skrifuð fyrst og fremst til að koma þekkingu minni á kerfi. Ég er ekki DBA og get tjáð mig á leikmannamáli einhvers staðar, svo allar leiðréttingar eru vel þegnar!

Sérstaklega tek ég fram að allt hér að neðan er viðeigandi og prófað fyrir PostgreSQL 12.3 á Ubuntu 18.04, allar skipanir verða að vera framkvæmdar sem forréttindanotandi.

Uppsetning

Þegar þessi grein er skrifuð er stöðuga útgáfan af WAL-G v0.2.15 (mars 2020). Þetta er það sem við munum nota (en ef þú vilt byggja það sjálfur frá master útibúinu, þá er github repository með allar leiðbeiningar fyrir þetta). Til að hlaða niður og setja upp þarftu að gera:

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

Eftir þetta þarftu fyrst að stilla WAL-G og síðan PostgreSQL sjálft.

Uppsetning WAL-G

Sem dæmi um að geyma afrit verður Amazon S3 notað (vegna þess að það er nær netþjónunum mínum og notkun þess er mjög ódýr). Til að vinna með það þarftu „s3 fötu“ og aðgangslykla.

Allar fyrri greinar um WAL-G notuðu stillingar með umhverfisbreytum, en með þessari útgáfu er hægt að finna stillingarnar í .walg.json skrá í heimaskrá postgres notandans. Til að búa það til skaltu keyra eftirfarandi bash skriftu:

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

Leyfðu mér að útskýra aðeins um allar breytur:

  • WALG_S3_PREFIX - slóðin að S3 fötunni þinni þar sem afritum verður hlaðið upp (þú getur annað hvort í rót eða í möppu);
  • AWS_ACCESS_KEY_ID – aðgangslykill í S3 (ef um endurheimt er að ræða á prófunarþjóni verða þessir lyklar að hafa ReadOnly Policy! Þessu er lýst nánar í kaflanum um endurheimt.);
  • AWS_SECRET_ACCESS_KEY – leynilykill í S3 geymslu;
  • WALG_COMPRESSION_METHOD – þjöppunaraðferð, það er betra að nota Brotli (þar sem þetta er hinn gullni meðalvegur á milli lokastærðar og þjöppunar/þjöppunarhraða);
  • WALG_DELTA_MAX_STEPS – fjölda „delta“ áður en búið er að búa til fullt öryggisafrit (þau spara tíma og stærð niðurhalaðra gagna, en geta aðeins hægt á bataferlinu, svo það er ekki ráðlegt að nota stór gildi);
  • PGDATA - slóð að möppunni með gagnagrunnsgögnunum þínum (þú getur komist að því með því að keyra skipunina pg_lsþyrpingar);
  • PGHOST – tenging við gagnagrunninn, með staðbundnu öryggisafriti er betra að gera það í gegnum unix-socket eins og í þessu dæmi.

Aðrar breytur má finna í skjölunum: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

Stillir PostgreSQL

Til þess að skjalavörðurinn inni í gagnagrunninum geti hlaðið inn WAL-skrám í skýið og endurheimt þá úr þeim (ef nauðsyn krefur), þarftu að stilla nokkrar breytur í stillingarskránni /etc/postgresql/12/main/postgresql.conf. Bara svona til að byrja með þú þarft að ganga úr skugga umað engin af stillingunum hér að neðan er stillt á önnur gildi, þannig að þegar uppsetningin er endurhlaðin hrynur DBMS ekki. Þú getur bætt við þessum breytum með því að nota:

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

Lýsing á færibreytum sem á að stilla:

  • wall_level - hversu mikið af upplýsingum á að skrifa í WAL logs, "eftirmynd" - skrifaðu allt;
  • skjalasafn_hamur – virkjaðu niðurhal á WAL annálum með því að nota skipunina frá færibreytunni skjalasafn_skipun;
  • skjalasafn_skipun – skipun til að geyma útfyllta WAL annál;
  • geymslutími – geymslu annála er aðeins framkvæmd þegar henni er lokið, en ef þjónninn þinn breytir/bætir litlum gögnum við gagnagrunninn, þá er skynsamlegt að setja hér takmörk á sekúndum, eftir það verður geymsluskipunin kölluð með valdi (Ég skrifa ákaft í gagnagrunninn á hverri sekúndu, svo ég ákvað að setja þessa breytu ekki í framleiðslu);
  • endurheimta_skipun – skipunin til að endurheimta WAL log úr öryggisafriti verður notuð ef „full öryggisafrit“ (grunnafrit) vantar nýjustu breytingarnar í gagnagrunninum.

Þú getur lesið meira um allar þessar breytur í þýðingu opinberu skjala: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Að setja upp afritunaráætlun

Hvað sem maður getur sagt, þá er þægilegasta leiðin til að keyra það cron. Þetta er það sem við munum stilla til að búa til afrit. Byrjum á skipuninni til að búa til fullt öryggisafrit: í wal-g er þetta upphafsrök vara-ýta. En fyrst, það er betra að keyra þessa skipun handvirkt frá postgres notandanum til að ganga úr skugga um að allt sé í lagi (og það eru engar aðgangsvillur):

#!/bin/bash

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

Ræstu rökin gefa til kynna slóðina að gagnaskránni - ég minni á að þú getur fundið það út með því að keyra pg_lsþyrpingar.

Ef allt gekk án villna og gögnunum var hlaðið inn í S3 geymslu, þá geturðu stillt reglulega ræsingu í 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

Í þessu dæmi byrjar afritunarferlið á hverjum degi klukkan 4:15.

Eyðir gömlum afritum

Líklegast þarftu ekki að geyma algerlega öll afrit frá Mesózoic tímum, svo það mun vera gagnlegt að „hreinsa“ geymsluna þína reglulega (bæði „full öryggisafrit“ og WAL logs). Við munum gera þetta allt í gegnum cron verkefni:

#!/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 mun keyra þetta verkefni á hverjum degi klukkan 6:30 að morgni og eyða öllu (fullu afriti, deltas og WALs) nema afritum síðustu 10 daga, en skilja eftir að minnsta kosti eitt öryggisafrit í tilgreind dagsetning þannig að einhver liður eftir dagsetningar voru innifaldar í PITR.

Endurheimt úr öryggisafriti

Það er ekkert leyndarmál að lykillinn að heilbrigðum gagnagrunni er reglubundin endurheimt og sannprófun á heilleika gagna inni. Ég skal segja þér hvernig á að endurheimta með WAL-G í þessum hluta og við munum tala um athuganir síðar.

Það skal tekið sérstaklega fram að til að endurheimta í prófunarumhverfi (allt sem er ekki framleiðsla) þarftu að nota Read Only reikning í S3 til að skrifa ekki óvart yfir afrit. Ef um WAL-G er að ræða þarftu að stilla eftirfarandi réttindi fyrir S3 notandann í Group Policy (Áhrif: Leyfa): s3: GetObject, s3:ListBucket, s3:GetBucketLocation. Og, auðvitað, ekki gleyma að stilla archive_mode=slökkt í stillingaskránni postgresql.conf, svo að prófunargagnagrunnurinn þinn vilji ekki afrita hljóðlega.

Endurreisn er framkvæmd með örlítilli hreyfingu á hendi eyða öllum PostgreSQL gögnum (þar á meðal notendur), svo vertu mjög varkár þegar þú keyrir eftirfarandi skipanir.

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

Fyrir þá sem vilja athuga bataferlið, þá hefur verið útbúið lítið stykki af bash-töfrum hér að neðan, þannig að ef vandamál koma upp í bata, mun handritið hrynja með útgöngukóða sem er ekki núll. Í þessu dæmi eru 120 athuganir með 5 sekúndum tíma (samtals 10 mínútur fyrir endurheimt) til að komast að því hvort merkjaskránni hafi verið eytt (þetta þýðir að endurheimt hefur tekist):

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

Eftir árangursríka bata, ekki gleyma að hefja alla ferla aftur (pgbouncer/monit, osfrv.).

Athugun gagna eftir endurheimt

Nauðsynlegt er að athuga heilleika gagnagrunnsins eftir endurheimt, svo að ekki komi upp staða með bilað/skakkt öryggisafrit. Og það er betra að gera þetta með hverri stofnuðu skjalasafni, en hvar og hvernig fer aðeins eftir ímyndunaraflinu þínu (þú getur hækkað einstaka netþjóna á klukkutíma fresti eða keyrt inn á CI). En að minnsta kosti er nauðsynlegt að athuga gögn og vísitölur í gagnagrunninum.

Til að athuga gögnin er nóg að keyra þau í gegnum dump, en það er betra að þegar þú býrð til gagnagrunninn hafiðu eftirlitssummur virkar (gagnaeftirlitssumman):

#!/bin/bash

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

Til að athuga vísitölur - er til amcheck mát, við skulum taka sql fyrirspurnina um það frá WAL-G próf og byggðu smá rökfræði í kringum það:

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

Til að draga saman

Mig langar að koma á framfæri þakklæti til Andrey Borodin fyrir aðstoð hans við undirbúning útgáfunnar og sérstakar þakkir fyrir framlag hans til þróunar WAL-G!

Þetta lýkur þessari aths. Ég vona að mér hafi tekist að koma á framfæri auðveldri uppsetningu og miklum möguleikum á að nota þetta tól í fyrirtækinu þínu. Ég heyrði mikið um WAL-G, en hafði aldrei nægan tíma til að setjast niður og finna út úr því. Og eftir að ég útfærði það heima kom þessi grein út úr mér.

Sérstaklega er vert að hafa í huga að WAL-G getur einnig unnið með eftirfarandi DBMS:

Heimild: www.habr.com

Bæta við athugasemd