WAL-G: PostgreSQL DBMS-i varukoopiad ja taastamine

Juba ammu on teada, et varukoopiate tegemine SQL-i tõmmistesse (kasutades pg_dump või pg_dumpall) pole hea mõte. PostgreSQL DBMS-i varundamiseks on parem kasutada käsku pg_basebackup, mis teeb WAL-i logidest binaarkoopia. Kuid kui hakkate uurima kogu koopia loomise ja taastamise protsessi, saate aru, et peate kirjutama vähemalt paar kolmerattalist jalgratast, et see toimiks ja ei tekitaks teile valu nii ülalt kui ka all. Kannatuste leevendamiseks töötati välja WAL-G.

WAL-G on Go-s kirjutatud tööriist PostgreSQL-i andmebaaside varundamiseks ja taastamiseks (ja hiljuti MySQL/MariaDB, MongoDB ja FoundationDB). See toetab tööd Amazon S3 salvestusruumiga (ja analoogidega, näiteks Yandex Object Storage), aga ka Google Cloud Storage, Azure Storage, Swift Object Storage ja lihtsalt failisüsteemiga. Kogu seadistamine taandub lihtsatele sammudele, kuid kuna seda käsitlevad artiklid on Internetis laiali, pole täielikku juhendit, mis hõlmaks kõiki samme algusest lõpuni (Habré lehel on mitu postitust, kuid paljud punktid jäävad seal vahele).

WAL-G: PostgreSQL DBMS-i varukoopiad ja taastamine

See artikkel on kirjutatud eelkõige minu teadmiste süstematiseerimiseks. Ma ei ole DBA ja oskan end kuskil võhikukeeles väljendada, seega kõik parandused on teretulnud!

Eraldi märgin, et kõik allolev on asjakohane ja testitud PostgreSQL 12.3 jaoks Ubuntu 18.04-s, kõik käsud tuleb täita privilegeeritud kasutajana.

Paigaldamine

Selle artikli kirjutamise ajal oli WAL-G stabiilne versioon v0.2.15 (märts 2020). Seda me kasutame (aga kui tahad selle ise põhiharust ehitada, siis githubi hoidlas on selleks kõik juhised). Allalaadimiseks ja installimiseks peate tegema järgmist:

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

Pärast seda peate kõigepealt konfigureerima WAL-G ja seejärel PostgreSQLi enda.

WAL-G seadistamine

Varukoopiate salvestamise näitena kasutatakse Amazon S3 (kuna see on minu serveritele lähemal ja selle kasutamine on väga odav). Sellega töötamiseks vajate "s3 ämbrit" ja juurdepääsuklahve.

Kõik varasemad artiklid WAL-G kohta kasutasid konfigureerimist keskkonnamuutujate abil, kuid selle väljalaskega saab seadistusi leida .walg.json faili postgresi kasutaja kodukataloogis. Selle loomiseks käivitage järgmine bash-skript:

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

Lubage mul selgitada veidi kõiki parameetreid:

  • WALG_S3_PREFIX – tee teie S3 ämbrisse, kuhu varukoopiad üles laaditakse (saate kas juure või kausta);
  • AWS_ACCESS_KEY_ID – juurdepääsuvõti S3-s (testserveris taastamise korral peab neil võtmetel olema kirjutuskaitstud poliitika! Seda kirjeldatakse üksikasjalikumalt taastamise jaotises.);
  • AWS_SECRET_ACCESS_KEY – salajane võti S3-mälus;
  • WALG_COMPRESSION_METHOD – tihendusmeetod, parem on kasutada Brotlit (kuna see on kuldne keskmine lõppsuuruse ja tihendus/dekompressioonikiiruse vahel);
  • WALG_DELTA_MAX_STEPS – "deltade" arv enne täieliku varukoopia loomist (need säästavad aega ja allalaaditud andmete suurust, kuid võivad taastamisprotsessi veidi aeglustada, mistõttu ei ole soovitatav kasutada suuri väärtusi);
  • PGDATA – tee andmebaasi andmetega kataloogi (saate teada, käivitades käsu pg_lsclusters);
  • PGHOST – andmebaasiga ühendumine, kohaliku varukoopiaga on parem seda teha unix-socketi kaudu nagu antud näites.

Muud parameetrid leiate dokumentatsioonist: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL-i seadistamine

Selleks, et andmebaasi sees olev arhiveerija saaks WAL-i logid pilve üles laadida ja neist (vajadusel) taastada, tuleb konfiguratsioonifailis määrata mitu parameetrit /etc/postgresql/12/main/postgresql.conf. Alustuseks peate veendumaet ükski allolevatest sätetest pole seatud muudele väärtustele, nii et konfiguratsiooni uuesti laadimisel ei jookseks DBMS kokku. Saate neid parameetreid lisada, kasutades:

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

Määratavate parameetrite kirjeldus:

  • wal_level – kui palju infot WAL logidesse kirjutada, “replica” – kirjuta kõik;
  • arhiivi_režiim – lubage WAL-logide allalaadimine, kasutades parameetri käsku arhiivi_käsk;
  • arhiivi_käsk – käsk täidetud WAL logi arhiveerimiseks;
  • archive_timeout – logide arhiveerimine toimub alles siis, kui see on lõpetatud, aga kui sinu server muudab/lisab andmebaasi vähe andmeid, siis on siin mõtekas seada limiit sekundites, mille järel kutsutakse arhiveerimiskäsk sunniviisiliselt (Kirjutan andmebaasi intensiivselt iga sekund, mistõttu otsustasin seda parameetrit tootmises mitte määrata);
  • taastamise_käsk – WAL-logi varukoopiast taastamise käsku kasutatakse juhul, kui "täielikus varukoopias" (baasvarukoopias) puuduvad andmebaasis viimased muudatused.

Lisateavet kõigi nende parameetrite kohta saate ametliku dokumentatsiooni tõlkest: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Varundusgraafiku seadistamine

Mida iganes võib öelda, kõige mugavam viis selle käitamiseks on cron. Selle konfigureerime varukoopiate loomiseks. Alustame täieliku varukoopia loomise käsuga: wal-g-s on see käivitamise argument backup-push. Kuid kõigepealt on parem käivitada see käsk postgresi kasutajalt käsitsi, et veenduda, et kõik on korras (ja juurdepääsuvigu pole):

#!/bin/bash

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

Käivitusargumendid näitavad teed andmekataloogi - tuletan meelde, et selle saate teada käivitades pg_lsclusters.

Kui kõik läks vigadeta ja andmed laaditi S3 salvestusruumi, saate seejärel konfigureerida perioodilise käivitamise crontabis:

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

Selles näites algab varundusprotsess iga päev kell 4:15.

Vanade varukoopiate kustutamine

Tõenäoliselt ei pea te säilitama absoluutselt kõiki mesosoikumi ajastu varukoopiaid, seega on kasulik oma salvestusruumi perioodiliselt "puhastada" (nii "täielikud varukoopiad" kui ka WAL-i logid). Teeme seda kõike cron-ülesande kaudu:

#!/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 käivitab selle ülesande iga päev kell 6, kustutades kõik (täielikud varukoopiad, deltad ja WAL-id), välja arvatud viimase 30 päeva koopiad, kuid jättes alles vähemalt ühe varukoopia kuni määratud kuupäeva nii, et mis tahes punkt pärast kuupäevad lisati PITR-i.

Taastamine varukoopiast

Pole saladus, et terve andmebaasi võti on perioodiline taastamine ja sees olevate andmete terviklikkuse kontrollimine. Selles jaotises räägin teile, kuidas taastada WAL-G abil, ja tšekkidest räägime hiljem.

Eraldi tuleks seda märkida et testkeskkonnas taastamiseks (kõik, mis pole tootmist), peate S3-s kasutama kirjutuskaitstud kontot, et mitte kogemata varukoopiaid üle kirjutada. WAL-G puhul peate rühmapoliitikas määrama S3 kasutajale järgmised õigused (Mõju: Luba): s3: GetObject, s3:ListBucket, s3:GetBucketLocation. Ja muidugi ärge unustage seadistada archive_mode=off seadete failis postgresql.conf, et teie testandmebaas ei taha vaikselt varundada.

Taastamine toimub kerge käeliigutusega kõigi PostgreSQL-i andmete kustutamine (kaasa arvatud kasutajad), seega olge järgmiste käskude käivitamisel äärmiselt ettevaatlik.

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

Neile, kes soovivad taasteprotsessi kontrollida, on allpool ette valmistatud väike tükike bash-maagiat, et taastamise probleemide korral jookseb skript nullist erineva väljumiskoodiga kokku. Selles näites tehakse 120 kontrolli 5-sekundilise ajalõpuga (kokku 10 minutit taastamiseks), et teha kindlaks, kas signaalifail on kustutatud (see tähendab, et taastamine oli edukas):

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

Pärast edukat taastumist ärge unustage kõiki protsesse tagasi käivitada (pgbouncer/monit jne).

Andmete kontrollimine pärast taastamist

Pärast taastamist tuleb kindlasti kontrollida andmebaasi terviklikkust, et ei tekiks katkise/kõvera varukoopiaga olukorda. Ja parem on seda teha iga loodud arhiiviga, kuid kus ja kuidas, sõltub ainult teie kujutlusvõimest (saate üksikuid servereid tunnipõhiselt tõsta või CI-s kontrollida). Kuid vähemalt on vaja andmebaasis olevaid andmeid ja indekseid kontrollida.

Andmete kontrollimiseks piisab, kui käivitate need läbi prügimäe, kuid parem on, kui andmebaasi loomisel on lubatud kontrollsummad (andmete kontrollsummad):

#!/bin/bash

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

Indekside kontrollimiseks - on olemas amchecki moodul, võtame selle jaoks SQL-i päringu WAL-G testid ja ehitage selle ümber väike loogika:

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

Kokku võtma

Tahaksin avaldada tänu Andrei Borodinile abi eest väljaande ettevalmistamisel ja erilist tänu tema panuse eest WAL-G arendamisse!

Sellega on käesolev märkus lõpetatud. Loodan, et suutsin edasi anda seadistamise lihtsust ja tohutut potentsiaali selle tööriista kasutamisel teie ettevõttes. Ma kuulsin palju WAL-G-st, kuid pole kunagi olnud piisavalt aega, et maha istuda ja sellest aru saada. Ja pärast seda, kui ma selle kodus rakendasin, tuli see artikkel minust välja.

Eraldi väärib märkimist, et WAL-G saab töötada ka järgmiste DBMS-idega:

Allikas: www.habr.com

Lisa kommentaar