WAL-G: kopje rezervë dhe rikuperimi i PostgreSQL DBMS

Prej kohësh dihet se krijimi i kopjeve rezervë në deponitë SQL (duke përdorur pg_dump ose pg_dumpall) nuk është një ide e mirë. Për të kopjuar postgreSQL DBMS, është më mirë të përdorni komandën pg_basebackup, e cila bën një kopje binare të regjistrave të WAL. Por kur të filloni të studioni të gjithë procesin e krijimit të një kopjeje dhe restaurimit, do të kuptoni se duhet të shkruani të paktën disa triçikleta që kjo të funksionojë dhe të mos ju shkaktojë dhimbje si sipër ashtu edhe poshtë. Për të lehtësuar vuajtjet, u zhvillua WAL-G.

WAL-G është një mjet i shkruar në Go për rezervimin dhe rivendosjen e bazave të të dhënave PostgreSQL (dhe së fundmi MySQL/MariaDB, MongoDB dhe FoundationDB). Ai mbështet punën me ruajtjen e Amazon S3 (dhe analoge, për shembull, Yandex Object Storage), si dhe Google Cloud Storage, Azure Storage, Swift Object Storage dhe thjesht me sistemin e skedarëve. I gjithë konfigurimi zbret në hapa të thjeshtë, por për shkak të faktit se artikujt në lidhje me të janë të shpërndara në internet, nuk ka një manual të plotë se si duhet të përfshijë të gjithë hapat nga fillimi në fund (ka disa postime në Habré, por aty mungojnë shumë pika).

WAL-G: kopje rezervë dhe rikuperimi i PostgreSQL DBMS

Ky artikull është shkruar kryesisht për të sistemuar njohuritë e mia. Unë nuk jam një DBA dhe mund të shprehem në gjuhën laike diku, kështu që çdo korrigjim është i mirëpritur!

Më vete, vërej se gjithçka më poshtë është e rëndësishme dhe e testuar për PostgreSQL 12.3 në Ubuntu 18.04, të gjitha komandat duhet të ekzekutohen si përdorues i privilegjuar.

Instalim

Në kohën e shkrimit të këtij artikulli, versioni i qëndrueshëm i WAL-G është v0.2.15 (mars 2020). Kjo është ajo që ne do të përdorim (por nëse doni ta ndërtoni vetë nga dega master, atëherë depoja e github ka të gjitha udhëzimet për këtë). Për të shkarkuar dhe instaluar duhet të bëni:

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

Pas kësaj, së pari duhet të konfiguroni WAL-G, dhe më pas vetë PostgreSQL.

Vendosja e WAL-G

Për një shembull të ruajtjes së kopjeve rezervë, do të përdoret Amazon S3 (sepse është më afër serverëve të mi dhe përdorimi i tij është shumë i lirë). Për të punuar me të, ju nevojitet një "kovë s3" dhe çelësat e hyrjes.

Të gjithë artikujt e mëparshëm rreth WAL-G përdorën konfigurimin duke përdorur variablat e mjedisit, por me këtë version cilësimet mund të vendosen në Skedari .walg.json në drejtorinë kryesore të përdoruesit të postgres. Për ta krijuar atë, ekzekutoni skriptin e mëposhtëm bash:

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

Më lejoni të shpjegoj pak për të gjithë parametrat:

  • WALG_S3_PREFIX – shtegun për në kovën tuaj S3 ku do të ngarkohen kopjet rezervë (mundeni ose në rrënjë ose në një dosje);
  • AWS_ACCESS_KEY_ID – çelësi i hyrjes në S3 (në rast rikuperimi në një server provë, këta çelësa duhet të kenë Politikë ReadOnly! Kjo përshkruhet më në detaje në seksionin mbi rikuperimin.);
  • AWS_SECRET_ACCESS_KEY – çelësi sekret në ruajtjen e S3;
  • WALG_COMPRESSION_METHOD – metoda e kompresimit, është më mirë të përdoret Brotli (pasi kjo është mesatarja e artë midis madhësisë përfundimtare dhe shpejtësisë së ngjeshjes/dekompresimit);
  • WALG_DELTA_MAX_HAPA – numri i “deltas” përpara krijimit të një kopje rezervë të plotë (ato kursejnë kohë dhe madhësinë e të dhënave të shkarkuara, por mund të ngadalësojnë pak procesin e rikuperimit, kështu që nuk këshillohet përdorimi i vlerave të mëdha);
  • PGDATA – rruga drejt drejtorisë me të dhënat tuaja të bazës së të dhënave (mund ta zbuloni duke ekzekutuar komandën pg_lsclusters);
  • PGHOST – Lidhja me bazën e të dhënave, me një kopje rezervë lokale është më mirë ta bëni atë përmes një fole unix si në këtë shembull.

