64

WAL-G — инструмент для бэкапа и восстановления БД

Серия SRE

WAL-G — прекрасный, быстрый, простой и эффективный инструмент для резервного копирования БД (PostgreSQL/MySQL/MariaDB/MongoDB/FoundationDB и т.п.) в почти любые облака (Amazon S3/MinIO, Yandex Object Storage, Google Cloud Storage, Azure Storage, Swift Object Storage и просто на файловую систему).


Исходники на github, собранные rpm под CentOS.


Расскажу на примере PostgreSQL и MongoDB, как пользоваться этой штукой. Версии актуальны на август 2022 года.


Все бэкапы складываю в MinIO — легкое хранилище объектов, совместимое с Amazon S3.

В местном редакторе не предусмотрен тег для кода, поэтому буду оформлять его в цитаты.


PostgreSQL


Для теста на одном из хостов поднимем PostgreSQL12:

yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL- 7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install postgresql12-server
/usr/pgsql-12/bin/postgresql-12-setup initdb
systemctl enable postgresql-12 && systemctl start postgresql-12

создаю тестовую базу:

su — postgres
psql
create database test1;
\c test1;
CREATE TABLE indexing_table(created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW());

Генерирую и вливаю в тестовую базу данные размером около 1 Гб:


CREATE TABLE large_for_test (num1 bigint, num2 double precision, num3 double precision);
INSERT INTO large_for_test (num1, num2, num3)
SELECT round(random()*10), random(), random()*142
FROM generate_series(1, 20000000) s(i);
EXPLAIN (analyse, buffers)
SELECT num1, avg(num3) as num3_avg, sum(num2) as num2_sum
FROM large_for_test
GROUP BY num1;


Чтобы архиватор внутри базы сам заливал WAL-журналы в облако и восстанавливался из них (в случае необходимости) настраиваю некоторые параметры в postgresql.conf:

wal_level=replica
archive_mode=on
archive_command=’/usr/local/bin/wal-g wal-push \”%p\” >> /var/log/postgresql/archive_command.log 2>&1'
archive_timeout=60
restore_command=’/usr/local/bin/wal-g wal-fetch \”%f\” \”%p\” >> /var/log/postgresql/restore_command.log 2>&1'

Подробнее обо всех этих параметрах можно прочитать в переводе официальной документации.


И рестартую PostgreSQL:

systemctl restart postgresql-12

На тот же хост, где и PostgreSQL, ставлю WAL-G версии 0.2.15 (по сути — это просто один бинарник, без внешних зависимостей):

curl -L https://github.com/wal-g/wal-g/releases/download/v0.2.15/wal... -o wal-g.linux-amd64.tar.gz
tar -xzf wal-g.linux-amd64.tar.gz
mv wal-g /usr/local/bin/
Бинарники (для разных БД) самой свежей на данный момент версии 2.0.1 лежат здесь.


Для конфигурирования WAL-G нужно положить файл .walg.json (пример файла здесь) в домашнюю директорию пользователя postgres:

cat > /var/lib/pgsql/.walg.json << EOF
{
"AWS_ENDPOINT": "http://minio:9000",
"WALG_S3_PREFIX": "s3://pgbackup",
"AWS_ACCESS_KEY_ID": "admin",
"AWS_SECRET_ACCESS_KEY": "password",
"AWS_S3_FORCE_PATH_STYLE": "true",
"WALG_COMPRESSION_METHOD": "brotli",
"WALG_DELTA_MAX_STEPS": "5",
"PGDATA": "/var/lib/pgsql/12/main",
"PGHOST": "/var/run/postgresql/.s.PGSQL.5432"
}
EOF

Не забываем поменять владельца этого файла:

chown postgres: /var/lib/pgsql/.walg.json
Бэкап


Проверяю создание полного бэкапа: в WAL-G это аргумент запуска backup-push. Для начала выполняю эту команду вручную от пользователя postgres, чтобы убедиться что всё хорошо (не забудьте сначала создать бакет с именем из WALG_S3_PREFIX):


time su — postgres -c ‘/usr/local/bin/wal-g backup-push /var/lib/pgsql/12/data’
INFO: 2020/08/17 06:05:00.211318 Couldn’t find previous backup. Doing full backup.
INFO: 2020/08/17 06:05:00.225448 Calling pg_start_backup()
INFO: 2020/08/17 06:05:01.819922 Walking …
INFO: 2020/08/17 06:05:01.820466 Starting part 1 …
INFO: 2020/08/17 06:05:21.049285 Finished writing part 1.
INFO: 2020/08/17 06:05:21.049323 Starting part 2 …
INFO: 2020/08/17 06:05:21.149069 Finished writing part 2.
INFO: 2020/08/17 06:05:21.659995 Starting part 3 …
INFO: 2020/08/17 06:05:21.660060 /global/pg_control
INFO: 2020/08/17 06:05:21.660309 Finished writing part 3.
INFO: 2020/08/17 06:05:21.662065 Calling pg_stop_backup()
INFO: 2020/08/17 06:05:23.878346 Starting part 4 …
INFO: 2020/08/17 06:05:23.878460 backup_label
INFO: 2020/08/17 06:05:23.878490 tablespace_map
INFO: 2020/08/17 06:05:23.878635 Finished writing part 4.
INFO: 2020/08/17 06:05:24.924564 Wrote backup with name base_00000001000000000000007E
real 0m24.829s
user 0m20.669s
sys 0m2.323s

Бэкап ~1 Гб БД выполняется очень быстро.


В MinIO в нужном бакете появляются бэкапы, 1 Гб БД ужимается до 351.92 Мб.


Если всё прошло без ошибок, то далее можно добавить периодический запуск этой команды в crontab. Необходимо учесть, что хранение всех бэкапов вечно не имеет никакого смысла, поэтому нужно настроить удаление старых резервных копий (можно в том же кроне).


Восстановление


Попробуем восстановиться по-взрослому, удалив все данные (БД и пользователей).


Останавливаю PostrgeSQL:

systemctl stop postgresql-12

Удаляю все данные из текущей базы:

rm -rf /var/lib/pgsql/12/data

Скачиваю резервную копию и разархивирую её:

su — postgres -c ‘/usr/local/bin/wal-g backup-fetch /var/lib/pgsql/12/data LATEST’


От имени пользователя postgres помещаю рядом с базой специальный файл-сигнал для восстановления (подробнее здесь) :

su — postgres -c ‘touch /var/lib/pgsql/12/data/recovery.signal’

Запускаю базу данных, чтобы она инициировала процесс восстановления:

systemctl start postgresql-12 && systemctl status postgresql-12

Смотрим логи, там красота :)

2020–08–17 08:57:55.281 EDT [25536] LOG: starting archive recovery
2020–08–17 08:57:55.876 EDT [25536] LOG: restored log file “000000010000000100000044” from archive
2020–08–17 08:57:56.617 EDT [25536] LOG: redo starts at 1/44000028
2020–08–17 08:57:56.834 EDT [25536] LOG: restored log file “000000010000000100000045” from archive
2020–08–17 08:57:58.006 EDT [25536] LOG: consistent recovery state reached at 1/45000050
2020–08–17 08:57:58.007 EDT [25533] LOG: database system is ready to accept read only connections
2020–08–17 08:57:58.223 EDT [25536] LOG: restored log file “000000010000000100000046” from archive
2020–08–17 08:57:59.811 EDT [25536] LOG: redo done at 1/46000148
2020–08–17 08:58:00.096 EDT [25536] LOG: restored log file “000000010000000100000046” from archive
2020–08–17 08:58:00.740 EDT [25536] LOG: selected new timeline ID: 2
2020–08–17 08:58:02.291 EDT [25536] LOG: archive recovery complete
2020–08–17 08:58:07.408 EDT [25533] LOG: database system is ready to accept connections

Проверяем, что все на месте, размеры совпадают. Все отлично работает.


Восстановление на определенное время


Если нужно восстановить базу на определенную минуту, то в recovery.conf добавляем параметр recovery_target_time (задается в формате YYYY-MM-DD HH:mm:ss)— указываем на какое время восстановить базу:

restore_command = ‘/usr/local/bin/wal-fetch.sh “%f” “%p”’
recovery_target_time = ‘2020–08–14 09:00:00’

Резюмируя по Postgres:


- На каждом хосте с Postgres устанавливаем WAL-G

- на каждом хосте с Postgres правим postgresql.conf

- в home пользователя postrges кладем .walg.json

ставим команду резервного копирования (и зачистки ненужных старых бэкапов) в cron


Чтобы в дальнейшем все было красиво, я у себя для каждого хоста с БД создаю отдельный бакет (например, по имени хоста).


MongoDB


Для тестов на одном из хостов поднимаю MongoDB 4.4 и использую тот же инстанс MinIO c созданным под эти цели бакетом mongo.


Заливаю в Монгу тестовые данные:

curl -LO https://raw.githubusercontent.com/mongodb/docs-assets/primer...
mongoimport — db test — collection restaurants — file /tmp/primer-dataset.json
2020–08–18T06:05:46.661–0400 connected to: mongodb://localhost/
2020–08–18T06:05:48.746–0400 25359 document(s) imported successfully. 0 document(s) failed to import.

Бэкап


В директории пользователя, от имени которого запускается бэкап, должен лежать файл .walg.json c примерно следующим содержимым (подробное описание параметров в документации):

{
“WALG_S3_PREFIX”: “s3://mongo”,
“AWS_ACCESS_KEY_ID”: “minioadmin”,
“AWS_SECRET_ACCESS_KEY”: “minioadmin”,
“AWS_ENDPOINT”: “http://minio:9000",
“AWS_S3_FORCE_PATH_STYLE”: “true”,
“WALG_STREAM_CREATE_COMMAND”: “mongodump — archive — uri=\”mongodb://127.0.0.1:27017\””,
“WALG_STREAM_RESTORE_COMMAND”: “mongorestore — archive — drop — uri=\”mongodb://127.0.0.1:27017\””,
“MONGODB_URI”: “mongodb://127.0.0.1:27017”,
“WALG_SENTINEL_USER_DATA”: “{\”key\”: \”value\”}”,
“OPLOG_ARCHIVE_TIMEOUT_INTERVAL”: “5s”,
“OPLOG_ARCHIVE_AFTER_SIZE”: “1048576”,
“WALG_COMPRESSION_METHOD”: “brotli”,
“WALG_DISK_RATE_LIMIT”: “41943040”,
“WALG_NETWORK_RATE_LIMIT”: “10485760”,
“WALG_LOG_LEVEL”: “DEVEL”,
“WALG_UPLOAD_CONCURRENCY” : 1,
“OPLOG_PITR_DISCOVERY_INTERVAL”: “168h”
}

Особо нужно обратить внимание на параметр MONGODB_URI, который используется для подключения к инстансу MongoDB — например, при необходимости подключения к определенной БД, при необходимости указать пользователя/логин/пароль для подключения и т.п. (документация).


Для бэкапа нужно выполнить команду

wal-g backup-push
2020–09–05T03:51:21.247–0400 writing admin.system.version to archive on stdout
2020–09–05T03:51:21.252–0400 done dumping admin.system.version (1 document)
2020–09–05T03:51:21.252–0400 writing test.restaurants to archive on stdout
2020–09–05T03:51:21.324–0400 done dumping test.restaurants (25359 documents)
INFO: 2020/09/05 03:51:21.504031 FILE PATH: stream_20200905T075121Z/stream.br
INFO: 2020/09/05 03:51:21.511747 Removing sigmask. Shutting down

После выполнения команды бэкап появляется в бакете.

Для периодичного бэкапа можно запускать эту команду в cron’e (и опять же, не забываем удалять старые бэкапы).


Восстановление


Смотрим командой wal-g backup-list список имеющихся у нас бэкапов:


wal-g backup-list
name last_modified wal_segment_backup_start
stream_20200905T075121Z 2020–09–05T07:51:21Z ZZZZZZZZZZZZZZZZZZZZZZZZ
stream_20200905T082140Z 2020–09–05T08:21:40Z ZZZZZZZZZZZZZZZZZZZZZZZZ

и командой wal-g backup-fetch backup-name восстанавливаем нужный нам бэкап:

wal-g backup-fetch stream_20200905T075121Z
2020–09–05T04:11:39.297–0400 preparing collections to restore from
2020–09–05T04:11:40.295–0400 reading metadata for test.restaurants from archive on stdin
2020–09–05T04:11:40.319–0400 restoring test.restaurants from archive on stdin
2020–09–05T04:11:40.717–0400 no indexes to restore
2020–09–05T04:11:40.717–0400 finished restoring test.restaurants (25359 documents, 0 failures)
2020–09–05T04:11:40.717–0400 25359 document(s) restored successfully. 0 document(s) failed to restore.
INFO: 2020/09/05 04:11:40.720019 Removing sigmask. Shutting down

Все прекрасно работает.


Чем WAL-G лучше того же pg_dump (или pg_basebackup или Barman и т.п.) хорошо написано здесь (очень хорошая статья для понимания, как это устроено и работает), если вкратце — то это инструмент разработчика и он не предназначен для работы с высоконагруженной БД.


Рекомендую попробовать, уверен, что понравится :) Если что - спрашивайте!

Лига Сисадминов

2.5K поста19K подписчиков

Правила сообщества

Мы здесь рады любым постам связанным с рабочими буднями специалистов нашей сферы деятельности.

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества