WAL-G: backup dhe rikuperim i DBMS PostgreSQL

Kahetë e fundit është se bëja e backup-eve në SQL-dumps (duke përdorur pg_dump ose pg_dumpall) nuk është ideja më e mirë. Për backup-in e bazës së të dhënave PostgreSQL, më mirë është të përdorni komandën pg_basebackup, e cila krijon një kopje binar të regjistrave WAL. Por kur filloni të studioni tërë procesin e krijimit të kopjeve dhe rikthimit, do të kuptoni se duhet të shkruani të paktën disa biçikleta me tri rrota, që gjithçka të funksionojë dhe të mos ju shkaktojë dhimbje as lart, as poshtë. Për të lehtësuar vuajtjet, u zhvillua WAL-G.

WAL-G – është një mjet i shkruar në Go për backup dhe rikthim të bazave të të dhënave PostgreSQL (dhe së fundmi edhe për MySQL/MariaDB, MongoDB dhe FoundationDB). Ai mbështet punën me ruajtjet 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. Të gjitha konfigurimet reduktohen në disa hapa të thjeshtë, por për shkak se artikujt mbi të janë të shpërndarë në internet – nuk ka një manual të plotë how-to, i cili do të përfshinte të gjitha hapat nga fillimi deri në mbarim (në Habrë ka disa postime, por shumë pika janë lënë jashtë).

WAL-G: backup dhe rikuperim i DBMS PostgreSQL

Ky artikull është shkruar kryesisht për të sistematizuar njohuritë e mia. Unë nuk jam DBA dhe ndonjëherë mund të shprehem në një gjuhë më të thjeshtë zhvillimi, prandaj mirëpriten çdo korrigjim!

Dua të theksoj se çdo gjë e përmendur më poshtë është e aplicueshme dhe e verifikuar për PostgreSQL 12.3 në Ubuntu 18.04, të gjitha komandat duhet të ekzekutohen nga një përdorues me privilegje.

Instalimi

Në momentin e shkruajtjes së këtij artikulli, versioni stabil i WAL-G është v0.2.15 (mars 2020). Ne do ta përdorim atë (por nëse dëshironi ta ndërtoni vetë nga dega master, më shumë informata për këtë gjeni në repozitorin në github). Për të shkarkuar dhe instaluar, ju lutem 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/

Pasi të përfundojë, duhet të konfiguroni fillimisht WAL-G, pastaj PostgreSQL vetë.

Konfigurimi i WAL-G

Për shembull, për ruajtjen e backup-eve do të përdoren 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ë nevojitet një „s3-bucket“ dhe çelësat e aksesit.

Në të gjitha artikujt e mëparshëm mbi WAL-G, është përdorur konfigurimi me ndihmën e variablave të mjedisit, por nga ky version, konfigurimet mund të vendosen në .walg.json skedari në direktorinë shtëpiake të përdoruesit postgres. Për ta krijuar atë, ekzekutoni skenarin 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

Pak shpjegim për të gjithë parametrat:

  • WALG_S3_PREFIX – rruga në bucket-in tuaj S3 ku do të ngarkohen backup-et (mund të jetë në rrënjë ose në një dosje);
  • AWS_ACCESS_KEY_ID – çelësi i aksesit në S3 (në rastin e rikthimit në një server provues – këto çelësa duhet të kenë Politiken ReadOnly! Më shumë për këtë është shkruar në seksionin mbi rikthimin);
  • AWS_SECRET_ACCESS_KEY – çelësi sekret në ruajtjen S3;
  • WALG_COMPRESSION_METHOD – metoda e kompresimit, më mirë të përdorni Brotli (sepse është një mesatar i mirë midis madhësisë përfundimtare dhe shpejtësisë së kompresimit/dekompresimit);
  • WALG_DELTA_MAX_STEPS – numri i "deltave" përpara se të krijohet një backup i plotë (ndihmojnë të kursejnë kohën dhe madhësinë e të dhënave të ngarkuara, por mund të ngadalësojnë pak procesin e rikthimit, prandaj nuk është mirë të përdoren vlera të mëdha);
  • PGDATA – rruga në direktorinë me të dhënat e bazës tuaj (mund të gjeni këtë duke ekzekutuar komandën pg_lsclusters);
  • PGHOST – lidhja me bazën, për backup lokal më mirë është ta bëni përmes unix-socket si në këtë shembull.

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

Konfigurimi i PostgreSQL

Që arkivuesi brenda bazës ta ngarkojë vetë regjistrat WAL në cloud dhe të rikthehet nga ata (në rast nevoje) – duhet të caktoni disa parametra në skedarin e konfigurimit /etc/postgresql/12/main/postgresql.conf. Së pari është e rëndësishme të siguroheni, se asnjë nga parametrat e mëposhtëm nuk janë caktuar në ndonjë vlerë tjetër, në mënyrë që gjatë ri-ngarkimit të konfiguracionit – DBMS të mos bjerë. Mund t'i shtoni këta 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ë vendosen:

  • wal_level – sa informacioni të shkruhet në regjistrat WAL, "replica" – shkruani gjithçka;
  • archive_mode – aktivizimi i ngarkimit të regjistrave WAL duke përdorur komandën nga parametri archive_command;
  • archive_command – komanda, për arkivimin e regjistrit të përfunduar WAL;
  • archive_timeout – arkivimi i regjistrave bëhet vetëm kur ai është përfunduar, por nëse serveri juaj modifikon/shton pak të dhëna në DB, ka kuptim të vendosni një kufi në sekonda, pas kalimit të të cilit komanda e arkivimit do të thirret me forcë (unë kam regjistrim intensiv në bazë çdo sekonde, kështu që e kam anashkaluar caktimin e këtij parametri në prodhim);
  • restore_command – komanda për rikthimin e regjistrit WAL nga backup-i, që do të përdoret në rast se në "backupin e plotë" (base backup) mungojnë ndryshimet e fundit në DB.

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

