Інкрыментальныя бэкапы postgresql з pgbackrest - курс маладога байца ад распрацоўніка

Адмова ад адказнасці

Я - распрацоўшчык. Я пішу код, з базай дадзеных узаемадзейнічаю толькі як карыстач. Я ні ў якім разе не прэтэндую на пасаду сістэмнага адміністратара і, тым больш, dba. Але...

Так выйшла, што мне трэба было арганізаваць рэзервовае капіраванне postgresql базы дадзеных. Ніякіх аблокаў - трымай SSH і зрабі, каб усё працавала і не прасіла грошай. Што мы робім у такіх выпадках? Правільна, піхаем pgdump у cron, кожны дзень бэкапім усё ў архіў і калі зусім разышліся — адпраўляем гэты архіў куды-небудзь далей.

У гэты раз складанасць складалася ў тым, што па планах база павінна была расці прыкладна на + - 100 МБ у дзень. Зразумела, ужо праз пару тыдняў жаданне бэкапіць усё pgdump'ам адпадзе. Тут на дапамогу прыходзяць інкрыментальныя бэкапы.

Цікава? Сардэчна запрашаем пад кат.

Інкрыментальны бэкап - разнавіднасць рэзервовай копіі, калі капіююцца не ўсе файлы крыніцы, а толькі новыя і змененыя з моманту стварэння папярэдняй копіі.

Як і любы распрацоўшчык, ЗУСІМ не жадаючы (на той момант) разбірацца ў тонкасцях postgres я хацеў знайсці зялёную кнопку. Ну, ведаеце, як у AWS, DigitalOcean: націснуў адну кнопку - атрымаў рэплікацыю, націснуў другую - наладзіў бэкапы, трэцюю - усё адкаціў на пару гадзін таму. Кнопкі і прыгожай GUIшнай прылады я не знайшоў. Калі вы ведаеце такі (бясплатны ці танны) - напішыце пра гэта ў каментарах.

Пагугліўшы я знайшоў два інструменты pgbarman и pgbackrest. З першым у мяне проста не задалося (вельмі бедная дакументацыя, спрабаваў усё падняць па старадаўніх мануалах), а вось у другога дакументацыя апынулася на ўзроўні, але і не без заганы. Каб спрасціць працу тым, хто сутыкнецца з падобнай задачай і быў напісаны дадзены артыкул.

Дачытаўшы дадзены артыкул вы навучыцеся рабіць інкрыментальныя бекапы, захоўваць іх на выдалены сервер (рэпазітар з бэкапамі) і аднаўляць іх у выпадку страты дадзеных ці іншых праблем на асноўным серверы.

Падрыхтоўка

Для прайгравання мануала вам спатрэбяцца два VPS. Першы будзе сховішчам (рэпазітаром, на якім будуць ляжаць бэкапы), а другі, уласна, сам сервер з postgres (у маім выпадку 11 версія postgres).

Мяркуецца, што на серверы з postgres у вас ёсць root, sudo карыстач, карыстач postgres і сам postgres усталяваны (карыстальнік postgres ствараецца аўтаматычна пры ўсталёўцы postgresql), а на серверы-рэпазітары ёсць root і sudo карыстач (у мануале будзе выкарыстоўвацца імя карыстача pgbackrest) .

Каб у вас было менш праблем пры прайграванні інструкцыі - курсівам я прапісваю дзе, якім карыстальнікам і з якімі правамі я выконваў каманду падчас напісання і праверкі артыкула.

Ўстаноўка pgbackrest

Рэпазітар (карыстальнік pgbackrest):

1. Спампоўваем архіў з pgbackrest і пераносім яго змесціва ў тэчку /build:

sudo mkdir /build
sudo wget -q -O - 
       https://github.com/pgbackrest/pgbackrest/archive/release/2.18.tar.gz | 
       sudo tar zx -C /build

2. Усталёўваны неабходныя для зборкі залежнасці:

sudo apt-get update
sudo apt-get install build-essential libssl-dev libxml2-dev libperl-dev zlib1g-dev 
       libpq-dev

3. Збіраем pgbackrest:

cd /build/pgbackrest-release-2.18/src && sudo ./configure
sudo make -s -C /build/pgbackrest-release-2.18/src

4. Капіяваны выкананы файл у дырэкторыю /usr/bin:

sudo cp /build/pgbackrest-release-2.18/src/pgbackrest /usr/bin
sudo chmod 755 /usr/bin/pgbackrest

5. Pgbackrest патрабуе наяўнасць perl. Усталёўваны:

sudo apt-get install perl

6. Ствараем дырэкторыі для логаў, даём ім пэўныя правы:

sudo mkdir -p -m 770 /var/log/pgbackrest
sudo chown pgbackrest:pgbackrest /var/log/pgbackrest
sudo mkdir -p /etc/pgbackrest
sudo mkdir -p /etc/pgbackrest/conf.d
sudo touch /etc/pgbackrest/pgbackrest.conf
sudo chmod 640 /etc/pgbackrest/pgbackrest.conf
sudo chown pgbackrest:pgbackrest /etc/pgbackrest/pgbackrest.conf

