WAL-G: serep lan pemulihan PostgreSQL DBMS

Wis suwe dikenal manawa nggawe serep menyang dumps SQL (nggunakake pg_dump utawa pg_dumpall) iku ora apik. Kanggo nggawe cadangan PostgreSQL DBMS, luwih becik nggunakake perintah kasebut pg_basebackup, sing nggawe salinan binar log WAL. Nanging nalika sampeyan miwiti sinau kabeh proses nggawe salinan lan mulihake, sampeyan bakal ngerti sing kudu nulis ing paling saperangan saka tricycles kanggo iki bisa lan ora nimbulaké pain loro ndhuwur lan ngisor. Kanggo ngenthengake kasangsaran, WAL-G dikembangake.

WAL-G minangka alat sing ditulis ing Go kanggo nggawe serep lan mulihake database PostgreSQL (lan luwih anyar MySQL/MariaDB, MongoDB lan FoundationDB). Ndhukung nggarap panyimpenan Amazon S3 (lan analog, contone, Yandex Object Storage), uga Google Cloud Storage, Azure Storage, Swift Object Storage lan mung karo sistem file. Kabeh persiyapan dadi langkah-langkah sing gampang, nanging amarga kasunyatane artikel babagan iki kasebar ing Internet, ora ana cara manual lengkap sing kalebu kabeh langkah saka wiwitan nganti rampung (ana sawetara kiriman ing Habré, nanging akeh titik sing ora kejawab ana).

WAL-G: serep lan pemulihan PostgreSQL DBMS

Artikel iki ditulis utamane kanggo sistematis kawruhku. Aku dudu DBA lan aku bisa ngomong nganggo basa awam ing endi wae, mula ana koreksi!

Kapisah, aku nyathet yen kabeh ing ngisor iki cocog lan diuji kanggo PostgreSQL 12.3 ing Ubuntu 18.04, kabeh prentah kudu dieksekusi minangka pangguna sing duwe hak istimewa.

Instalasi

Nalika nulis artikel iki, versi WAL-G sing stabil yaiku v0.2.15 (Maret 2020). Iki sing bakal kita gunakake (nanging yen sampeyan pengin mbangun dhewe saka cabang master, banjur repositori github duwe kabeh instruksi kanggo iki.). Kanggo ngundhuh lan nginstal sampeyan kudu nindakake:

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

Sawise iki, sampeyan kudu ngatur WAL-G dhisik, banjur PostgreSQL dhewe.

Nyetel WAL-G

Kanggo conto nyimpen serep, Amazon S3 bakal digunakake (amarga luwih cedhak karo serverku lan panggunaane murah banget). Kanggo nggarap, sampeyan butuh "ember s3" lan tombol akses.

Kabeh artikel sadurunge babagan WAL-G nggunakake konfigurasi nggunakake variabel lingkungan, nanging karo release iki setelan bisa dumunung ing file .walg.json ing direktori ngarep pangguna postgres. Kanggo nggawe, jalanake skrip bash ing ngisor iki:

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

Ayo kula nerangake sethithik babagan kabeh paramèter:

  • WALG_S3_PREFIX - dalan menyang ember S3 ing ngendi serep bakal diunggah (sampeyan bisa menyang root utawa menyang folder);
  • AWS_ACCESS_KEY_ID – tombol akses ing S3 (ing kasus Recovery ing server test, tombol iki kudu ReadOnly Kebijakan! Iki diterangake kanthi luwih rinci ing bagean babagan pemulihan.);
  • AWS_SECRET_ACCESS_KEY - kunci rahasia ing panyimpenan S3;
  • WALG_COMPRESSION_METHOD - cara komprèsi, luwih apik kanggo nggunakake Brotli (amarga iki tegese emas antarane ukuran final lan kacepetan komprèsi / decompression);
  • WALG_DELTA_MAX_STEPS - nomer "delta" sadurunge nggawe serep lengkap (padha ngirit wektu lan ukuran data sing diundhuh, nanging bisa rada alon proses pemulihan, saengga ora dianjurake nggunakake nilai gedhe);
  • PGDATA – path menyang direktori karo data database (sampeyan bisa ngerteni kanthi mbukak printah pg_lsclusters);
  • PGHOST – nyambung menyang database, karo serep lokal iku luwih apik kanggo nindakake liwat unix-soket kaya ing conto iki.

Parameter liyane bisa ditemokake ing dokumentasi: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

Nggawe PostgreSQL

Supaya arsip ing database bisa ngunggah log WAL menyang awan lan mulihake saka wong-wong mau (yen perlu), sampeyan kudu nyetel sawetara paramèter ing file konfigurasi. /etc/postgresql/12/main/postgresql.conf. Mung kanggo wiwitan sampeyan kudu nggawe manawasing ora ana setelan ing ngisor iki disetel kanggo sembarang nilai liyane, supaya nalika konfigurasi wis reloaded, DBMS ora crash. Sampeyan bisa nambah parameter kasebut kanthi nggunakake:

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

