Het is al lang bekend dat het maken van back-ups naar SQL-dumps (met behulp van pg_dump of pg_dumpall) geen goed idee is. Voor het back-uppen van PostgreSQL-databases kun je beter het commando pg_basebackupgebruiken, dat een binaire kopie maakt van de WAL-logbestanden. Maar als je de hele procedure voor het maken en herstellen van een kopie gaat bestuderen, begrijp je dat je minstens een paar driewielers moet schrijven om dit allemaal werkend te krijgen zonder dat het je boven- en onderrug pijn doet. Om het lijden te verlichten is WAL-G ontwikkeld.
– een tool geschreven in Go voor het maken van back-ups en het herstellen van PostgreSQL-databases (en sinds kort ook MySQL/MariaDB, MongoDB en FoundationDB). Het ondersteunt opslag in Amazon S3 (en soortgelijke diensten, zoals Yandex Object Storage), evenals Google Cloud Storage, Azure Storage, Swift Object Storage en gewoon de bestandssysteem. Alle configuratie bestaat uit een paar eenvoudige stappen, maar omdat artikelen hierover verspreid zijn over het internet, ontbreekt een complete how-to handleiding die alle stappen van begin tot eind omvat (op Habr zijn er verschillende berichten, maar veel momenten worden daar gemist).

Dit artikel is in de eerste plaats geschreven om mijn kennis te systematiseren. Ik ben geen DBA en kan soms spreektaal of ontwikkeltaal gebruiken, dus corrigerende opmerkingen zijn welkom!
Ik zou vooral willen benadrukken dat alles hier relevant is en is getest voor PostgreSQL 12.3 op Ubuntu 18.04, alle commando's moeten worden uitgevoerd door een geprivilegieerde gebruiker.
Installatie
Op het moment van schrijven is de stabiele versie van WAL-G - . Die gaan we gebruiken (maar als je het zelf wilt bouwen vanuit de master-tak, zijn er in de repository op GitHub alle instructies hiervoor). Voor het downloaden en installeren dienen we het volgende uit te voeren:
#!/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/
Daarna moet je eerst WAL-G configureren en dan PostgreSQL zelf.
WAL-G configureren
Voor het voorbeeld van het opslaan van back-ups zal Amazon S3 worden gebruikt (omdat het dichter bij mijn servers ligt en het gebruik heel goedkoop is). Voor de werking hiervan heb je een "s3-bucket" en toegangssleutels nodig.
In alle eerdere artikelen over WAL-G werd configuratie met omgevingsvariabelen gebruikt, maar met deze release kunnen de instellingen worden geplaatst in in de home directory van de postgres-gebruiker. Voor het aanmaken hiervan voeren we de 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 iets uitleggen over alle parameters:
- WALG_S3_PREFIX – pad naar uw S3-bucket waar de back-ups naartoe worden geüpload (kan zowel naar de root als naar een map);
- AWS_ACCESS_KEY_ID – toegangssleutel voor S3 (bij herstel op een testserver – deze sleutels moeten een ReadOnly Policy hebben! Dit wordt uitgebreider besproken in de sectie over herstel.);
- AWS_SECRET_ACCESS_KEY – geheime sleutel in de S3-opslag;
- WALG_COMPRESSION_METHOD – compressiemethode, het is beter om Brotli te gebruiken (aangezien dit een goede balans biedt tussen de uiteindelijke grootte en de snelheid van compressie/decompressie);
- WALG_DELTA_MAX_STEPS – aantal 'delta's' tot het maken van een volledige back-up (ze besparen tijd en de grootte van de te uploaden gegevens, maar kunnen het herstelproces iets vertragen, daarom is het niet wenselijk om grote waarden te gebruiken);
- PGDATA – pad naar de map met gegevens van uw database (u kunt dit achterhalen door het commando uit te voeren pg_lsclusters);
- PGHOST – verbinding met de database, bij lokale back-ups is het beter om via unix-socket te maken zoals in dit voorbeeld.
De overige parameters kunnen in de documentatie worden bekeken: .
Configuratie van PostgreSQL
Om de archiver binnen de database zelf WAL-logboeken naar de cloud te laten uploaden en, indien nodig, hiervan te herstellen – moet u een paar parameters instellen in het configuratiebestand /etc/postgresql/12/main/postgresql.conf. Maar eerst moet u ervoor zorgen, dat geen van de onderstaande instellingen op andere waarden zijn ingesteld, zodat de DBMS niet crasht bij het herstarten van de configuratie. Deze parameters kunnen worden toegevoegd met:
#!/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 ingestelde parameters:
- wal_level – hoeveel informatie er in de WAL-logboeken wordt geschreven, 'replica' – schrijf alles;
- archive_mode – inschakelen van het uploaden van WAL-logboeken via het commando in de parameter archive_command;
- archive_command – commando voor het archiveren van de voltooide WAL-logboeken;
- archive_timeout – archivering van logboeken vindt alleen plaats als deze volledig zijn, maar als uw server weinig wijzingen/toevoegingen aan de DB maakt, is het zinvol om hier een limiet in seconden in te stellen, waarna het archiveringscommando geforceerd wordt aangeroepen (ik heb intensieve schrijfoperaties in de database elke seconde, daarom heb ik besloten deze parameter in productie niet in te stellen.);
- restore_command – commando voor het herstellen van WAL-logboek uit de back-up, zal worden gebruikt als in de 'volledige back-up' (base backup) de laatste wijzigingen in de DB ontbreken.
Meer over al deze parameters kan worden gelezen in de vertaling van de officiële documentatie: .
Instellen van het back-upschema
Hoe dan ook, de handigste manier om dit te starten is via cron. Dat gaan we instellen voor het maken van back-ups. Laten we beginnen met het commando voor het maken van een volledige back-up: in wal-g is dit de opstartparameter. backup-push. Maar voor nu is het beter om dit commando handmatig uit te voeren als gebruiker postgres, om te controleren of alles goed gaat (en er geen toegangsproblemen zijn):
#!/bin/bash
su - postgres -c '/usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main'
In de opstartparameters is het pad naar de datadirectory opgegeven - ik herinner je erop dat je dit kunt achterhalen door pg_lsclusters.
Als alles goed is gegaan en de gegevens zijn geüpload naar de S3-opslag, dan kunnen we de periodieke uitvoering 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 's morgens gestart.
Verwijderen van oude back-ups
Waarschijnlijk wil je niet alle back-ups uit het tijdperk van de dinosaurussen bewaren, dus het is nuttig om periodiek je opslag op te schonen (zowel 'volledige back-ups' als WAL-logs). We doen dit ook via een cron-taak:
#!/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 's morgens uit, waarbij alles (volledige back-ups, deltas en WAL's) wordt verwijderd, behalve kopieën van de laatste 10 dagen, maar laat in ieder geval één back-up van de opgegeven datum staan, zodat elk tijdstip tot van een datum in PITR valt. worden toegevoegd na Het is geen geheim dat de sleutel tot een gezonde database ligt in periodiek herstel en controle van de integriteit van de gegevens. Hoe te herstellen met WAL-G - dat zal ik in dit gedeelte uitleggen, en we zullen het over controles hebben daarna.
Herstellen uit een back-up
Het is vermeldenswaard
dat voor herstel in een testomgeving (alles wat niet productie is) je een Read Only-account in S3 moet gebruiken, om te voorkomen dat je per ongeluk back-ups overschrijft. In het geval van WAL-G moet je de volgende rechten voor de S3-gebruiker toekennen in het Groepsbeleid ( Effect: Toestaans3:GetObject): s3:ListBucket, s3:GetBucketLocation, s3:PutObject. En natuurlijk niet vergeten om vooraf in te stellen archive_mode=off in het configuratiebestand postgresql.conf, zodat je testdatabase niet stilletjes een back-up maakt.
Herstel verloopt met een simpele handbeweging door het verwijderen van alle PostgreSQL-gegevens inclusief gebruikers, dus wees alsjeblieft uiterst voorzichtig bij het uitvoeren van de volgende commando's.
#!/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 – hieronder is een klein stuk bash-magie voorbereid, zodat in geval van problemen tijdens het herstel – het script valt met een niet-nul exitcode. In dit voorbeeld worden 120 controles uitgevoerd met een time-out van 5 seconden (totaal 10 minuten voor herstel), om te ontdekken of het signaalbestand is verwijderd (dit zou betekenen dat het herstel succesvol was):
#!/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 na een succesvol herstel niet om alle processen (pgbouncer/monit enz.) weer op te starten.
Controle van gegevens na herstel
Het is absoluut noodzakelijk om de integriteit van de database na herstel te controleren, om situaties met een beschadigde/kware back-up te vermijden. Het is het beste om dit met elk gemaakt archief te doen, maar waar en hoe – hangt alleen van uw fantasie af (u kunt afzonderlijke servers op uurbasis opzetten of de controle in CI uitvoeren). Maar ten minste – moet de gegevens- en indexcontrole in de database worden uitgevoerd.
Voor gegevenscontrole is het voldoende om ze via een dump te draaien, maar het is beter als u bij het aanmaken van de database controle sommen had ingeschakeld ():
#!/bin/bash
if ! su - postgres -c 'pg_dumpall > /dev/null'
then
echo 'pg_dumpall failed'
exit 125
fi
Voor indexcontrole is er , de SQL-query hiervoor halen we uit en we bouwen een kleine logica eromheen:
#!/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 Andrej Borodin bedanken voor zijn hulp bij het voorbereiden van deze publicatie en een speciale dank voor zijn bijdrage aan de ontwikkeling van WAL-G!
Dit artikel is tot een einde gekomen. Ik hoop dat ik de eenvoud van de configuratie en het enorme potentieel van deze tool voor uw bedrijf heb kunnen overbrengen. Ik heb veel gehoord over WAL-G, maar ik had nooit tijd om me te verdiepen. En nadat ik het zelf heb geïmplementeerd – kwam deze artikel voort.
Het is ook belangrijk op te merken dat WAL-G kan werken met de volgende DBMS:
- ;
- ;
- ;
- En volgens de commits worden er nog een paar verwacht!
Bron: habr.com
