Главная » Хабрахабр » Теория и практика бэкапов с Borg

Теория и практика бэкапов с Borg

Поскольку уже более года мы с удовольствием используем его в production, в этой статье я поделюсь накопленными у нас «впечатлениями» о Borg. К нашему огромному удивлению на хабре не оказалось ни одного материала про замечательный Open Source-инструмент для резервного копирования данных ­— Borg (не путать с одноимённым прародителем Kubernetes!).

Предыстория: опыт с Bacula и Bareos

В 2017 году мы устали от Bacula и Bareos, которые использовали с самого начала своей деятельности (т.е. около 9 лет в production на тот момент). Почему? За время эксплуатации у нас накопилось немало недовольства:

  • Зависает SD (Storage Daemon). Если у вас настроена параллельность, то обслуживание SD усложняется, а его зависание блокирует дальнейшие бэкапы по расписанию и возможность восстановления.
  • Нужно генерировать конфиги и клиенту, и директору. Даже если автоматизировать это (в нашем случае в разное время применялись и Chef, и Ansible, и своя разработка), нужно мониторить, что директор после своего reload’а на самом деле подхватил конфиг. Это отслеживается только в выводе команды reload и вызове messages после (чтобы получить сам текст ошибки).
  • Расписание бэкапов. Разработчики Bacula решили пойти собственным путём и написали свой формат расписаний, который не получится просто распарсить или конвертировать в другой. Вот примеры стандартных расписаний бэкапов в наших старых инсталяциях:
    • Ежедневный полный бэкап по средам и инкрементальные в остальные дни:
      Run = Level=Full Pool="Foobar-low7" wed at 18:00
      Run = Level=Incremental Pool="Foobar-low7" at 18:00
    • Полный бэкап wal-файлов 2 раза в месяц и инкремент каждый час:
      Run = Level=Full FullPool=CustomerWALPool 1st fri at 01:45
      Run = Level=Full FullPool=CustomerWALPool 3rd fri at 01:45
      Run = Level=Incremental FullPool=CustomerWALPool IncrementalPool=CustomerWALPool on hourly
    • Сгенерированных schedule на все случаи жизни (в разные дни недели каждые 2 часа) у нас получилось примерно 1665… из-за чего Bacula/Bareos периодически сходили с ума.
  • У bacula-fd (и bareos-fd) на каталогах с большим количеством данных (скажем, 40 ТБ, из которых на 35 ТБ приходятся крупные файлы [100+ Мб], а на оставшиеся 5 Тб — мелкие [от 1 Кб до 100 Мб]) начинается медленная утечка памяти, что на production ну совсем неприятная ситуация.

  • На бэкапах с большим количеством файлов Bacula и Bareos очень сильно зависят от производительности используемой СУБД. На каких она дисках? Насколько мастерски вы умеете её тюнить под эти специфичные нужды? А в базе, между прочим, создаётся одна(!) непартицируемая таблица со списком всех файлов во всех бэкапах и вторая — со списком всех путей во всех бэкапах. Если вы не готовы выделить хотя бы 8 Гб RAM под базу + 40 Гб SSD для вашего бэкап-сервера — сразу готовьтесь к тормозам.
  • Зависимость от БД достойна ещё одного пункта. Bacula/Bareos на каждый файл спрашивают директора, был ли уже такой файл уже. Директор, конечно, лезет в БД, в те самые огромные таблицы… Получается, что резервное копирование можно заблокировать просто тем фактом, что одновременно запустились несколько тяжёлых бэкапов — даже если diff’а там на несколько мегабайт.

Несправедливо будет сказать, что никакие проблемы не решались совсем, но мы дошли до того состояния, когда действительно устали от различных workaround’ов, и хотели надёжного решения «здесь и сейчас».

