WAL-G. PostgreSQL DBMS-ի կրկնօրինակում և վերականգնում

Վաղուց հայտնի է, որ կրկնօրինակներ պատրաստելը SQL աղբանոցներում (օգտագործելով pg_dump կամ pg_dumpall) լավ գաղափար չէ։ PostgreSQL DBMS-ը կրկնօրինակելու համար ավելի լավ է օգտագործել հրամանը pg_basebackup, որը պատրաստում է WAL տեղեկամատյանների երկուական պատճեն: Բայց երբ սկսես ուսումնասիրել կրկնօրինակի ստեղծման և վերականգնման ողջ գործընթացը, կհասկանաս, որ պետք է գրել առնվազն մի երկու եռանիվ, որպեսզի դա աշխատի և ցավ չպատճառի քեզ վերևում և ներքևում: Տառապանքը մեղմելու համար մշակվել է WAL-G-ը:

ՎԱԼ-Գ Go-ում գրված գործիք է՝ PostgreSQL տվյալների բազաները կրկնօրինակելու և վերականգնելու համար (իսկ վերջերս MySQL/MariaDB, MongoDB և FoundationDB) Այն աջակցում է աշխատել Amazon S3 պահեստավորման հետ (և անալոգներ, օրինակ՝ Yandex Object Storage), ինչպես նաև Google Cloud Storage, Azure Storage, Swift Object Storage և պարզապես ֆայլային համակարգի հետ: Ամբողջ կարգավորումը հանգում է պարզ քայլերի, բայց քանի որ դրա մասին հոդվածները ցրված են ինտերնետում, չկա ամբողջական ձեռնարկ, որը կներառի բոլոր քայլերը սկզբից մինչև վերջ (կան մի քանի հրապարակումներ Habré-ում, բայց այնտեղ շատ կետեր բաց են թողնվում):

WAL-G. PostgreSQL DBMS-ի կրկնօրինակում և վերականգնում

Այս հոդվածը գրվել է հիմնականում իմ գիտելիքները համակարգելու համար: Ես DBA չեմ և կարող եմ ինչ-որ տեղ արտահայտվել աշխարհիկ լեզվով, այնպես որ ցանկացած ուղղում ողջունելի է:

Առանձին-առանձին ես նշում եմ, որ ստորև նշված ամեն ինչ տեղին է և փորձարկված է PostgreSQL 12.3-ի համար Ubuntu 18.04-ում, բոլոր հրամանները պետք է կատարվեն որպես արտոնյալ օգտվող:

Տեղակայում

Այս հոդվածը գրելու պահին WAL-G-ի կայուն տարբերակն է v0.2.15 (մարտ 2020). Սա այն է, ինչ մենք կօգտագործենք (բայց եթե ցանկանում եք ինքներդ կառուցել այն հիմնական ճյուղից, ապա github պահեստն ունի դրա բոլոր հրահանգները) Ներբեռնելու և տեղադրելու համար անհրաժեշտ է անել.

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

Դրանից հետո դուք պետք է նախ կարգավորեք WAL-G-ը, այնուհետև PostgreSQL-ն:

WAL-G-ի կարգավորում

Կրկնօրինակների պահպանման օրինակի համար կօգտագործվի Amazon S3 (քանի որ այն ավելի մոտ է իմ սերվերներին և դրա օգտագործումը շատ էժան է) Դրա հետ աշխատելու համար ձեզ հարկավոր է «s3 դույլ» և մուտքի ստեղներ:

WAL-G-ի մասին բոլոր նախորդ հոդվածներն օգտագործում էին կոնֆիգուրացիան՝ օգտագործելով շրջակա միջավայրի փոփոխականները, սակայն այս թողարկման դեպքում կարգավորումները կարող են տեղակայվել .walg.json ֆայլ postgres օգտագործողի տնային գրացուցակում: Այն ստեղծելու համար գործարկեք հետևյալ 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

Թույլ տվեք մի փոքր բացատրել բոլոր պարամետրերի մասին.

  • WALG_S3_PREFIX – դեպի ձեր S3 դույլ տանող ուղին, որտեղ կվերբեռնվեն կրկնօրինակները (կարող եք կամ դեպի արմատ կամ թղթապանակ);
  • AWS_ACCESS_KEY_ID - մուտքի բանալին S3-ում (թեստային սերվերի վրա վերականգնման դեպքում այս ստեղները պետք է ունենան միայն կարդալու քաղաքականություն: Սա ավելի մանրամասն նկարագրված է վերականգնման մասին բաժնում:);
  • AWS_SECRET_ACCESS_KEY – գաղտնի բանալի S3 պահեստում;
  • WALG_COMPRESSION_METHOD – սեղմման մեթոդ, ավելի լավ է օգտագործել Brotli-ն (քանի որ սա ոսկե միջինն է վերջնական չափի և սեղմման/դեկոպրեսիոն արագության միջև);
  • WALG_DELTA_MAX_STEPS – «դելտաների» քանակը մինչև ամբողջական կրկնօրինակում ստեղծելը (նրանք խնայում են ժամանակն ու ներբեռնված տվյալների չափը, բայց կարող են մի փոքր դանդաղեցնել վերականգնման գործընթացը, ուստի խորհուրդ չի տրվում օգտագործել մեծ արժեքներ);
  • PGDATA - ուղին դեպի գրացուցակ ձեր տվյալների բազայի տվյալներով (դուք կարող եք պարզել հրամանը գործարկելով pg_lsclusters);
  • PGHOST – միանալով տվյալների բազային, տեղական կրկնօրինակով ավելի լավ է դա անել unix-socket-ի միջոցով, ինչպես այս օրինակում:

Այլ պարամետրեր կարելի է գտնել փաստաթղթերում. https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL-ի կարգավորում

Որպեսզի տվյալների բազայի ներսում գտնվող արխիվատորը վերբեռնի WAL տեղեկամատյանները ամպի մեջ և վերականգնի դրանք (անհրաժեշտության դեպքում), դուք պետք է մի քանի պարամետր սահմանեք կազմաձևման ֆայլում: /etc/postgresql/12/main/postgresql.conf. Պարզապես սկսնակների համար դուք պետք է համոզվեքոր ստորև նշված կարգավորումներից և ոչ մեկը սահմանված չէ որևէ այլ արժեքի վրա, այնպես որ, երբ կազմաձևումը վերաբեռնվի, DBMS-ը չի խափանում: Դուք կարող եք ավելացնել այս պարամետրերը, օգտագործելով.

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

Սահմանվելիք պարամետրերի նկարագրությունը.

  • wal_level – որքան տեղեկատվություն գրել WAL տեղեկամատյաններում, «կրկնօրինակ» – գրել ամեն ինչ;
  • archive_mode – միացնել WAL տեղեկամատյանների ներբեռնումը` օգտագործելով պարամետրի հրամանը archive_command;
  • archive_command – Ավարտված WAL մատյան արխիվացնելու հրաման.
  • archive_timeout – տեղեկամատյանների արխիվացումը կատարվում է միայն այն ավարտվելուց հետո, բայց եթե ձեր սերվերը փոխում է/փոքր տվյալներ է ավելացնում տվյալների բազայում, ապա իմաստ ունի վայրկյանների ընթացքում սահմանել այստեղ, որից հետո արխիվացման հրամանը հարկադիր կանչվելու է (Ես ամեն վայրկյան ինտենսիվ գրում եմ տվյալների բազայում, ուստի որոշեցի չսահմանել այս պարամետրը արտադրության մեջ);
  • restore_command – WAL մատյանը կրկնօրինակից վերականգնելու հրամանը կօգտագործվի, եթե «ամբողջական կրկնօրինակում» (բազային կրկնօրինակում) բացակայում են տվյալների բազայի վերջին փոփոխությունները:

Այս բոլոր պարամետրերի մասին ավելին կարող եք կարդալ պաշտոնական փաստաթղթերի թարգմանության մեջ. https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Պահուստային ժամանակացույցի ստեղծում

Ինչ էլ ասի, այն գործարկելու ամենահարմար տարբերակը cron-ն է: Սա այն է, ինչ մենք կկարգավորենք կրկնօրինակներ ստեղծելու համար: Սկսենք ամբողջական կրկնօրինակում ստեղծելու հրամանից. wal-g-ում սա մեկնարկի փաստարկն է պահեստային-հրում. Բայց նախ, ավելի լավ է այս հրամանը ձեռքով գործարկել postgres-ի օգտագործողից՝ համոզվելու համար, որ ամեն ինչ լավ է (և մուտքի սխալներ չկան).

#!/bin/bash

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

Գործարկման փաստարկները ցույց են տալիս տվյալների գրացուցակի ուղին - հիշեցնում եմ ձեզ, որ այն կարող եք պարզել վազելով pg_lsclusters.

Եթե ​​ամեն ինչ անցել է առանց սխալների, և տվյալները բեռնվել են S3 պահեստում, ապա կարող եք կարգավորել պարբերական գործարկումը 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

Այս օրինակում պահուստավորման գործընթացը սկսվում է ամեն օր առավոտյան ժամը 4:15-ին:

Հին կրկնօրինակների ջնջում

Ամենայն հավանականությամբ, ձեզ հարկավոր չէ պահել մեզոզոյական դարաշրջանի բացարձակապես բոլոր կրկնօրինակները, այնպես որ օգտակար կլինի պարբերաբար «մաքրել» ձեր պահեստը (և «լրիվ կրկնօրինակները», և «WAL» տեղեկամատյանները): Մենք այս ամենը կանենք 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-ը կկատարի այս առաջադրանքը ամեն օր առավոտյան ժամը 6:30-ին, ջնջելով ամեն ինչ (ամբողջական կրկնօրինակները, դելտաները և WAL-ները), բացի վերջին 10 օրվա պատճեններից, բայց թողնելով առնվազն մեկ կրկնօրինակ: դեպի նշված ամսաթիվը, որպեսզի ցանկացած կետ այն բանից հետո ամսաթվերը ներառվել են PITR-ում:

Վերականգնում պահուստից

Գաղտնիք չէ, որ առողջ տվյալների բազայի բանալին ներսի տվյալների պարբերական վերականգնումն ու ամբողջականության ստուգումն է։ Ես ձեզ կասեմ, թե ինչպես վերականգնել WAL-G-ի միջոցով այս բաժնում, իսկ ստուգումների մասին մենք կխոսենք ավելի ուշ:

Պետք է նշել առանձին որ թեստային միջավայրում վերականգնելու համար (այն ամենն, ինչ արտադրված չէ) պետք է S3-ում օգտագործել միայն կարդալու հաշիվ, որպեսզի պատահաբար չվերագրվեն կրկնօրինակները: WAL-G-ի դեպքում դուք պետք է S3 օգտագործողի համար սահմանեք հետևյալ իրավունքները Group Policy-ում (Էֆեկտ. Թույլատրել): s3: GetObject, s3:ListBucket, s3: GetBucketLocation. Եվ, իհարկե, մի մոռացեք սահմանել archive_mode=անջատված պարամետրերի ֆայլում postgresql.conf, որպեսզի ձեր թեստային տվյալների բազան չուզենա հանգիստ կրկնօրինակել:

Վերականգնումն իրականացվում է ձեռքի մի փոքր շարժումով ջնջելով բոլոր PostgreSQL տվյալները (ներառյալ օգտվողները), ուստի խնդրում ենք չափազանց զգույշ եղեք հետևյալ հրամանները գործարկելիս:

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

Նրանց համար, ովքեր ցանկանում են ստուգել վերականգնման գործընթացը, ստորև պատրաստվել է bash magic-ի մի փոքրիկ կտոր, որպեսզի վերականգնման հետ կապված խնդիրների դեպքում սցենարը խափանվի ոչ զրոյական ելքի կոդով։ Այս օրինակում կատարվում է 120 ստուգում՝ 5 վայրկյան ընդմիջումով (ընդհանուր 10 րոպե վերականգնման համար)՝ պարզելու, թե արդյոք ազդանշանային ֆայլը ջնջվել է (սա կնշանակի, որ վերականգնումը հաջող է եղել).

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

Հաջող վերականգնումից հետո մի մոռացեք բոլոր գործընթացները հետ սկսել (pgbouncer/monit և այլն):

Վերականգնումից հետո տվյալների ստուգում

Վերականգնումից հետո անհրաժեշտ է ստուգել տվյալների բազայի ամբողջականությունը, որպեսզի կոտրված/կեղծ կրկնօրինակի հետ կապված իրավիճակ չառաջանա։ Եվ ավելի լավ է դա անել յուրաքանչյուր ստեղծված արխիվի հետ, բայց որտեղ և ինչպես կախված է միայն ձեր երևակայությունից (կարող եք անհատական ​​սերվերներ բարձրացնել ժամային կտրվածքով կամ ստուգել CI-ում): Բայց նվազագույնը, անհրաժեշտ է ստուգել տվյալների բազայում առկա տվյալները և ինդեքսները։

Տվյալները ստուգելու համար բավական է դրանք անցկացնել աղբանոցով, բայց ավելի լավ է, որ տվյալների բազան ստեղծելիս միացված լինեն ստուգման գումարները (տվյալների ստուգման գումարները):

#!/bin/bash

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

Ցուցանիշները ստուգելու համար - գոյություն ունի amcheck մոդուլ, եկեք վերցնենք դրա համար sql հարցումը WAL-G թեստեր և դրա շուրջ մի փոքր տրամաբանություն կառուցիր.

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

Ամփոփելով

Ցանկանում եմ իմ երախտագիտությունը հայտնել Անդրեյ Բորոդինին հրատարակության պատրաստման հարցում ցուցաբերած օգնության համար և հատուկ շնորհակալություն WAL-G-ի զարգացման գործում ունեցած ներդրման համար:

Սա եզրափակում է այս գրառումը: Հուսով եմ, որ կարողացա փոխանցել տեղադրման հեշտությունը և ձեր ընկերությունում այս գործիքն օգտագործելու հսկայական ներուժը: Ես շատ եմ լսել WAL-G-ի մասին, բայց երբեք ժամանակ չեմ ունեցել նստել և պարզել այն: Եվ այն բանից հետո, երբ ես այն իրականացրեցի տանը, այս հոդվածը դուրս եկավ ինձանից:

Առանձին-առանձին, հարկ է նշել, որ WAL-G-ը կարող է նաև աշխատել հետևյալ DBMS-ի հետ.

Source: www.habr.com

Добавить комментарий