WAL-G: PostgreSQL DBVS dublējumkopijas un atkopšana

Jau sen ir zināms, ka dublējumkopiju veidošana SQL izgāztuvēs (izmantojot pg_dump vai pg_dumpall) nav laba ideja. Lai dublētu PostgreSQL DBVS, labāk ir izmantot komandu pg_basebackup, kas veido WAL žurnālu bināro kopiju. Bet, kad sākat pētīt visu kopijas izveides un atjaunošanas procesu, jūs sapratīsit, ka jums ir jāuzraksta vismaz pāris trīsriteņi, lai tas darbotos un neradītu sāpes gan augšā, gan apakšā. Lai atvieglotu ciešanas, tika izstrādāts WAL-G.

WAL-G ir programmā Go rakstīts rīks PostgreSQL datu bāzu dublēšanai un atjaunošanai (un nesen MySQL/MariaDB, MongoDB un FoundationDB). Tā atbalsta darbu ar Amazon S3 krātuvi (un analogiem, piemēram, Yandex Object Storage), kā arī Google Cloud Storage, Azure Storage, Swift Object Storage un vienkārši ar failu sistēmu. Visa iestatīšana sastāv no vienkāršām darbībām, taču, tā kā raksti par to ir izkaisīti internetā, nav pilnīgas rokasgrāmatas, kas ietvertu visas darbības no sākuma līdz beigām (ir vairākas ziņas vietnē Habré, bet daudzi punkti ir izlaisti).

WAL-G: PostgreSQL DBVS dublējumkopijas un atkopšana

Šis raksts tika rakstīts galvenokārt, lai sistematizētu manas zināšanas. Neesmu DBA un kaut kur māku izteikties nespeciālista valodā, tāpēc laipni gaidīti visi labojumi!

Atsevišķi es atzīmēju, ka viss zemāk ir būtisks un pārbaudīts PostgreSQL 12.3 operētājsistēmā Ubuntu 18.04, visas komandas ir jāizpilda kā priviliģētam lietotājam.

Uzstādīšana

Šī raksta rakstīšanas laikā WAL-G stabilā versija ir v0.2.15 (2020. gada marts). Tas ir tas, ko mēs izmantosim (bet, ja vēlaties to izveidot pats no galvenās filiāles, tad github repozitorijā ir visi norādījumi par to). Lai lejupielādētu un instalētu, jums jāveic šādas darbības:

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

Pēc tam vispirms ir jākonfigurē WAL-G un pēc tam pats PostgreSQL.

WAL-G iestatīšana

Dublējumu glabāšanas piemēram tiks izmantots Amazon S3 (jo tas ir tuvāk maniem serveriem un tā lietošana ir ļoti lēta). Lai strādātu ar to, jums ir nepieciešams “s3 spainis” un piekļuves atslēgas.

Visos iepriekšējos rakstos par WAL-G tika izmantota konfigurācija, izmantojot vides mainīgos, taču šajā laidienā iestatījumus var atrast .walg.json failu postgres lietotāja mājas direktorijā. Lai to izveidotu, palaidiet šādu bash skriptu:

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

Ļaujiet man nedaudz paskaidrot visus parametrus:

  • WALG_S3_PREFIX – ceļš uz jūsu S3 spaini, kur tiks augšupielādēti dublējumkopijas (varat gan uz sakni, gan uz mapi);
  • AWS_ACCESS_KEY_ID - piekļuves atslēga S3 (atkopšanas gadījumā testa serverī šīm atslēgām ir jābūt tikai lasīšanas politikai! Tas ir sīkāk aprakstīts sadaļā par atgūšanu.);
  • AWS_SECRET_ACCESS_KEY – slepenā atslēga S3 krātuvē;
  • WALG_COMPRESSION_METHOD – kompresijas metodi, labāk izmantot Brotli (jo tas ir zelta vidusceļš starp galīgo izmēru un kompresijas/dekompresijas ātrumu);
  • WALG_DELTA_MAX_SOĻI – “deltu” skaits pirms pilnas dublējuma izveides (tie ietaupa laiku un lejupielādēto datu apjomu, bet var nedaudz palēnināt atkopšanas procesu, tāpēc nav vēlams izmantot lielas vērtības);
  • PGDATA - ceļš uz direktoriju ar jūsu datu bāzes datiem (to var uzzināt, izpildot komandu pg_lsclusters);
  • PGHOST – pieslēdzoties datu bāzei, ar lokālo dublējumu labāk to darīt caur unix-socket kā šajā piemērā.

Citus parametrus var atrast dokumentācijā: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL iestatīšana

Lai arhivētājs datubāzē varētu augšupielādēt WAL žurnālus mākonī un atjaunot tos no tiem (ja nepieciešams), konfigurācijas failā ir jāiestata vairāki parametri /etc/postgresql/12/main/postgresql.conf. Tikai iesācējiem jums ir jāpārliecināska nevienam no tālāk norādītajiem iestatījumiem nav iestatītas citas vērtības, lai, atkārtoti ielādējot konfigurāciju, DBVS neavarētu. Varat pievienot šos parametrus, izmantojot:

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

Iestatāmo parametru apraksts:

  • wal_level – cik daudz informācijas ierakstīt WAL žurnālos, “replica” – ieraksti visu;
  • archive_mode – iespējot WAL žurnālu lejupielādi, izmantojot komandu no parametra archive_command;
  • archive_command – komanda aizpildīta WAL žurnāla arhivēšanai;
  • archive_timeout – žurnālu arhivēšana tiek veikta tikai tad, kad tā ir pabeigta, bet, ja jūsu serveris izmaina/pievieno maz datu datu bāzei, tad šeit ir jēga iestatīt ierobežojumu sekundēs, pēc kuras arhivēšanas komanda tiks izsaukta piespiedu kārtā (Es katru sekundi intensīvi rakstu datubāzē, tāpēc nolēmu ražošanā šo parametru neiestatīt);
  • Restore_command – komanda atjaunot WAL žurnālu no dublējuma tiks izmantota, ja “pilnai dublējumam” (bāzes dublējumam) trūkst jaunāko izmaiņu datu bāzē.

