В продолжение старой темы про резервное копирование решил накидать про то как отправлять бекапы в облако быстро и весело.
В моём случае бакапы будут отправляться в Selectel (надо в России, чтобы всё хостилось, ну, вы знаете), но по большому счёту от других стореждей отличаться будут только реквизиты авторизации по swift-протоколу.
Сценарий не сложный: сборка инкрементальных бекапов будет делаться с помощью duplicity, который по swift будет отправлять сгенерированные бекапы в облачное хранилище Selectel. Основная тут сложность в отправке, нужен клиент для работы со swift.
Установка swift-клиента на Ubuntu 14 и 16
В несколько шагов устанавливаем клиента:
Сперва, сразу добавляем в переменные окружения реквизиты необходимые для работы с сервисом через swift (пароль и пользователя необходимо взять из аккаунта Selectel):
# ~/.bash_profile export SWIFT_USERNAME="some_user" export SWIFT_PASSWORD="some_pass" export SWIFT_AUTHURL="https://auth.selcdn.ru" export SWIFT_AUTHVERSION="1"
Не забудем сразу это подхватить:
$ source ~/.bash_profile
Кстати, в этот момент лучше уже создать специальный контейнер в Selectel для бекапов. Ниже он понадобится, в данном случае он называется backups.
Обновляемся и устанавливаем необходимые пакеты из репы:
$ apt-get update $ apt-get install python-pip gnupg2 python-paramiko python-pycryptopp python-boto python-dev librsync-dev python-lockfile libffi-dev libssl-dev
Устанавливаем непосредственно питоновский swift-клиент версию 2.2 т.к. была странная бага при первой установке: подозрительное поведение похожее на невозможность авторизации доп. пользователя в Selectel. В 2.2 всё нормально работает (хотя уже есть версия 3), а написано это тут (не совсем это, но почти).
$ pip install --upgrade pip $ pip install -Iv python-swiftclient==2.2 python-keystoneclient==2.2
Если установка прошла хорошо, то можно сразу перейти к следующему пункту.
В процессе множества попыток установить первый раз была бага при установке python-keystoneclient. Из кеша pip подтягивал не то что надо (что в первый раз пытались установить, а не в текущий, не смотря на указанную версию) и потому всё крешелось (как ниже обозначена ошибка). Выход нашёл тут.
Command python setup.py egg_info failed with error code 1 in /tmp/pip_build_root/positional Storing debug log for failure in /root/.pip/pip.log
Необходимо кое-что доставить для python:
$ pip install --upgrade --force requests[security] # или если zsh # pip install --upgrade --force requests\[security\]
На Ubuntu 16 пришлось ещё кое-что доставить (тут про это):
$ pip install --force pyOpenSSL ndg-httpsclient pyasn1
Установка duplicity и бекап
Для того чтобы начать бекапить в облако надо собрать и настроить duplicity:
Собираем свежий duplicity (взято с DO). Релизы duplicity можно посмотреть по этому FTP.
$ cd /root $ wget http://ftp.acc.umu.se/mirror/gnu.org/savannah//duplicity/duplicity-0.7.10.tar.gz $ tar xzvf duplicity* $ cd duplicity* $ python setup.py install $ cd .. $ rm -rf duplicity*
Создаём необходимые директории для складывания бекапов, логов и конфига.
$ mkdir -p /var/backups/dump/mysql/ $ mkdir /var/backups/dump/mongodb/ $ mkdir /var/log/duplicity/
Устанавливаем маленький скрипт duplicity-backup.sh позволяющий все параметры для duplicity держать в виде удобного конфига:
$ cd /opt $ git clone --branch v1.3.0 https://github.com/zertrin/duplicity-backup.sh.git duplicity-backup
Делаем файл исполняемым:
$ chmod +x /opt/duplicity-backup/duplicity-backup.sh
Создаём конфиг, где указано какие директории бекапить, куда отправлять (в директорию по названию сервера) и др. Более подробно про конфиг можно поглядеть в примере /opt/duplicity-backup/duplicity-backup.conf.example. А тут приведён его короткий вариант (без комментариев) без шифрования и подписи бекапов:
# /opt/duplicity-backup/duplicity-backup.conf #!/bin/bash ENCRYPTION="no" ROOT="/" # HOSTNAME=$(hostname -f) DEST="swift://backups/${HOSTNAME}" INCLIST=("/opt" "/root" "/etc" "/var" "/srv" "/home") STATIC_OPTIONS="--full-if-older-than 1M" CLEAN_UP_TYPE="remove-all-but-n-full" CLEAN_UP_VARIABLE="2" LOGDIR="/var/log/duplicity/" LOG_FILE="duplicity-`date +%Y-%m-%d_%H-%M`.log" LOG_FILE_OWNER="root:root" VERBOSITY="-v3" #EMAIL_TO= #EMAIL_FROM= #EMAIL_SUBJECT= #EMAIL_FAILURE_ONLY="yes" # send e-mail only if there was an error while creating backup #MAIL="mailx" # default command for Linux mail # Possible values for NOTIFICATION_SERVICE are: slack, pushover, ifttt NOTIFICATION_SERVICE="slack" NOTIFICATION_FAILURE_ONLY="yes" # send notifications only if there was an error while creating backup # Provider: Slack SLACK_HOOK_URL="https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxx" SLACK_CHANNEL="#error" SLACK_USERNAME="duplicity-backup" SLACK_EMOJI="package"
Внимание! При копировании конфига могут была странная ошибка с INCLIST, там добавлялся скрытый символ, или что-то вроде того, и в конечном итоге при бекапе в du попадала строка с пробелом в начале и всё крешелось. Просто на всякий случай предупреждаю т.к. сам столкнулся.
По конфигу не должно быть особых сложностей. Обращаю только внимание, что в параметре DEST собственно и указан наш контейнер из Selectel, к которому идёт обращение по протоколу swift по реквизитам, которые мы указали в переменных окружения.
Кстати, прошу заметить, что в конце конфига есть оповещения в Slack, если произошла ошибка во время бекапа. Очень полезно.
И про ротацию логов не забываем. Т.к. при каждом запуске создаётся отдельный файл-лог, то надо бы всё это ротировать, а то так в скором времени толпы файлов будут. Добавляем новый конфиг /etc/logrotate.d/duplicity:
/var/log/duplicity/*.log { daily missingok rotate 30 compress delaycompress copytruncate notifempty }
Устанавливаем в crontab команду, которая собирает и отправляет необходимые файлы. Но обратите внимание, что всегда перед запуском duplicity подтягивается .bash_profile, в противном случае окружение в крон само не пробрасывается.
Тут я привёл примеры команд для бекапа разных штук:
MySQL (базы храняться 14 дней, вместо USER и PASS свои доступы):
0 2 * * * /bin/mkdir -p /var/backups/dump/mysql/ && /usr/bin/find /var/backups/dump/mysql/ -mtime +14 -delete && /usr/bin/mysqldump --single-transaction --routines --events --triggers --add-drop-table --extended-insert -uUSER -h127.0.0.1 -pPASS -A | gzip -9 > /var/backups/dump/mysql/$(date + '\%d-\%m-\%y').sql && . $HOME/.bash_profile ; /opt/duplicity-backup/duplicity-backup.sh -c /opt/duplicity-backup/duplicity-backup.conf --backup
MongoDB (базы храняться 14 дней):
0 2 * * * /bin/mkdir -p /var/backups/dump/mongodb/ && /usr/bin/find /var/backups/dump/mongodb/ -mtime +14 -delete && /usr/bin/mongodump -o /var/backups/dump/mongodb/$(date +'\%d-\%m-\%y') && . $HOME/.bash_profile ; /opt/duplicity-backup/duplicity-backup.sh -c /opt/duplicity-backup/duplicity-backup.conf --backup
GitLab:
0 2 * * * /usr/bin/gitlab-rake gitlab:backup:create && . $HOME/.bash_profile ; /opt/duplicity-backup/duplicity-backup.sh -c /opt/duplicity-backup/duplicity-backup.conf --backup
После этого каждый день в 2а часа ночи будет создаваться бека указанных в конфиге директорий. Для проверки желательно сразу запустить команду.
Устранение проблем
Если потребуется удалить duplicity, то можно это устроить. Поскольку это python, то по’python’овски и удалять, находим все установленные файлы во время установки и удаляем их:
$ python setup.py install --record files.txt
$ cat files.txt | xargs rm -rf
На этом мне больше сказать нечего. Удачи!