Сломалось какая-то мелочь раз в неделю? Bacula/Bareos прекрасно работают с небольшим количеством (10-30) однородных job’ов. Однако у нас есть проекты, где количество job’ов исчисляется сотнями, а количество файлов в них — сотнями тысяч. Ничего страшного: отдали задачу дежурному (или другому инженеру) — починили. Всё это привело к тому, что 2 часа в день нужно было заниматься починкой бэкапов во всех проектах, потому что буквально везде что-то по мелочи или серьёзно ломалось. В итоге, 5 минут в неделю на починку бэкапа (не считая нескольких часов настройки до этого) начали приумножаться.

Непременно, он будет максимально бородат и суров, а от его взгляда бэкапы чинятся моментально, пока он спокойно попивает кофе. Тут кто-то может подумать, что бэкапами должен заниматься выделенный для этого специальный инженер. Не все могут позволить себе круглосуточно чинить и следить за бэкапами, а уж тем более — выделенного под эти цели инженера. И эта мысль в чем-то может быть верна… Но всегда есть но. Поэтому перешли к поискам альтернативных решений, которые «просто работают». Мы же просто уверены, что эти 2 часа в день лучше тратить на что-то более продуктивное и полезное.

Borg как новый путь

Поиски других Open Source-вариантов были размазаны во времени, поэтому сложно оценить общие затраты, но в один прекрасный момент (в прошлом году) наше внимание устремилось к «виновнику торжества» — BorgBackup (или просто Borg). Отчасти тому способствовал реальный опыт его использования одним из наших инженеров (на предыдущем месте работы).

4. Borg написан на Python (необходима версия >= 3. Распространяется на условиях свободной лицензии BSD (3-clause). 0), а требовательный к производительности код (сжатие, шифрование и т.п.) реализован на C/Cython. Для инсталляции BorgBackup доступны пакеты для популярных Linux-дистрибутивов и других ОС, а также исходники, устанавливаемые в том числе и через pip, — более подробную информацию об этом можно найти в документации проекта. Поддерживает множество платформ включая Linux, *BSD, macOS, а также на экспериментальном уровне Cygwin и Linux Subsystem of Windows 10.

Вот его основные достоинства: Чем же Borg нас так сильно подкупил?

Переход на Borg начал осуществляться медленно, на небольших проектах. По началу это были простые скрипты в cron, которые каждый день делали своё дело. Всё так продолжалось около полугода. За это время нам приходилось много раз доставать бэкапы… и оказалось, что Borg не пришлось чинить буквально совсем! Почему? Потому что тут работает простой принцип: «Чем проще механизм, тем меньше мест, где он сломается».

Практика: как сделать бэкап с Borg?