Katrangan paramèter sing bakal disetel:

  • wal_level - pinten informasi sing kudu ditulis ing log WAL, "replika" - tulis kabeh;
  • arsip_mode – ngaktifake ndownload log WAL nggunakake printah saka parameter archive_command;
  • archive_command – printah kanggo arsip log WAL rampung;
  • archive_timeout – arsip log dileksanakake mung nalika wis rampung, nanging yen server ngganti / nambah data sethitik menyang database, banjur iku ndadekake pangertèn kanggo nyetel watesan kene ing sawetara detik, sawise kang printah arsip bakal disebut forcibly (Aku nulis kanthi intensif menyang database saben detik, mula aku mutusake ora nyetel parameter iki ing produksi);
  • restore_command – printah kanggo mulihake log WAL saka serep bakal digunakake yen "serep lengkap" (base backup) kurang owah-owahan paling anyar ing database.

Sampeyan bisa maca liyane babagan kabeh parameter kasebut ing terjemahan dokumentasi resmi: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Nggawe jadwal serep

Apa wae sing bisa dikandhakake, cara sing paling trep kanggo mbukak yaiku cron. Iki sing bakal kita atur kanggo nggawe serep. Ayo diwiwiti kanthi printah kanggo nggawe serep lengkap: ing wal-g iki minangka argumen peluncuran serep-push. Nanging pisanan, luwih apik kanggo mbukak printah iki kanthi manual saka pangguna postgres kanggo mesthekake yen kabeh apik (lan ora ana kesalahan akses):

#!/bin/bash

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

Argumentasi peluncuran nuduhake dalan menyang direktori data - Aku ngelingake sampeyan bisa nemokake kanthi mlaku pg_lsclusters.

Yen kabeh ora ana kesalahan lan data dimuat menyang panyimpenan S3, banjur sampeyan bisa ngatur peluncuran berkala ing 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

Ing conto iki, proses serep diwiwiti saben dina jam 4:15.

Mbusak serep lawas

Paling kamungkinan, sampeyan ora perlu kanggo nyimpen pancen kabeh serep saka jaman Mesozoic, supaya bakal migunani kanggo periodik "ngresiki" panyimpenan (loro "full serep" lan WAL log). Kita bakal nindakake iki kabeh liwat tugas 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 bakal nindakake tugas iki saben dina jam 6:30 am, mbusak kabeh (serep lengkap, delta lan WAL) kajaba salinan kanggo 10 dina pungkasan, nanging ninggalake paling ora siji serep kanggo tanggal tartamtu supaya sembarang titik после tanggal padha klebu ing PITR.

Mulihake saka serep

Ora ana rahasia manawa kunci database sing sehat yaiku pemugaran lan verifikasi integritas data ing njero. Aku bakal pitutur marang kowe carane waras nggunakake WAL-G ing bagean iki, lan kita bakal pirembagan bab mriksa mengko.

Wigati dicathet kanthi kapisah sing kanggo mulihake ing lingkungan test (kabeh sing ora produksi) sampeyan kudu nggunakake akun Read Only ing S3 supaya ora sengaja nimpa serep. Ing kasus WAL-G, sampeyan kudu nyetel hak ing ngisor iki kanggo pangguna S3 ing Kebijakan Grup (Efek: Allow): s3: GetObject, s3: ListBucket, s3: GetBucketLocation. Lan, mesthi, aja lali nyetel archive_mode=mati ing file setelan postgresql.conf, supaya database test sampeyan ora pengin digawe serep sepi.

Restorasi ditindakake kanthi gerakan tangan sing sithik mbusak kabeh data PostgreSQL (kalebu pangguna), mula ati-ati banget nalika nindakake perintah ing ngisor iki.

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

Kanggo sing pengin mriksa proses pemulihan, potongan cilik sihir bash wis disiapake ing ngisor iki, supaya yen ana masalah ing pemulihan, skrip bakal nabrak karo kode metu non-nol. Ing conto iki, 120 mriksa ditindakake kanthi wektu entek 5 detik (total 10 menit kanggo pemulihan) kanggo ngerteni apa file sinyal wis dibusak (iki tegese pemulihan 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

Sawise Recovery sukses, aja lali kanggo miwiti kabeh pangolahan bali (pgbouncer/monit, etc.).

Priksa data sawise Recovery

Penting kanggo mriksa integritas database sawise pemugaran, supaya kahanan karo serep bejat / bengkong ora muncul. Lan luwih apik kanggo nindakake iki karo saben arsip sing digawe, nanging ing ngendi lan kepiye mung gumantung ing imajinasi sampeyan (sampeyan bisa ngunggahake server individu saben jam utawa mriksa ing CI). Nanging paling ora, perlu mriksa data lan indeks ing basis data.

Kanggo mriksa data, cukup kanggo mbukak liwat mbucal, nanging luwih apik yen nalika nggawe database sampeyan wis aktif checksums (data checksum):

#!/bin/bash

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

Kanggo mriksa indeks - ana modul amcheck, ayo njupuk pitakon sql saka Tes WAL-G lan mbangun logika cilik ing saubengé:

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

Kanggo ngringkes

Aku seneng ngucapake matur nuwun marang Andrey Borodin kanggo bantuan ing nyiapake publikasi lan matur nuwun khusus kanggo kontribusi kanggo pangembangan WAL-G!

Iki rampung cathetan iki. Muga-muga aku bisa nyedhiyakake gampang persiyapan lan potensial gedhe kanggo nggunakake alat iki ing perusahaan sampeyan. Aku krungu akeh babagan WAL-G, nanging ora duwe cukup wektu kanggo njagong lan ngerteni. Lan sawise aku ngetrapake ing omah, artikel iki metu saka aku.

Kapisah, perlu dicathet yen WAL-G uga bisa nggarap DBMS ing ngisor iki:

Source: www.habr.com

Add a comment