WAL-G: back-ups en herstel van PostgreSQL DBMS

Het is al lang bekend dat back-ups gemaakt kunnen worden in SQL-dumps (met behulp van pg_dump of pg_dumpall) is niet het beste idee. Om een ​​back-up te maken van de PostgreSQL DBMS is het beter om de opdracht te gebruiken pg_basebackup, die een binaire kopie van WAL-logs maakt. Maar wanneer u zich verdiept in het hele proces van het maken van een kopie en de restauratie, zult u begrijpen dat u minstens een paar driewielers moet schrijven om dit allemaal te laten werken zonder dat het u zowel aan de boven- als onderkant pijn doet. Om het lijden te verlichten werd WAL-G ontwikkeld.

WAL-G – is een tool geschreven in Go voor het maken van back-ups en het herstellen van PostgreSQL-databases (en meer recent MySQL/MariaDB, MongoDB en FoundationDB). Het ondersteunt het werken met Amazon S3-opslag (en vergelijkbare opslag, bijvoorbeeld Yandex Object Storage), evenals Google Cloud Storage, Azure Storage, Swift Object Storage en gewoon met het bestandssysteem. De hele opzet bestaat uit eenvoudige stappen, maar omdat er overal op internet artikelen over te vinden zijn, is er geen complete handleiding die alle stappen van begin tot eind beschrijft (er zijn wel verschillende berichten op Habr, maar daar ontbreken nog veel punten).

WAL-G: back-ups en herstel van PostgreSQL DBMS

Dit artikel is vooral geschreven om mijn kennis te systematiseren. Ik ben geen DBA en gebruik soms lekentaal, dus alle correcties zijn welkom!

Ik wil er apart op wijzen dat alles hieronder relevant is en is getest voor PostgreSQL 12.3. Ubuntu 18.04, alle commando's moeten worden uitgevoerd als een gebruiker met beheerdersrechten.

installatie

Op het moment dat dit artikel werd geschreven, was de stabiele versie van WAL-G v0.2.15 (maart 2020). Dit is wat we zullen gebruiken (maar als je het zelf wilt bouwen vanuit de master-branch, dan heeft de github-repository alle instructies daarvoor). Om te downloaden en te installeren, moet u het volgende doen:

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

Hierna moet u eerst WAL-G en vervolgens PostgreSQL zelf configureren.

WAL-G instellen

Amazon S3 wordt bijvoorbeeld gebruikt voor het opslaan van back-ups (omdat het dichter bij mijn servers staat en het erg goedkoop is in gebruik). Om ermee te kunnen werken heb je een "s3 bucket" en toegangssleutels nodig.

Alle voorgaande artikelen over WAL-G gebruikten configuratie met behulp van omgevingsvariabelen, maar met deze release kunnen de instellingen in .walg.json-bestand in de home directory van de postgres gebruiker. Om dit te maken, voert u het volgende bash-script uit:

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

Ik zal alle parameters nog even kort toelichten:

  • WALG_S3_PREFIX – het pad naar uw S3-bucket waar de back-ups worden geüpload (naar de root of naar een map);
  • AWS_ACCESS_KEY_ID – toegangssleutel tot S3 (in geval van herstel op een testserver – deze sleutels moeten een ReadOnly-beleid hebben! Dit wordt uitgebreider beschreven in het gedeelte over herstel);
  • AWS_SECRET_ACCESS_KEY – geheime sleutel in S3-opslag;
  • WALG_COMPRESSIE_METHODE – compressiemethode, het is beter om Brotli te gebruiken (omdat het de gulden middenweg is tussen de uiteindelijke grootte en de snelheid van compressie/decompressie);
  • WALG_DELTA_MAX_STEPS – het aantal “delta’s” voordat een volledige back-up wordt gemaakt (hiermee bespaart u tijd en de omvang van de gedownloade gegevens, maar het herstelproces kan enigszins worden vertraagd, dus het is niet raadzaam om grote waarden te gebruiken);
  • PGDATA – pad naar de map met uw databasegegevens (U kunt dit achterhalen door de opdracht uit te voeren pg_lclusters);
  • PGHOST – verbinding met de database, voor lokale back-up is het beter om dit via een unix-socket te doen zoals in dit voorbeeld.

De overige parameters zijn te vinden in de documentatie: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL configureren

Om ervoor te zorgen dat de archiveringsfunctie in de database WAL-logs naar de cloud uploadt en er (indien nodig) vanaf herstelt, moet u verschillende parameters in het configuratiebestand instellen /etc/postgresql/12/main/postgresql.conf. Alleen voor beginners je moet ervoor zorgendat geen van de onderstaande instellingen op een andere waarde is ingesteld, zodat het DBMS niet crasht wanneer de configuratie opnieuw wordt opgestart. U kunt deze parameters toevoegen met behulp van:

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

Beschrijving van de in te stellen parameters:

  • wal_niveau – hoeveel informatie moet er naar de WAL-logs worden geschreven, “replica” – schrijf alles;
  • archiefmodus – schakel het downloaden van WAL-logs in met behulp van de opdracht uit de parameter archief_commando;
  • archief_commando – een opdracht om een ​​voltooid WAL-logboek te archiveren;
  • archief_timeout – archivering van logs wordt alleen uitgevoerd als deze is voltooid, maar als uw server weinig gegevens aan de database wijzigt/toevoegt, is het zinvol om hier een limiet in seconden in te stellen, waarna de archiveringsopdracht geforceerd wordt aangeroepen (Ik schrijf elke seconde intensief naar de database, dus ik heb geweigerd deze parameter in productie te zetten);
  • herstel_commando – een opdracht om het WAL-logboek te herstellen vanuit een back-up, wordt gebruikt als de “volledige back-up” (basisback-up) de laatste wijzigingen in de database mist.

Meer details over al deze parameters kunt u vinden in de vertaling van de officiële documentatie: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Een back-upschema instellen

Wat je ook zegt, de handigste manier om te lanceren is cron. Dit is wat we zullen configureren om back-upkopieën te maken. Laten we beginnen met de opdracht om een ​​volledige back-up te maken: in wal-g is dit een opstartargument back-up push. Maar eerst is het beter om deze opdracht handmatig uit te voeren als postgres-gebruiker om er zeker van te zijn dat alles in orde is (en dat er geen toegangsfouten zijn):

#!/bin/bash

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

De opstartargumenten geven het pad naar de gegevensmap aan. Ik herinner u eraan dat u dit kunt vinden door het volgende uit te voeren: pg_lclusters.

Als alles zonder fouten is verlopen en de gegevens in de S3-opslag zijn geladen, kunt u een periodieke lancering in crontab instellen:

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

In dit voorbeeld wordt het back-upproces elke dag om 4:15 uur gestart.

Oude back-ups verwijderen

Waarschijnlijk hoeft u niet al uw back-ups uit het Mesozoïcum te bewaren. Daarom is het wellicht een goed idee om uw opslag regelmatig op te schonen (zowel volledige back-ups als WAL-logs). We zullen dit alles ook via een cron-taak doen:

#!/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 voert deze taak elke dag om 6:30 uur uit en verwijdert alles (volledige back-ups, delta's en WAL's), behalve de laatste 10 dagen aan back-ups, maar laat minstens één back-up achter naar de opgegeven datum, zodat elk punt na data werden opgenomen in PITR.

Herstellen vanaf een back-up

Het is geen geheim dat de sleutel tot een gezonde database ligt in het periodiek herstellen en controleren van de integriteit van de gegevens erin. Hoe u kunt herstellen met behulp van WAL-G – dat vertel ik u in dit gedeelte, en later zullen we het over controles hebben.

Het moet apart worden vermeld dat u voor het herstellen naar een testomgeving (alles wat niet in productie is) een Alleen-lezen-account in S3 nodig hebt om te voorkomen dat u per ongeluk back-ups overschrijft. In het geval van WAL-G moet u de volgende rechten voor de S3-gebruiker instellen in Groepsbeleid (Effect: Toestaan): s3:GetObject, s3:LijstBucket, s3:GetBucketLocation. En vergeet natuurlijk niet om het eerst in te stellen archief_modus=uit in het instellingenbestand postgresql.conf, zodat uw testbasis niet stilletjes geback-upt wil worden.

De restauratie wordt uitgevoerd met een lichte handbeweging het verwijderen van alle PostgreSQL-gegevens (inclusief gebruikers), dus wees uiterst voorzichtig wanneer u de volgende opdrachten uitvoert.

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

Voor degenen die het herstelproces willen controleren, staat hieronder een klein stukje bash-magie klaar. Mochten er problemen optreden tijdens het herstel, dan crasht het script met een exit-code die niet nul is. In dit voorbeeld worden 120 controles uitgevoerd met een time-out van 5 seconden (10 minuten totaal hersteltijd) om te controleren of het signaalbestand is verwijderd (dit betekent dat het herstel is geslaagd):

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

Vergeet niet om alle processen (pgbouncer/monit, enz.) opnieuw te starten nadat het herstel succesvol is verlopen.

Gegevens controleren na herstel

Het is van groot belang om de integriteit van de database te controleren na herstel, om te voorkomen dat er een beschadigde back-upkopie ontstaat. Het is beter om dit met elk aangemaakt archief te doen, maar waar en hoe hangt alleen van uw verbeelding af (u kunt elk uur aparte servers opzetten of een controle uitvoeren in CI). Maar het is minimaal nodig om de gegevens en indexen in de database te controleren.

Om de gegevens te controleren, is het voldoende om deze via een dump te halen, maar het is beter dat u bij het aanmaken van de database checksums inschakelt (gegevenscontrolesommen):

#!/bin/bash

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

Om indexen te controleren - er is amcheck-module, we zullen de SQL-query ervoor ophalen WAL-G-tests en we zullen er een beetje logica omheen bouwen:

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

Samenvattend

Ik wil Andrey Borodin bedanken voor zijn hulp bij de voorbereiding van deze publicatie en in het bijzonder voor zijn bijdrage aan de ontwikkeling van WAL-G!

Hiermee is dit verslag afgerond. Ik hoop dat ik duidelijk heb kunnen uitleggen hoe eenvoudig de installatie is en welke enorme mogelijkheden deze tool biedt voor uw bedrijf. Ik heb veel gehoord over WAL-G, maar ik heb nooit de tijd gehad om er rustig over na te denken. En nadat ik het thuis in de praktijk bracht, is dit artikel uit mij ontstaan.

Het is de moeite waard om apart op te merken dat WAL-G ook met de volgende DBMS kan werken:

Bron: www.habr.com

Koop betrouwbare hosting voor sites met DDoS-bescherming, VPS VDS-servers 🔥 Koop betrouwbare websitehosting met DDoS-bescherming, VPS- en VDS-servers | ProHoster