Рассмотрим простой пример создания бэкапа:

  1. Скачиваем последний релизный бинарник на сервер бэкапа и машину, которую будем бэкапить, с официального репозитория:

    sudo wget https://github.com/borgbackup/borg/releases/download/1.1.6/borg-linux64 -O /usr/local/bin/borg
    sudo chmod +x /usr/local/bin/borg

    Примечание: Если для теста вы используете локальную машину и как источник и как приёмник, то вся разница будет только в URI, который мы передадим, но мы же помним, что бэкап нужно хранить отдельно, а не на той же машине.

  2. На сервере бэкапов создаём пользователя borg:

    sudo useradd -m borg

    Просто: без групп и со стандартным shell’ом, но обязательно с домашним каталогом.

  3. На клиенте генерируется SSH-ключ:

    ssh-keygen

  4. На сервере пользователю borg добавляем сгенерированный ключ:

    mkdir ~borg/.ssh
    echo 'command="/usr/local/bin/borg serve" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNdaDfqUUf/XmSVWfF7PfjGlbKW00MJ63zal/E/mxm+vJIJRBw7GZofe1PeTpKcEUTiBBEsW9XUmTctnWE6p21gU/JNU0jITLx+vg4IlVP62cac71tkx1VJFMYQN6EulT0alYxagNwEs7s5cBlykeKk/QmteOOclzx684t9d6BhMvFE9w9r+c76aVBIdbEyrkloiYd+vzt79nRkFE4CoxkpvptMgrAgbx563fRmNSPH8H5dEad44/Xb5uARiYhdlIl45QuNSpAdcOadp46ftDeQCGLc4CgjMxessam+9ujYcUCjhFDNOoEa4YxVhXF9Tcv8Ttxolece6y+IQM7fbDR' > ~borg/.ssh/authorized_keys
    chown -R borg:borg ~borg/.ssh

  5. Инициализируем borg repo на сервере с клиента:

    ssh borg@172.17.0.3 hostname # просто для проверки соединения
    borg init -e none borg@172.17.0.3:MyBorgRepo

    Ключ -e служит для выбора метода шифрования репозитория (да, вы можете дополнительно зашифровать каждый репозиторий своим паролем!). В данном случае, т.к. это пример, шифрованием мы не пользуемся. MyBorgRepo — это имя каталога, в котором будет borg repo (создавать его заранее не нужно — Borg всё сделает сам).

  6. Запускаем первый бэкап с помощью Borg:

    borg create --stats --list borg@172.17.0.3:MyBorgRepo::"MyFirstBackup-" /etc /root

    Про ключи:

    • --stats и --list дают нам статистику по бэкапу и попавшим в него файлам;
    • borg@172.17.0.3:MyBorgRepo — тут всё понятно, это наш сервер и каталог. А что дальше за магия?..
    • ::"MyFirstBackup-{now:%Y-%m-%d_%H:%M:%S}" — это имя архива внутри репозитория. Оно произвольно, но мы придерживаемся формата Имя_бэкапа-timestamp (timestamp в формате Python).

Что дальше? Конечно, посмотреть, что же попало в наш бэкап! Список архивов внутри репозитория:

borg@b3e51b9ed2c2:~$ borg list MyBorgRepo/
Warning: Attempting to access a previously unknown unencrypted repository!
Do you want to continue? [yN] y
MyFirstBackup-2018-08-04_16:55:53 Sat, 2018-08-04 16:55:54 [89f7b5bccfb1ed2d72c8b84b1baf477a8220955c72e7fcf0ecc6cd5a9943d78d]

Видим бэкап с timestamp’ом и как Borg спрашивает нас, действительно ли мы хотим обратиться к нешифрованному репозиторию, в котором ещё не разу не были.

Смотрим список файлов:

borg list MyBorgRepo::MyFirstBackup-2018-08-04_16:55:53

Достаём файл из бэкапа (можно и весь каталог):

borg@b3e51b9ed2c2:~$ borg extract MyBorgRepo::MyFirstBackup-2018-08-04_16:55:53 etc/hostname
borg@b3e51b9ed2c2:~$ ll etc/hostname -rw-r--r-- 1 borg borg 13 Aug 4 16:27 etc/hostname

Поздравляю, ваш первый бэкап с Borg готов!

Практика: автоматизируй это [с GitLab]!

Завернув всё это в скрипты, мы настроили бэкапы вручную подобным образом примерно на 40 хостах. Поняв, что Borg действительно работает, начали переводить на него больше и более крупные проекты…

А именно: WebUI или какого-то централизованного места для настройки бэкапов. И тут мы столкнулись с тем, что есть в Bareos, но нет у Borg! Погуглив готовые инструменты и собравшись в видеоконференции, мы взялись за дело. И мы очень надеемся, что это временное явление, но пока нам надо было что-то решить. Подумали, как можно сделать, обрисовали план, как и куда это можно встроить, но… Нормальные бэкапы нужны сейчас, а на грандиозные планы времени взять неоткуда. Была замечательная идея интеграции Borg с нашими внутренними сервисами, как мы делали раньше с Bacula (сама Bacula забирала список job’ов из нашего централизованного API, к которому мы имели свой интерфейс, интегрированный с другими настройками проектов). Что делать?

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

  • Что использовать как централизованное управление бэкапами?
  • Что умеет любой Linux-администратор?
  • Что сможет понять и настроить даже менеджер, показывающий график бэкапов клиентам?
  • Что каждый день выполняет по расписанию задания на вашей системе?
  • Что не будет трудным в настройке и не будет ломаться?..

Ответ был очевиден: это старый добрый crond, который героически выполняет свой долг каждый день. Простой. Не зависает. Сможет поправить даже менеджер, который с Unix на «вы».

Неужели каждый раз ходить на машину проекта и править файл руками? Итак, crontab, но где же всё это держать? Мы можем положить наше расписание в Git-репозиторий и настроить GitLab Runner, который по коммиту будет обновлять его на хосте. Конечно, нет.

Но должен заметить, что он ни в коем случае не является необходимостью. Примечание: Именно GitLab был выбран в качестве средства автоматизации, потому что он удобен для поставленной задачи и в нашем случае есть практически везде.

Раскладывать crontab для бэкапов вы можете привычным для себя средством автоматизации или вообще вручную (на маленьких проектах или домашних инсталляциях).

Итак, вот что понадобится для простой автоматизации:

GitLab и репозиторий, в котором для начала будет два файла: 1.

  • schedule — расписание бэкапов,
  • borg_backup_files.sh — простой скрипт бэкапа файлов (как в примере выше).

Пример schedule:

# WARNING! CRONTAB MANAGED FROM GITLAB CI RUNNER IN ${CI_PROJECT_URL}
# CI_COMMIT_SHA: ${CI_COMMIT_SHA}
# Branch/tag: ${CI_COMMIT_REF_NAME}
# Timestamp: ${TIMESTAMP}
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # MyRemoteHost
0 0 * * * ${CI_PROJECT_DIR}/borg_backup_files.sh 'SYSTEM /etc,/opt'

Переменные CI используются для того, чтобы проверить успешность обновления crontab’а, а CI_PROJECT_DIR — каталог, в котором окажется репозиторий после клонирования runner’ом. Последняя строка указывает на то, что бэкап выполняется каждый день в полночь.

Пример borg_backup_files.sh:

#!/bin/bash
BORG_SERVER="borg@10.100.1.1"
NAMEOFBACKUP=${1}
DIRS=${2}
REPOSITORY="${BORG_SERVER}:$(hostname)-${NAMEOFBACKUP}" borg create --list -v --stats \ $REPOSITORY::"files-{now:%Y-%m-%d_%H:%M:%S}" \ $(echo $DIRS | tr ',' ' ') || \ echo "borg create failed"

Первым аргументом здесь передаётся имя бэкапа, а вторым — список директорий для бэкапа, через запятую. Строго говоря, списком может являться и набор отдельных файлов.

GitLab Runner, запущенный на машине, которую необходимо бэкапить, и заблокированный только на выполнение job’ов этого репозитория. 2.

Сам CI-сценарий, реализуемый файлом .gitlab-ci.yml: 3.

stages: - deploy
Deploy: stage: deploy script: - export TIMESTAMP=$(date '+%Y.%m.%d %H:%M:%S') - cat schedule | envsubst | crontab - tags: - borg-backup

4. SSH-ключ у пользователя gitlab-runner c доступом к серверу бэкапов (в примере это 10.100.1.1). По умолчанию он должен лежать в .ssh/id_rsa домашнего каталога пользователя (gitlab-runner).

Пользователь borg на том же 10. 5. 1. 100. 1 с доступом только к команде borg serve:

$ cat .ssh/authorized_keys
command="/usr/bin/borg serve" ssh-rsa AAAAB3NzaC1yc2EAA...

Теперь при коммите в репозиторий Runner заполнит содержимое crontab’а. А при наступлении времени срабатывания cron’а выполнится бэкап каталогов /etc и /opt, который окажется на сервере бэкапов в каталоге MyHostname-SYSTEM сервера 10.100.1.1.