7. Правяраем:

pgbackrest version

Postgres сервер (sudo карыстач або root):

Працэс усталёўкі pgbackrest на серверы з postgres аналагічны працэсу ўсталёўкі на рэпазітары (так, pgbackrest павінен стаяць на абодвух серверах), але ў 6-ым пункце другую і апошнюю каманды:

sudo chown pgbackrest:pgbackrest /var/log/pgbackrest
sudo chown pgbackrest:pgbackrest /etc/pgbackrest/pgbackrest.conf

заменны на:

sudo chown postgres:postgres /var/log/pgbackrest
sudo chown postgres:postgres /etc/pgbackrest/pgbackrest.conf

Настройка ўзаемадзеяння паміж серверамі праз passwordless SSH

Для таго, каб pgbackrest карэктна працаваў, неабходна наладзіць узаемадзеянне паміж postgres серверам і рэпазітаром па файле-ключу.

Рэпазітар (карыстальнік pgbackrest):

Ствараем пару ключоў:

mkdir -m 750 /home/pgbackrest/.ssh
ssh-keygen -f /home/pgbackrest/.ssh/id_rsa 
       -t rsa -b 4096 -N ""

Увага! Указаныя вышэй каманды выконваем без sudo.

Postgres сервер (sudo карыстач або root):

Ствараем пару ключоў:

sudo -u postgres mkdir -m 750 -p /var/lib/postgresql/.ssh
sudo -u postgres ssh-keygen -f /var/lib/postgresql/.ssh/id_rsa 
       -t rsa -b 4096 -N ""

Рэпазітар (sudo карыстальнік):

Капіяваны публічны ключ postgres сервера на сервер-рэпазітар:

(echo -n 'no-agent-forwarding,no-X11-forwarding,no-port-forwarding,' && 
       echo -n 'command="/usr/bin/pgbackrest ${SSH_ORIGINAL_COMMAND#* }" ' && 
       sudo ssh root@<postgres_server_ip> cat /var/lib/postgresql/.ssh/id_rsa.pub) | 
       sudo -u pgbackrest tee -a /home/pgbackrest/.ssh/authorized_keys

На дадзеным кроку папросіць пароль ад root карыстальніка. Уводзіць трэба менавіта пароль root карыстальніка postgres сервера!

Postgres сервер (sudo карыстальнік):

Капіяваны публічны ключ рэпазітара на сервер з postgres:

(echo -n 'no-agent-forwarding,no-X11-forwarding,no-port-forwarding,' && 
       echo -n 'command="/usr/bin/pgbackrest ${SSH_ORIGINAL_COMMAND#* }" ' && 
       sudo ssh root@<repository_server_ip> cat /home/pgbackrest/.ssh/id_rsa.pub) | 
       sudo -u postgres tee -a /var/lib/postgresql/.ssh/authorized_keys

На дадзеным кроку папросіць пароль ад root карыстальніка. Уводзіць трэба менавіта пароль root карыстальніка рэпазітара!

правяраем:

Рэпазітар (root карыстач, для чысціні эксперыменту):

sudo -u pgbackrest ssh postgres@<postgres_server_ip>

Postgres сервер (root карыстач, для чысціні эксперыменту):

sudo -u postgres ssh pgbackrest@<repository_server_ip>

Пераканаемся, што без праблем атрымліваем доступ.

Настройка postgres сервера

Postgres сервер (sudo карыстач або root):

1. Дазволім "стукацца" на postgres сервер з вонкавых ip. Для гэтага адрэдагуемы файл postgresql.conf (знаходзіцца ў тэчцы /etc/postgresql/11/main), дадаўшы ў яго радок:

listen_addresses = '*'

Калі такі радок ужо ёсць - альбо раскаментуйце яго, альбо ўсталюеце значэнне параметра як '*'.

У файле pg_hba.conf (таксама знаходзіцца ў тэчцы /etc/postgresql/11/асноўны) дадаем наступныя радкі:

hostssl  all  all  0.0.0.0/0  md5
host  all  all  0.0.0.0/0  md5

дзе:

hostssl/host - подключаемся через SSL (или нет)
all - разрешаем подключение ко всем базам
all - имя пользователя, которому разрешаем подключение (всем)
0.0.0.0/0 - маска сети с которой можно подключаться
md5 - способ шифрования пароля

2. Унясем неабходныя налады ў postgresql.conf (ён знаходзіцца ў тэчцы /etc/postgresql/11/асноўны) для працы pgbackrest:

archive_command = 'pgbackrest --stanza=main archive-push %p' # Где main - название кластера. При установке postgres автоматически создает кластер main.
archive_mode = on
max_wal_senders = 3
wal_level = replica

3. Унясем неабходныя налады ў файл канфігурацыі pgbackrest (/etc/pgbackrest/pgbackrest.conf):

[main]
pg1-path=/var/lib/postgresql/11/main

[global]
log-level-file=detail
repo1-host=<repository_server_ip>

4. Перазагрузім postgresql:

sudo service postgresql restart

Настройка сервера-рэпазітара

Рэпазітар (pgbackrest карыстальнік):

Унясём неабходныя налады ў файл канфігурацыі pgbackrest
(/etc/pgbackrest/pgbackrest.conf):

[main]
pg1-host=<postgres_server_ip>
pg1-path=/var/lib/postgresql/11/main

[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2 # Параметр, указывающий сколько хранить полных бэкапов. Т.е. если у вас есть два полных бэкапа и вы создаете третий, то самый старый бэкап будет удален. Можно произносить как "хранить не более двух бэкапов" - по аналогии с ротациями логов. Спасибо @Aytuar за исправление ошибки.
start-fast=y # Начинает резервное копирование немедленно, прочитать про этот параметр можно тут https://postgrespro.ru/docs/postgrespro/9.5/continuous-archiving

Стварэнне сховішча

Рэпазітар (pgbackrest карыстальнік):

Ствараем новае сховішча для кластара асноўнай:

sudo mkdir -m 770 /var/lib/pgbackrest
sudo chown -R pgbackrest /var/lib/pgbackrest/
sudo -u pgbackrest pgbackrest --stanza=main stanza-create

Праверка

Postgres сервер (sudo карыстач або root):

Правяраем на postgres серверы:

sudo -u postgres pgbackrest --stanza=main --log-level-console=info check

Рэпазітар (pgbackrest карыстальнік):

Правяраем на серверы-рэпазітары:

sudo -u pgbackrest pgbackrest --stanza=main --log-level-console=info check

Пераконваемся, што ў выснове бачым радок "check command end: completed successfully".

Стаміліся? Пераходзім да самага цікавага.

Які робіцца бэкап

Рэпазітар (pgbackrest карыстальнік):

1. Выконваем рэзервовае капіраванне:

sudo -u pgbackrest pgbackrest --stanza=main backup

2. Пераконваемся, што бэкап быў створаны:

ls /var/lib/pgbackrest/backup/main/

Pgbackrest створыць першы поўны бэкап. Пры жаданні вы можаце запусціць каманду бэкапу паўторна і пераканацца, што сістэма створыць інкрыментальны бэкап.

Калі вы хочаце паўторна зрабіць поўны бэкап, то ўкажыце дадатковы сцяг:

sudo -u pgbackrest pgbackrest --stanza=main --type=full backup

Калі вы жадаеце падрабязную выснову ў кансоль, то таксама пазначце:

sudo -u pgbackrest pgbackrest --stanza=main --type=full --log-level-console=info backup

Аднаўляем бэкап

Postgres сервер (sudo карыстач або root):

1. Спыняем які працуе кластар:

sudo pg_ctlcluster 11 main stop

2. Аднаўляемся з бэкапу:

sudo -u postgres pgbackrest --stanza=main --log-level-console=info --delta --recovery-option=recovery_target=immediate restore

Каб аднавіць базу ў стан апошняга поўнага бэкапу выкарыстоўвайце каманду без указання recovery_target:

sudo -u postgres pgbackrest --stanza=main --log-level-console=info --delta restore

Важна! Пасля аднаўлення можа апынуцца так, што база завісне ў рэжыме аднаўлення (будуць памылкі ў духу ERROR: cannot execute DROP DATABASE in a read-only transaction). Шчыра кажучы, я яшчэ не зразумеў, з чым гэта злучана. Вырашаецца наступным чынам (трэба будзе крыху пачакаць пасля выканання каманды):

sudo -u postgres psql -c "select pg_wal_replay_resume()"

Насамрэч, ёсць магчымасць аднавіць пэўны бэкап па ім імені. Тут я толькі пакажу спасылку на апісанне дадзенай фічы ў дакументацыі. Распрацоўнікі раяць выкарыстоўваць дадзены параметр з асцярожнасцю і тлумачаць чаму. Ад сябе магу дадаць, што я яго выкарыстоўваў. Калі вельмі трэба - пераканайцеся, што пасля аднаўлення база выйшла з recovery mode (select pg_is_in_recovery() павінен паказаць "f") і на ўсялякі выпадак зрабіце поўны бэкап пасля аднаўлення.

3. Запускаем кластар:

sudo pg_ctlcluster 11 main start

Пасля аднаўлення бэкапу нам неабходна выканаць паўторны бэкап:

Рэпазітар (pgbackrest карыстальнік):

sudo pgbackrest --stanza=main backup

На гэтым усё. У заключэнне хачу нагадаць, што я ні ў якім разе не спрабую будаваць з сябе senior dba і пры найменшай магчымасці буду выкарыстоўваць аблокі. У наш час сам пачынаю вывучаць розныя тэмы накшталт рэзервовага капіявання, рэплікацый, маніторынгу і да т.п. і аб выніках пішу невялікія справаздачы, каб зрабіць невялікі фундуш у супольнасць і пакінуць для сябе невялікія шпаргалкі.

У наступных артыкулах пастараюся распавесці аб дадатковых фічах - аднаўленне дадзеных на чысты кластар, шыфраванне бэкапаў і публікацыю на S3, бэкапы праз rsync.

Крыніца: habr.com

Дадаць каментар