WAL-G: backups è ricuperazione di PostgreSQL DBMS

Hè cunnisciutu longu chì fà e copie di salvezza in dumps SQL (usendu pg_dump o pg_dumpall) ùn hè micca una bona idea. Per fà una copia di salvezza di u DBMS PostgreSQL, hè megliu aduprà u cumandamentu pg_basebackup, chì face una copia binaria di i logs WAL. Ma quandu avete principiatu à studià tuttu u prucessu di creà una copia è di ristaurazione, capirete chì avete bisognu di scrive almenu un paru di tricicli per questu per travaglià è ùn vi causa micca dolore sopra è sottu. Per alleviate a sofferenza, WAL-G hè statu sviluppatu.

WAL-G hè un strumentu scrittu in Go per a copia di salvezza è restaurà e basa di dati PostgreSQL (è più recentemente MySQL / MariaDB, MongoDB è FoundationDB). Supporta u travagliu cù l'almacenamiento Amazon S3 (è analoghi, per esempiu, Yandex Object Storage), è ancu Google Cloud Storage, Azure Storage, Swift Object Storage è solu cù u sistema di fugliale. L'intera cunfigurazione si riduce à semplici passi, ma per via di u fattu chì l'articuli nantu à questu sò spargugliati in Internet, ùn ci hè micca un manuale cumpletu di cumu fà chì includessi tutti i passi da u principiu à a fine (ci sò parechji posti nantu à Habré, ma ci mancanu assai punti).

WAL-G: backups è ricuperazione di PostgreSQL DBMS

Questu articulu hè statu scrittu principalmente per sistematizà a mo cunniscenza. Ùn sò micca un DBA è mi possu sprime in lingua laica in qualchì locu, cusì ogni currezzione hè benvenuta!

Separatamente, aghju nutatu chì tuttu quì sottu hè pertinente è pruvatu per PostgreSQL 12.3 in Ubuntu 18.04, tutti i cumandamenti devenu esse eseguiti cum'è un utilizatore privilegiatu.

rimarchevuli

A l'ora di scrive stu articulu, a versione stabile di WAL-G hè v0.2.15 (marzu 2020). Questu hè ciò chì useremu (ma sè vo vulete custruisce da sè stessu da u ramu maestru, allora u repository github hà tutte l'istruzzioni per questu.). Per scaricà è stallà, avete bisognu di fà:

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

Dopu questu, avete bisognu di cunfigurà WAL-G prima, è dopu PostgreSQL stessu.

Installazione di WAL-G

Per un esempiu di salvezza di salvezza, Amazon S3 serà utilizatu (perchè hè più vicinu à i mo servitori è u so usu hè assai prezzu). Per travaglià cun ellu, avete bisognu di un "s3 bucket" è e chjave d'accessu.

Tutti l'articuli precedenti nantu à WAL-G anu utilizatu a cunfigurazione cù variabili di l'ambiente, ma cù questa liberazione i paràmetri ponu esse situati in .walg.json schedariu in u cartulare di casa di l'utilizatore postgres. Per creà, eseguite u seguente script 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

Lasciami spiegà un pocu di tutti i paràmetri:

  • WALG_S3_PREFIX - u percorsu à u vostru bucket S3 induve e copie di salvezza seranu caricate (pudete sia à a radica sia à un cartulare);
  • AWS_ACCESS_KEY_ID - chjave d'accessu in S3 (in casu di ricuperazione in un servitore di prova, queste chjave deve avè una Politica di ReadOnly! Questu hè descrittu in più detail in a sezione di ricuperazione.);
  • AWS_SECRET_ACCESS_KEY - chjave secreta in u almacenamiento S3;
  • WALG_COMPRESSION_METHOD - metudu di cumpressione, hè megliu aduprà Brotli (perchè questu hè u mediu d'oru trà a dimensione finale è a velocità di compressione / decompressione);
  • WALG_DELTA_MAX_STEPS - u numeru di "deltas" prima di creà una copia di salvezza sana (salvanu u tempu è a dimensione di i dati telecaricati, ma ponu rallentà ligeramente u prucessu di ricuperazione, per quessa ùn hè micca cunsigliatu di utilizà grandi valori);
  • PGDATA - percorsu à u cartulare cù i vostri dati di basa di dati (pudete scopre da eseguisce u cumandamentu pg_lsclusters);
  • PGHOST - cunnessu à a basa di dati, cù una copia di salvezza locale hè megliu per fà via un unix-socket cum'è in questu esempiu.

Altri parametri ponu esse truvati in a documentazione: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

Configurazione di PostgreSQL

Per chì l'archiviu in a basa di dati per carica i logs WAL in u nuvulu è restaurà da elli (se necessariu), avete bisognu di stabilisce parechji paràmetri in u schedariu di cunfigurazione. /etc/postgresql/12/main/postgresql.conf. Solu per principianti avete bisognu à assicuràchì nimu di i paràmetri sottu sò stabiliti à qualsiasi altri valori, perchè quandu a cunfigurazione hè ricaricata, u DBMS ùn falla micca. Pudete aghjunghje sti paràmetri cù:

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

Descrizzione di i paràmetri da stabilisce:

  • wal_level - quantu infurmazione scrive in i logs WAL, "replica" - scrivite tuttu;
  • archive_mode - permette u scaricamentu di i logs WAL usendu u cumandimu da u paràmetru archive_command;
  • archive_command - cumandamentu per archivià un logu WAL cumpletu;
  • archive_timeout - l'archiviazione di i logs hè realizatu solu quandu hè cumpletu, ma se u vostru servitore cambia / aghjunghje pocu dati à a basa di dati, allora hè sensu di stabilisce un limitu quì in sicondi, dopu chì u cumandamentu d'archiviazione serà chjamatu per forza (Scrivu intensivamente à a basa di dati ogni siconda, perchè decisu di ùn stabilisce micca stu paràmetru in a produzzione);
  • risturà_cumanda - u cumandamentu per restaurà u logu WAL da una copia di salvezza serà utilizatu se a "copia di salvezza completa" (copia di salvezza di basa) ùn manca l'ultimi cambiamenti in a basa di dati.

Pudete leghje più nantu à tutti sti paràmetri in a traduzzione di a documentazione ufficiale: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Configurazione di un schedariu di salvezza

Qualunque si pò dì, a manera più còmuda di eseguisce hè cron. Questu hè ciò chì avemu da cunfigurà per creà backups. Cuminciamu cù u cumandimu per creà una copia di salvezza completa: in wal-g questu hè l'argumentu di lanciamentu backup-push. Ma prima, hè megliu eseguisce stu cumandamentu manualmente da l'utilizatore postgres per assicurà chì tuttu hè bè (è ùn ci sò micca errori d'accessu):

#!/bin/bash

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

L'argumenti di lanciamentu indicanu u percorsu à u repertoriu di dati - vi ricurdò chì pudete truvà fora in esecuzione pg_lsclusters.

Se tuttu hè andatu senza errori è i dati sò stati caricati in l'almacenamiento S3, allora pudete cunfigurà u lanciamentu periodicu in 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

In questu esempiu, u prucessu di salvezza principia ogni ghjornu à 4:15 am.

Sguassà i vechji backups

Hè assai prubabile, ùn avete micca bisognu di mantene assolutamente tutte e copie di salvezza di l'era Mesozoica, cusì serà utile per "pulizia" periodicamente u vostru almacenamentu (sia "copia di salvezza completa" è logs WAL). Faremu tuttu questu attraversu un compitu 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 eseguirà stu compitu ogni ghjornu à 6:30 am, sguassendu tuttu (copia di salvezza cumpleta, delta è WAL) eccettu e copie per l'ultimi 10 ghjorni, ma lascendu almenu una copia di salvezza. à data specificata cusì chì ogni puntu после e date sò state incluse in PITR.

Risturà da una copia di salvezza

Ùn hè un sicretu chì a chjave per una basa di dati sana hè a risturazione periodica è a verificazione di l'integrità di e dati in l'internu. Vi dicu cumu ricuperà cù WAL-G in questa sezione, è parlemu di cuntrolli dopu.

Hè vale a pena nutà separatamente chì per restaurà in un ambiente di prova (tuttu ciò chì ùn hè micca pruduzzione) avete bisognu di utilizà un contu Read Only in S3 per ùn sovrascrive accidentalmente backups. In u casu di WAL-G, avete bisognu di stabilisce i seguenti diritti per l'utilizatore S3 in Politica di Gruppu (Effettu: permette): s3: GetObject, s3:ListBucket, s3: GetBucketLocation. È, sicuru, ùn vi scurdate di mette archive_mode = off in u schedariu di paràmetri postgresql.conf, cusì chì a vostra basa di dati di teste ùn vole micca esse salvata in silenziu.

A risturazione hè fatta cù un ligeru muvimentu di a manu sguassà tutte e dati PostgreSQL (cumpresi l'utilizatori), cusì fate assai attenti quandu eseguite i seguenti cumandamenti.

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

Per quelli chì vulete cuntrollà u prucessu di ricuperazione, un picculu pezzu di magia bash hè statu preparatu sottu, perchè in casu di prublemi in a ricuperazione, u script crash cun un codice di uscita non-zero. In questu esempiu, 120 cuntrolli sò fatti cù un timeout di 5 seconde (un totale di 10 minuti per a ricuperazione) per sapè se u schedariu di signale hè statu sguassatu (questu significarà chì a ricuperazione hè successu):

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

Dopu a ricuperazione successu, ùn vi scurdate di inizià tutti i prucessi (pgbouncer/monit, etc.).

Cuntrollà i dati dopu a ripresa

Hè imperativu di verificà l'integrità di a basa di dati dopu a risturazione, perchè una situazione cù una copia di salvezza rotta / storta ùn hè micca. È hè megliu fà questu cù ogni archiviu creatu, ma induve è cumu dipende solu da a vostra imaginazione (pudete suscitarà servitori individuali nantu à una basa di ogni ora o eseguite un cuntrollu in CI). Ma à u minimu, hè necessariu di verificà e dati è l'indici in a basa di dati.

Per verificà e dati, hè abbastanza per eseguisce à traversu un dump, ma hè megliu chì quandu crea a basa di dati avete checksums attivati ​​(cuntrolli di dati):

#!/bin/bash

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

Per verificà l'indici - esiste modulu amcheck, pigliemu a query sql per questu Testi WAL-G è custruisce un pocu di logica intornu à questu:

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

Per riassume

Vogliu sprime a mo gratitùdine à Andrey Borodin per u so aiutu in a preparazione di a publicazione è un ringraziu speciale per a so cuntribuzione à u sviluppu di WAL-G!

Questu cuncludi sta nota. Spergu chì aghju sappiutu trasmette a facilità di cunfigurazione è l'enorme putenziale per aduprà sta strumentu in a vostra cumpagnia. Aghju intesu assai di WAL-G, ma ùn aghju mai avutu abbastanza tempu per pusà è capisce. E dopu avè implementatu in casa, questu articulu hè surtitu da mè.

Separatamente, vale a pena nutà chì WAL-G pò ancu travaglià cù i seguenti DBMS:

Source: www.habr.com

Add a comment