Vairāk par visiem šiem parametriem varat lasīt oficiālās dokumentācijas tulkojumā: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Rezerves grafika iestatīšana

Lai ko arī teiktu, ērtākais veids, kā to palaist, ir cron. Tas ir tas, ko mēs konfigurēsim, lai izveidotu dublējumus. Sāksim ar komandu, lai izveidotu pilnu dublējumu: wal-g šis ir palaišanas arguments backup-push. Bet vispirms labāk ir palaist šo komandu manuāli no postgres lietotāja, lai pārliecinātos, ka viss ir kārtībā (un nav piekļuves kļūdu):

#!/bin/bash

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

Palaišanas argumenti norāda ceļu uz datu direktoriju – atgādinu, ka to var uzzināt palaižot pg_lsclusters.

Ja viss noritēja bez kļūdām un dati tika ielādēti S3 krātuvē, tad varat konfigurēt periodisko palaišanu programmā 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

Šajā piemērā dublēšanas process sākas katru dienu pulksten 4:15.

Veco dublējumkopiju dzēšana

Visticamāk, jums nav jāsaglabā pilnīgi visas mezozoja laikmeta dublējumkopijas, tāpēc būs noderīgi periodiski “iztīrīt” savu krātuvi (gan “pilnas dublējumkopijas”, gan WAL žurnālus). Mēs to darīsim, izmantojot cron uzdevumu:

#!/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 izpildīs šo uzdevumu katru dienu plkst. 6:30, dzēšot visu (pilnas dublējumkopijas, deltas un WAL), izņemot pēdējo 10 dienu kopijas, bet atstājot vismaz vienu dublējumu. līdz norādītais datums, lai jebkurš punkts pēc datumi tika iekļauti PITR.

Atjaunošana no dublējuma

Nav noslēpums, ka veselīgas datu bāzes atslēga ir periodiska atjaunošana un iekšējo datu integritātes pārbaude. Šajā sadaļā pastāstīšu, kā atgūt, izmantojot WAL-G, un par pārbaudēm runāsim vēlāk.

Jāatzīmē atsevišķi ka, lai atjaunotu testa vidē (visu, kas nav produkcijas), jums ir jāizmanto tikai lasāms konts S3, lai nejauši nepārrakstītu dublējumkopijas. WAL-G gadījumā grupas politikā S3 lietotājam ir jāiestata šādas tiesības (Ietekme: Atļaut): s3: GetObject, s3:ListBucket, s3: GetBucketLocation. Un, protams, neaizmirstiet iestatīt archive_mode=off iestatījumu failā postgresql.conf, lai jūsu testa datubāze nevēlētos klusi dublēt.

Restaurācija tiek veikta ar nelielu rokas kustību dzēšot visus PostgreSQL datus (ieskaitot lietotājus), tāpēc, lūdzu, esiet īpaši uzmanīgs, izpildot šādas komandas.

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

Tiem, kas vēlas pārbaudīt atkopšanas procesu, zemāk ir sagatavots neliels bash maģijas gabals, lai atkopšanas problēmu gadījumā skripts avarētu ar nulles izejas kodu. Šajā piemērā tiek veiktas 120 pārbaudes ar 5 sekunžu taimautu (kopā 10 minūtes atkopšanai), lai noskaidrotu, vai signāla fails ir dzēsts (tas nozīmēs, ka atkopšana bija veiksmīga):

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

Pēc veiksmīgas atkopšanas neaizmirstiet atsākt visus procesus (pgbouncer/monit utt.).

Datu pārbaude pēc atkopšanas

Pēc atjaunošanas obligāti jāpārbauda datu bāzes integritāte, lai nerastos situācija ar bojātu/greizu dublējumu. Un labāk to darīt ar katru izveidoto arhīvu, taču tas, kur un kā, ir atkarīgs tikai no jūsu iztēles (jūs varat palielināt atsevišķus serverus par stundu vai veikt pārbaudi CI). Bet vismaz ir jāpārbauda dati un indeksi datu bāzē.

Lai pārbaudītu datus, pietiek tos palaist caur izgāztuvi, bet labāk, ja veidojot datu bāzi, ir iespējotas kontrolsummas (datu kontrolsummas):

#!/bin/bash

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

Lai pārbaudītu indeksus - pastāv amcheck modulis, ņemsim sql vaicājumu tam no WAL-G testi un izveidojiet ap to nelielu loģiku:

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

Apkopot

Vēlos izteikt pateicību Andrejam Borodinam par palīdzību izdevuma sagatavošanā un īpašu pateicību par ieguldījumu WAL-G attīstībā!

Tas noslēdz šo piezīmi. Es ceru, ka man izdevās parādīt iestatīšanas vieglumu un milzīgo potenciālu šī rīka izmantošanai jūsu uzņēmumā. Esmu daudz dzirdējis par WAL-G, taču man nekad nebija pietiekami daudz laika, lai apsēstos un izdomātu. Un pēc tam, kad es to ieviesu mājās, šis raksts iznāca no manis.

Atsevišķi ir vērts atzīmēt, ka WAL-G var strādāt arī ar šādām DBVS:

Avots: www.habr.com

Pievieno komentāru