Вместо заключения: что можно ещё?

Применение Borg на этом, конечно, не заканчивается. Вот несколько идей для дальнейшей реализации, часть которых мы у себя уже реализовали:

  • Добавить универсальные скрипты для разных бэкапов, которые по окончанию выполнения запускают borg_backup_files.sh, направленный на каталог с результатом своей работы. Например, так можно бэкапить PostgreSQL (pg_basebackup), MySQL (innobackupex), GitLab (встроенный rake job, создающий архив).
  • Центральный хост со schedule для бэкапа. Не настраивать же на каждом хосте GitLab Runner? Пусть он будет один на сервере бэкапов, а crontab при запуске передаёт скрипт бэкапа на машину и запускает его там. Для этого, конечно, понадобится пользователь borg на машине клиенте и ssh-agent, чтобы не раскладывать ключ к серверу бэкапов на каждой машине.
  • Мониторинг. Куда же без него! Алерты о некорректно завершённом бэкапе обязательно должны быть.
  • Очистка borg repository от старых архивов. Несмотря на хорошую дедупликацию, старые бэкапы всё равно приходится чистить. Для этого можно сделать вызов borg prune по окончанию работы скрипта бэкапа.
  • Веб-интерфейс к расписанию. Пригодится, если правка crontab руками или в web-интерфейсе для вас выглядит не солидно/неудобно.
  • Pie charts. Немного графиков для наглядного представления процента успешно выполненных бэкапов, времени их выполнения, ширины «съеденного» канала. Не зря я уже писал, что не хватает WebUI, как в Bareos…
  • Простые действия, которые хотелось бы получать по кнопке: запуск бэкапа по требованию, восстановление на машину и т.п.

И в самом конце хотелось бы добавить пример эффективности дедупликации на реальном рабочем бэкапе WAL-файлов PostgreSQL в production-среде:

borg@backup ~ $ borg info PROJECT-PG-WAL
Repository ID: 177eeb28056a60487bdfce96cfb33af1c186cb2a337226bc3d5380a78a6aeeb6
Location: /mnt/borg/PROJECT-PG-WAL
Encrypted: No
Cache: /mnt/borg/.cache/borg/177eeb28056a60487bdfce96cfb33af1c186cb2a337226bc3d5380a78a6aeeb6
Security dir: /mnt/borg/.config/borg/security/177eeb28056a60487bdfce96cfb33af1c186cb2a337226bc3d5380a78a6aeeb6
------------------------------------------------------------------------------ Original size Compressed size Deduplicated size
All archives: 6.68 TB 6.70 TB 19.74 GB Unique chunks Total chunks
Chunk index: 11708 3230099

Это 65 дней бэкапа WAL-файлов, которые делались каждый час. При использовании Bacula/Bareos, т.е. без дедупликации, мы получили бы 6,7 Тб данных. Только подумайте: можем позволить себе хранить почти 7 терабайт данных, прошедших через PostgreSQL, всего в 20 Гб фактически занимаемого места.

P.S.

Читайте также в нашем блоге:


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Триумф и трагедия «Бурана»

В полностью автоматическом режиме он совершил 2 витка вокруг Земли и успешно приземлился спустя 205 минут. Ровно 30 лет назад с космодрома Байконур на ракете-носителе «Энергия» в свой единственный полёт отправился корабль «Буран». Это стало несомненным триумфом советской космонавтики, впервые ...

[Из песочницы] Несертифицированный GPS-трекер из Китая. Законно ли в России?

Иностранные интернет-магазины завалены разнообразными устройствами, оснащёнными GPS, GSM-модулями, позволяющими отслеживать местоположение наблюдаемого объекта и управлять устройством посредством SMS и мобильных приложений. И, конечно же, большинство из них не сертифицированы и запрещены для ввоза/использования в России. Простой обыватель, услышав слова «несертифицированный» ...