Konfigurimi i orarit të backup-it

Megjithëse është çështje diskutimi, mënyra më e thjeshtë për të nisur është cron. Pikërisht atë do ta konfiguroni për të krijuar kopje rezervë. Të fillojmë me komandën për të bërë një kopje të plotë rezervë: në wal-g ky është argumenti i nisjes backup-push. Por më parë është më mirë ta ekzekutoni këtë komandë manualisht nga përdoruesi postgres, për të siguruar që gjithçka shkon mirë (dhe nuk ka ndonjë gabim aksesimi):

#!/bin/bash

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

Në argumentet e nisjes është e specifikuar rruga për deri tek direktoria e të dhënave – kujtoj se mund ta zbuloni atë duke ekzekutuar pg_lsclusters.

Nëse gjithçka shkoi pa gabime dhe të dhënat u ngarkuan në depozitat S3, atëherë mund të konfiguroni një nisje 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 kopjimit niset çdo ditë në 4:15 të mëngjesit.

Fshirja e kopjeve rezervë të vjetra

Me shumë mundësi nuk ju nevojitet të ruani të gjitha kopjet rezervë që nga koha e Mezozoikut, prandaj do të ishte e dobishme të "pastrohet" periodikisht depozita juaj (si "kopjet e plota", ashtu si dhe WAL-logs). Këtë do ta bëjmë gjithashtu përmes një detyre cron:

#!/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 të ekzekutonte këtë detyrë çdo ditë në 6:30 të mëngjesit, duke fshirë gjithçka (kopjet e plota, diferencat dhe WAL-të) përveç kopjeve të fundit 10 ditëve, por do të lërë të paktën një kopje deri në nga data e specifikuar, për të siguruar që çdo moment pas data të shkojë në PITR.

Rivendosja nga kopja rezervë

Nuk është sekret për askënd që çelësi për një bazë të shëndoshë është rikuperimi dhe kontrolli periodik i integritetit të të dhënave brenda saj. Si të rikuperohet duke përdorur WAL-G – do ta shpjegoj në këtë seksion, dhe do të flasim për kontrollet më vonë.

Është e rëndësishme të theksohet se për rikuperimin në një ambient provoje (gjithçka që nuk është production) – duhet të përdoret një llogari Read Only në S3, për të evituar që aksidentalisht të shkruhen mbi kopjet rezervë. Në rastin e WAL-G do t'iu nevojitet të caktoni përdoruesit të S3 të drejtat e mëposhtme në Politikat e Grupit (Efekti: Lejo): s3:GetObject, s3:ListBucket, s3:GetBucketLocation. Dhe, sigurisht, të mos harroni të vendosni archive_mode=off në skedarin e konfigurimeve postgresql.conf, që të mos e dëshirojë baza juaj e testimit që të bëjë backup pa u vënë re.

Rikuperimi bëhet me një veprim të lehtë nga fshirja e të gjitha të dhënave PostgreSQL (përfshirë përdoruesit), prandaj, ju lutemi, jini jashtëzakonisht të matur kur të 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ë dëshirojnë të kontrollojnë procesin e rikuperimit – më poshtë është përgatitur një copëz e vogël bashkimi, që në rast probleme me rikuperimin – skripti të dështojë me një kod dalje jo zero. Në këtë shembull bëhen 120 kontrolle me një kohë të pritur prej 5 sekondash (në total 10 minuta për rikuperimin), për të parë nëse është fshirë skedari sinjalizues (kjo do të thotë se rikuperimi ka kaluar me sukses):

#!/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ë nisin sërish të gjithë proceset (pgbouncer/monit etj).

Kontrolli i të dhënave pas rikuperimit

Është e domosdoshme të kontrolloni integritetin e bazës pas rikuperimit, për të evituar një situatë me një kopje rezervë të prishur/apavendosur. Dhe është më mirë ta bëni këtë me çdo arkiv të krijuar, por ku dhe si – varet vetëm nga fantazia juaj (mund të ngrini servera të ndarë me pagesë për orë ose të ekzekutoni kontrollin në CI). Por të paktën – është e nevojshme të kontrolloni të dhënat dhe indeksat në bazë.

Për të kontrolluar të dhënat, mjafton t'i kaloni ato përmes një dump-i, por është më mirë që kur krijoni bazën të keni aktivizuar sumat e kontrollit (kontrolli i 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 indeksat – ekziston moduli amcheck, një query sql për të do ta marrim nga testet WAL-G dhe rreth tij do të ndërtojmë një logjikë të vogël:

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

Dua të shpreh falënderime për Andrej Borodin për ndihmën në përgatitjen e publikimit dhe një falënderim të veçantë për kontributin e tij në zhvillimin e WAL-G!

Me këtë, kjo shënim përfundoi. Shpresoj se kam arritur të tregoj lehtësinë e konfigurimit dhe potencialin e madh për përdorimin e këtij strumenti në kompaninë tuaj. Kam dëgjuar shumë për WAL-G, por nuk kam pasur kurrë kohë të ulem dhe të kuptoj. Dhe pas shpalljes së tij te vetja – u krijua ky artikull.

Është e rëndësishme të theksohet që WAL-G mund të funksionojë gjithashtu me bazat e të dhënave të mëposhtme:

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster