Планирование бэкапа MongoDB в хранилище объектов

Регулярное резервное копирование баз данных – очень важный компонент защиты данных от непредвиденных ситуаций и потери. В целом существует две широкие категории резервных копий – физические (на уровне файловой системы) и логические.

Физический бэкап подразумевает создание снапшота основных файлов данных в определенный момент времени и возможность восстановить БД с использованием состояния, зафиксированного в снапшоте. Этот метод позволяет быстро создавать резервные копии больших баз данных, особенно если они используются вместе со снапшотами файловой системы или блочного хранилища.

Читайте также: Основы работы со снапшотами

Логический бэкап подразумевает использование инструмента (например, mongodump или pg_dump) для экспорта данных из БД в файлы резервных копий, которые затем восстанавливаются с помощью соответствующего инструмента восстановления (например, mongorestore или pg_restore). Они обеспечивают подробный контроль над копированием и восстановлением, а полученные резервные копии обычно можно использовать для разных версий и установок СУБД. Поскольку логические средства резервного копирования считывают все данные, хранящиеся в памяти, логический бэкап выполняется медленно и может вызвать серьезную дополнительную нагрузку при копировании особо больших БД.

Данный мануал научит вас создавать резервные копии MongoDB с помощью mongodump, встроенного инструмента логического бэкапа. Также вы узнаете, как сжать и загрузить полученные файлы данных в удаленное хранилище и научитесь планировать резервное копирование и загрузки с помощью Bash и cron и, конечно, восстанавливать данные.

В результате вы получите платформу для расширяемой стратегии автоматического резервного копирования, которая позволит вам быстро восстановить утраченные данные. В небольших базах и базах данных среднего размера mongodump дает четкий контроль над копированием и восстановлением. Хранение этих сжатых архивов данных в удаленном хранилище объектов обеспечит быстрый и постоянный доступ к ним, так что данные вашего приложения будут защищены и быстро восстановлены в случае потери.

Примечание: Использование инструмента mongodump, особенно в сильно загруженных базах данных, может повлиять на производительность. Рекомендуем сначала протестировать бэкап на тестовой БД, чтобы убедиться, что этот метод будет работать в среде производства.

Требования

1: Тестовые данные

Если вы начинаете работу с чистой БД, и пока у вас еще нет данных, нужно создать тестовые данные. Для примера здесь будет использоваться фиктивная коллекция restaurants. Если же у вас уже есть коллекции данных, с которыми вы можете работать, пропустите этот раздел.

Подключитесь к запущенной БД:

mongo

Вы увидите командную строку Mongo:

MongoDB shell version: 3.2.19
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten]
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-11T20:30:57.320+0000 I CONTROL  [initandlisten]
>

По умолчанию оболочка подключается к базе данных test.

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

show collections

Поскольку вы еще ничего не добавили в базу данных, коллекций сейчас в ней нет, и вы вернетесь в командную строку без вывода.

Вставьте документ в фиктивную коллекцию restaurants, которая будет автоматически создана (так как она еще не существует):

db.restaurants.insert({'name': 'Pizzeria Mario'})

Вы увидите такой вывод:

WriteResult({ "nInserted" : 1 })

Значит, данные успешно добавлены.

Снова просмотрите коллекции:

show collections

Теперь коллекция restaurants будет в списке:

restaurants

Чтобы закрыть оболочку MongoDB, нажмите CTRL + D.

2: Резервное копирование данных MongoDB с помощью mongodump

Теперь нужно использовать встроенную утилиту mongodump для резервного копирования (или дампа) всей базы данных MongoDB в сжатый архив.

Сначала создадим временный каталог под названием backup для хранения архива mongodump:

mkdir backup

Теперь создайте тестовую базу данных test в этом экземпляре MongoDB в сжатом архиве test_dump.gz. Если ваш экземпляр содержит другие базы данных, вы можете указать другое имя базы данных после флага —db. Вы также можете опустить флаг -db для запуска резервного копирования всех баз данных вашего экземпляра MongoDB.

Примечание: Следующую команду нужно запускать из терминала, а не из оболочки Mongo.

mongodump --db test --archive=./backup/test_dump.gz --gzip

Здесь используется флаг —archive, который указывает, что все данные нужно сохранить в один файл архива (чье местоположение указано параметром archive); флаг –gzip указывает, что файл нужно сжать. Кроме того, вы можете использовать флаги —collection или —query для выбора коллекции или запроса для архивации. Чтобы узнать больше об этих флагах, проконсультируйтесь с документацией mongodump.

Вы увидите такой вывод:

2018-04-13T16:29:32.191+0000    writing test.restaurants to archive './backup/test_dump.gz'
2018-04-13T16:29:32.192+0000    done dumping test.restaurants (1 document)

Это значит, что резервное копирование БД прошло успешно.

3: Загрузка резервных данных в хранилище объектов

Чтобы загрузить архив в хранилище, нужен инструмент s3cmd.

Сначала проверьте конфигурацию s3cmd и попытайтесь получить доступ к хранилищу. В этом мануале мы будем использовать mongo-backup-demo в качестве тестового хранилища (но вы должны указать имя вашего хранилища):

s3cmd info s3://mongo-backup-demo/
s3://mongo-backup-demo/ (bucket):
Location:  nyc3
Payer:     BucketOwner
Expiration Rule: none
Policy:    none
CORS:      none
ACL:       3587522: FULL_CONTROL

Это значит, что соединение установлено успешно и s3cmd может перемещать объекты в хранилище.

Теперь давайте переместим созданный ранее архив:

s3cmd put ./backup/test_dump.gz s3://mongo-backup-demo/
upload: './backup/test_dump.gz' -> 's3://mongo-backup-demo/test_dump.gz'  [1 of 1]
297 of 297   100% in    0s    25.28 kB/s  done

Как только передача данных будет завершена, убедитесь, что файл был успешно перенесен в хранилище:

s3cmd ls s3://mongo-backup-demo/

Вы должны увидеть архив резервной копии:

2018-04-13 20:39       297   s3://mongo-backup-demo/test_dump.gz

На этом этапе вы успешно создали резервную копию базы данных MongoDB и перенесли резервный архив в ваше хранилище.

4: Создание и тестирование сценария для автоматизации резервного копирования

Теперь вы можете соединить все проделанные ранее действия в один скрипт Bash.

Создание сценария Bash

Сначала нужно написать сценарий, объединяющий команды mongodump и s3cmd put, и добавить несколько дополнительных записей.

Откройте пустой файл в текстовом редакторе (здесь мы будем использовать nano):

nano backup_mongo.sh

Вставьте следующие фрагменты кода, обновив соответствующие имена хранилища, базы данных и файлов. Здесь файл будет называться backup_mongo.sh, но вы можете назвать этот файл как хотите. Полный код скрипта вы найдете в конце этого раздела.

Начните сценарий строками:

#!/bin/bash
set -e
...

Строка  #!/bin/bash сообщает оболочке интерпретировать сценарий как код Bash. Строка set -e говорит интерпретатору немедленно выйти, если какая-либо из команд сценария завершилась неудачно.

...
STORAGE_NAME=mongo-backup-demo
BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
DB=test
...

В этом разделе устанавливаются три переменные:

STORAGE_NAME: имя хранилища, в которое нужно загрузить копии.
BACKUP_NAME: имя архива с резервными копиями.
DB: база данных MongoDB, которую нужно копировать. Если вы создаете резервную копию всего экземпляра MongoDB (всех баз данных), эта переменная не нужна.

...
date
echo "Backing up MongoDB database to storage: $STORAGE_NAME"
echo "Dumping MongoDB $DB database to compressed archive"
mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip
echo "Copying compressed archive to storage: $STORAGE_NAME"
s3cmd put $HOME/backup/tmp_dump.gz s3://$STORAGE_NAME/$BACKUP_NAME
...

Затем мы выводим дату и время (для логирования) и запускаем резервное копирование с помощью команды mongodump, которую тестировали выше. Снова сохраняем резервный архив в ~/backup/.

После этого s3cmd копирует этот архив в место, указанное переменными STORAGE_NAME и BACKUP_NAME. Например, если имя пространства – это mongo-backup-demo, а текущая дата и время – 2018/04/12 12:42:21, резервная копия будет называться 180412_124221.gz и будет сохранена в хранилище mongo-backup-demo.

...
echo "Cleaning up compressed archive"
rm $HOME/backup/tmp_dump.gz
echo 'Backup complete!'

Этот код удалит резервный архив из каталога ~/backup, поскольку он успешно скопирован в хранилище, и в выводе сообщит, что резервное копирование завершено.

Полный сценарий должен выглядеть так:

#!/bin/bash
set -e
STORAGE_NAME=mongo-backup-demo
BACKUP_NAME=$(date +%y%m%d_%H%M%S).gz
DB=test
date
echo "Backing up MongoDB database to storage: $STORAGE_NAME"
echo "Dumping MongoDB $DB database to compressed archive"
mongodump --db $DB --archive=$HOME/backup/tmp_dump.gz --gzip
echo "Copying compressed archive to storage: $STORAGE_NAME"
s3cmd put $HOME/backup/tmp_dump.gz s3://$STORAGE_NAME/$BACKUP_NAME
echo "Cleaning up compressed archive"
rm $HOME/backup/tmp_dump.gz
echo 'Backup complete!'

Сохраните файл.

Тестирование сценария

Теперь попробуйте запустить сценарий backup_mongo.sh.

Сделайте его исполняемым:

chmod +x backup_mongo.sh

А затем запустите его:

./backup_mongo.sh

Вы получите такой вывод:

Mon Apr 16 22:20:26 UTC 2018
Backing up MongoDB database to storage: mongo-backup-demo
Dumping MongoDB test database to compressed archive
2018-04-16T22:20:26.664+0000    writing test.restaurants to archive '/home/8host/backup/tmp_dump.gz'
2018-04-16T22:20:26.671+0000    done dumping test.restaurants (1 document)
Copying compressed archive to storage: mongo-backup-demo
upload: '/home/8host/backup/tmp_dump.gz' -> 's3://mongo-backup-demo/180416_222026.gz'  [1 of 1]
297 of 297   100% in    0s     3.47 kB/s  done
Cleaning up compressed archive
Backup complete!

Теперь можно запланировать запуск этого скрипта в cron.

5: Планирование ежедневного бэкапа с помощью cron

Чтобы запланировать запуск сценария резервного копирования ночью, можно использовать cron, утилиту планирования заданий, встроенную в Unix-подобные операционные системы.

Сначала создайте каталог для хранения логов сценария резервного копирования. Затем добавьте сценарий в файл конфигурации crontab (cron), чтобы демон мог запускать его каждую ночь. Поскольку cron поддерживает любую частоту запуска задач, вы можете дополнительно спланировать еженедельное или ежемесячное резервное копирование.

Создание каталога для логов сценария

Создайте каталог для хранения логов сценария резервного копирования. Эти логи позволят вам периодически проверять сценарий, чтобы убедиться, что все в порядке; также их можно использовать для отладки.

Создайте подкаталог mongo_backup в /var/log:

sudo mkdir /var/log/mongo_backup

Затем дайте пользователю Unix право на запись в нем. В данном случае пользователь условно называется 8host (укажите имя своего пользователя).

sudo chown 8host:8host /var/log/mongo_backup

Теперь этот пользователь имеет право на запись в /var/log/mongo_backup. Поскольку cronjob запускается от имени 8host, он теперь может писать в логах.

Создание cronjob

Чтобы запланировать сценарий, нужно отредактировать crontab. На каждого пользователя выделяется по одному crontab-у, также есть общий crontab в /etc/crontab. Запланировать сценарий нужно в crontab-е вашего текущего пользователя (здесь это 8host). В некоторых ситуациях это можно сделать и в общесистемном crontab-е.

Откройте crontab:

crontab -e

Вам будет предложено выбрать текстовый редактор:

no crontab for 8host - using an empty one
Select an editor.  To change later, run 'select-editor'.
1. /bin/ed
2. /bin/nano <---- easiest
3. /usr/bin/vim.basic
4. /usr/bin/vim.tiny
Choose 1-4 [2]: no crontab for 8host - using an empty one

Выберите редактор, указав его порядковый номер. Затем добавьте в файл после закомментированных строк следующую строку:

# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
0 2 * * * /home/8host/mongo_backup.sh >>/var/log/mongo_backup/mongo_backup.log 2>&1

Обязательно добавьте новую строку в конце crontab. Сохраните и закройте файл.

Вы увидите следующий результат:

no crontab for 8host - using an empty one
crontab: installing new crontab

Сценарий резервного копирования будет запускаться в 2 часа ночи. stdout и stderr (потоки выходных данных и ошибок) будут переданы и добавлены в лог mongo_backup.log в каталоге, который вы создали ранее.

Вы можете изменить 0 2 * * * (2 часа ночи в синтаксисе cron)  и указать другое время и частоту резервного копирования. Чтобы узнать больше о cron и его синтаксисе, ознакомьтесь с руководством Автоматизация задач с помощью Cron.

6: Тестовое восстановление данных

Любая стратегия резервного копирования должна содержать процедуру восстановления, которую нужно регулярно тестировать. Попробуйте восстановить данные из файла резервной копии, который вы загрузили в хранилище.

Сначала загрузите test_dump.gz из хранилища в домашний каталог на сервере MongoDB:

s3cmd get s3://mongo-backup-demo/test_dump.gz
download: 's3://mongo-backup-demo/test_dump.gz' -> './test_dump.gz'  [1 of 1]
297 of 297   100% in    0s  1305.79 B/s  done

Если вы начали работу со свежего экземпляра MongoDB, у вас будет только БД test, которая, в свою очередь, стала единственной скопированной БД.

Для демонстрации теперь нужно удалить тестовую базу данных, чтобы вы могли выполнить чистое восстановление. Если мы не сделаете этого, процедура восстановления столкнется с оригинальными документами и не восстановит никаких данных – все они есть в оригиналах.

Подключитесь к MongoDB:

mongo

Выберите БД test и удалите ее с экземпляра MongoDB.

use test
db.dropDatabase()

Вы увидите:

{ "dropped" : "test", "ok" : 1 }

Теперь выйдите из оболочки mongo и выполните команду mongorestore:

mongorestore --gzip --archive=test_dump.gz --db test

В команде указано, что исходный файл резервной копии сжимается и хранится в формате архива (напомним, что мы использовали флаги —archive и —gzip при вызове mongodump).

2018-04-16T23:10:07.317+0000    creating intents for archive
2018-04-16T23:10:07.453+0000    reading metadata for test.restaurants from archive 'test_dump.gz'
2018-04-16T23:10:07.497+0000    restoring test.restaurants from archive 'test_dump.gz'
2018-04-16T23:10:07.541+0000    restoring indexes for collection test.restaurants from metadata
2018-04-16T23:10:07.541+0000    finished restoring test.restaurants (1 document)
2018-04-16T23:10:07.541+0000    done

Этот вывод значит, что БД восстановлена успешно.

Теперь убедитесь, что данные коллекции restaurants успешно восстановлены.

Откройте оболочку MongoDB и запросите коллекцию:

db.restaurants.find()

Вы увидите объект, сохраненный в первом разделе мануала:

{ "_id" : ObjectId("5ace7614dbdf8137afe60025"), "name" : "Pizzeria Mario" }

Вы успешно скопировали и восстановили данные.

Заключение

Этот мануал можно расширить:

  • В зависимости от ваших целей вы можете увеличить или уменьшить частоту резервного копирования.
  • Еще одно полезное дополнение — это функция оповещений, которая срабатывает, если подкоманда сценария резервного копирования выходит из строя (например, эта функция может отправлять электронное сообщение на ваш почтовый ящик).
  • Этот скрипт не обрабатывает удаление объектов из хранилища. Вы можете настроить ротацию резервных копий, чтобы удалять устаревшие.

Поскольку процедура mongodump включает в себя быстрое считывание всех данных, этот метод резервного копирования хорошо подходит для баз данных малого и среднего размера, особенно для частичного резервного копирования (например, копирования коллекции или набора данных). Для более крупных развертываний рекомендуется использовать бэкап на уровне файловой системы. Чтобы узнать больше о резервных копиях MongoDB на уровне файловой системы, читайте Резервное копирование базы данных MongoDB с помощью снапшотов. Чтобы узнать больше о различных методах резервного копирования базы данных MongoDB, вы можете ознакомиться с руководством MongoDB.

Решение, представленное в этом мануале, использует mongodump для управления бэкапом и удаленное хранилище объектов для экономичного и долговременного хранения данных. Чтобы узнать больше о утилите резервного копирования mongodump, обратитесь к руководству MongoDB.

Tags: , , ,