Parametrat e tjerë mund të gjenden në dokumentacion: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

Konfigurimi i PostgreSQL

Në mënyrë që arkivi brenda bazës së të dhënave të ngarkojë regjistrat e WAL në cloud dhe t'i rivendosë ato prej tyre (nëse është e nevojshme), duhet të vendosni disa parametra në skedarin e konfigurimit /etc/postgresql/12/main/postgresql.conf. Vetëm për fillim ju duhet të siguroheniqë asnjë nga cilësimet e mëposhtme nuk është vendosur në ndonjë vlerë tjetër, në mënyrë që kur konfigurimi të ringarkohet, DBMS të mos prishet. Ju mund t'i shtoni këto parametra duke përdorur:

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

Përshkrimi i parametrave që do të vendosen:

  • niveli_wal – sa informacion për të shkruar në regjistrat e WAL, “kopje” – shkruani gjithçka;
  • arkiv_mode – aktivizoni shkarkimin e regjistrave të WAL duke përdorur komandën nga parametri arkivi_komandë;
  • arkivi_komandë – komanda për arkivimin e një regjistri të plotësuar të WAL;
  • arkiv_koha – arkivimi i regjistrave kryhet vetëm kur të përfundojë, por nëse serveri juaj ndryshon/shton pak të dhëna në bazën e të dhënave, atëherë ka kuptim të vendosni një kufi këtu në sekonda, pas së cilës komanda e arkivimit do të thirret me forcë (Unë shkruaj intensivisht në bazën e të dhënave çdo sekondë, kështu që vendosa të mos e vendos këtë parametër në prodhim);
  • restore_command – komanda për të rivendosur regjistrin e WAL nga një kopje rezervë do të përdoret nëse "backup-i i plotë" (backup bazë) i mungojnë ndryshimet më të fundit në bazën e të dhënave.

Ju mund të lexoni më shumë rreth të gjithë këtyre parametrave në përkthimin e dokumentacionit zyrtar: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Vendosja e një plani rezervë

Çfarëdo që mund të thuhet, mënyra më e përshtatshme për ta drejtuar atë është cron. Kjo është ajo që ne do të konfigurojmë për të krijuar kopje rezervë. Le të fillojmë me komandën për të krijuar një kopje rezervë të plotë: në wal-g ky është argumenti i nisjes rezervë-shtytje. Por së pari, është më mirë ta ekzekutoni këtë komandë manualisht nga përdoruesi i postgres për t'u siguruar që gjithçka është në rregull (dhe nuk ka gabime në hyrje):

#!/bin/bash

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

Argumentet e nisjes tregojnë shtegun për në drejtorinë e të dhënave - ju kujtoj se mund ta zbuloni duke ekzekutuar pg_lsclusters.

Nëse gjithçka shkoi pa gabime dhe të dhënat u ngarkuan në ruajtjen e S3, atëherë mund të konfiguroni nisjen periodike në 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

Në këtë shembull, procesi i rezervimit fillon çdo ditë në orën 4:15 të mëngjesit.

Fshirja e kopjeve rezervë të vjetra

Me shumë mundësi, nuk keni nevojë të mbani absolutisht të gjitha kopjet rezervë nga epoka mezozoike, kështu që do të jetë e dobishme që periodikisht të "pastroni" ruajtjen tuaj (si "kopje të plota" dhe regjistrat e WAL). Ne do ta bëjmë këtë të gjithë përmes një detyre kronike:

#!/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 do ta ekzekutojë këtë detyrë çdo ditë në orën 6:30 të mëngjesit, duke fshirë gjithçka (kopjet rezervë të plotë, deltat dhe WAL) përveç kopjeve për 10 ditët e fundit, por duke lënë të paktën një kopje rezervë tek datë të caktuar në mënyrë që çdo pikë pas datat janë përfshirë në PITR.

Rivendosja nga një kopje rezervë

Nuk është sekret që çelësi për një bazë të dhënash të shëndetshme është restaurimi periodik dhe verifikimi i integritetit të të dhënave brenda. Unë do t'ju tregoj se si të rikuperoni duke përdorur WAL-G në këtë seksion, dhe ne do të flasim për kontrollet më vonë.

Duhet të shënohet veçmas që për të rivendosur në një mjedis testimi (gjithçka që nuk është prodhim) duhet të përdorni një llogari Read Only në S3 në mënyrë që të mos mbishkruani aksidentalisht kopjet rezervë. Në rastin e WAL-G, ju duhet të vendosni të drejtat e mëposhtme për përdoruesin S3 në Politikën e Grupit (Efekti: Lejo): s3: GetObject, s3:ListBucket, s3: GetBucketLocation. Dhe, sigurisht, mos harroni të vendosni archive_mode=off në skedarin e cilësimeve postgresql.conf, në mënyrë që databaza juaj e testimit të mos dëshirojë të kopjohet në heshtje.

Restaurimi kryhet me një lëvizje të lehtë të dorës fshirja e të gjitha të dhënave PostgreSQL (përfshirë përdoruesit), kështu që ju lutemi të jeni jashtëzakonisht të kujdesshëm kur ekzekutoni komandat e mëposhtme.

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

Për ata që duan të kontrollojnë procesin e rikuperimit, më poshtë është përgatitur një pjesë e vogël e magjisë bash, në mënyrë që në rast të problemeve në rikuperim, skripti të rrëzohet me një kod daljeje jo zero. Në këtë shembull, bëhen 120 kontrolle me një afat kohor prej 5 sekondash (gjithsej 10 minuta për rikuperim) për të zbuluar nëse skedari i sinjalit është fshirë (kjo do të thotë që rikuperimi ishte i suksesshëm):

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

Pas rikuperimit të suksesshëm, mos harroni të rifilloni të gjitha proceset (pgbouncer/monit, etj.).

Kontrollimi i të dhënave pas rikuperimit

Është e domosdoshme të kontrollohet integriteti i bazës së të dhënave pas restaurimit, në mënyrë që të mos lindë një situatë me një kopje rezervë të prishur/të shtrembër. Dhe është më mirë ta bëni këtë me çdo arkiv të krijuar, por ku dhe si varet vetëm nga imagjinata juaj (mund të ngrini serverë individualë çdo orë ose të kryeni një kontroll në CI). Por së paku, është e nevojshme të kontrolloni të dhënat dhe indekset në bazën e të dhënave.

Për të kontrolluar të dhënat, mjafton t'i kaloni ato përmes një hale, por është më mirë që kur krijoni bazën e të dhënave të keni aktivizuar kontrollet (shumat e kontrollit të të dhënave):

#!/bin/bash

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

Për të kontrolluar indekset - ekziston moduli amcheck, le të marrim pyetjen sql për të Testet WAL-G dhe ndërto pak logjikë rreth saj:

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

Për të përmbledhur

Dua të shpreh mirënjohjen time për Andrey Borodin për ndihmën e tij në përgatitjen e botimit dhe falënderime të veçanta për kontributin e tij në zhvillimin e WAL-G!

Kjo përfundon këtë shënim. Shpresoj se kam qenë në gjendje të përcjell lehtësinë e konfigurimit dhe potencialin e madh për përdorimin e këtij mjeti në kompaninë tuaj. Kam dëgjuar shumë për WAL-G, por kurrë nuk kam pasur kohë të mjaftueshme për t'u ulur dhe për ta kuptuar. Dhe pasi e zbatova në shtëpi, më doli ky artikull.

Më vete, vlen të përmendet se WAL-G gjithashtu mund të punojë me DBMS-të e mëposhtme:

Burimi: www.habr.com

Shto një koment