Организация backup-сервера. Linux, ZFS и rsync

TL;DR:
Статья о настройке бекапа линуксовых серверов. В качестве хранилища используется раздел ZFS с включенными дедубликацией и компрессией. Ежедневно делаются снапшоты, которые сохраняются в течение недели (7 штук). Ежемесячные снапшоты хранятся в течение года (еще 12 штук). В качестве транспорта выступает rsync: на сервере он запущен демоном, на клиентах он запускается из crontab.

Так получилось, что у меня есть пара серверов, на которых под KVM живут виртуальные машины. Хотелось бекапить образы этих машин в сеть, но так, чтобы выполнялись условия:

  • Хранить все бекапы за последнюю неделю.
  • Хранить в течении года ежемесячные бекапы.
  • Никаких сторонних бекап-агентов. На клиентах только стандартное и проверенное поколениями админов ПО.
  • Экономно расходовать место в хранилище. Желательна компрессия и дедубликация данных.
  • Все файлы должны быть доступны без дополнительных инструментов и оболочек. Идеальный вариант: каждый бекап в отдельном каталоге.


Можно ли всё это совместить? Да, и очень просто.

Все компьютеры, о которых идет речь в этой статье, являются серверами. Но как-то глупо и длинно делить их на “сервер, который хранит бекапы” и “сервер, бекапы которого хранит сервер, который хранит бекапы”. Поэтому первый я буду называть просто сервером, а второй уже начал называть клиентом.

1. ZFS с компрессией и дедубликацией


Наиболее привычная для меня ОС – Linux. Всё то же самое без особых изменений должно подойти и к Solaris, и к FreeBSD, в которых ZFS есть давно и что называется “из коробки”. Но Linux мне ближе и роднее, а проект по портированию на него ZFS выглядит уже достаточно зрелым. За год экспериментов у меня не было с ним заметных проблем. Поэтому поставил на сервер Debian Wheezy, подключил официальный репозитарий проекта и установил нужные пакеты.

Создал пул, указав что zfs у меня будет на /dev/md1 и что монтировать эту файловую систему я хочу к каталогу /mnt/backup:

# zpool create backup -m /mnt/backup /dev/md1


По имени устройства /dev/md1 можно заметить, что я использую линуксовый software raid. Да, я знаю, что у ZFS есть свой способ создавать зеркала. Но поскольку на этой машине уже есть одно зеркало (для корневого раздела) и оно сделано штатным mdadm, то и для второго зеркала я предпочту использовать его же.

Включил дедубликацию и компрессию, сделал видимым каталог со снапшотами:

# zfs set dedup=on backup
# zfs set compression=on backup
# zfs set snapdir=visible backup


Положил в /usr/local/bin скрипт для создания снапшотов:

#!/bin/bash

export LANG=C
ZPOOL='backup'

# Храним все снапшоты 7 дней
# снапшот на четвертое число каждого месяца храним год

NOWDATE=`date +20%g-%m-%d` # дата формата ГГГГ-ММ-ДД
OLDDAY=`date -d -7days +%e`

if [ $OLDDAY -eq '4' ]
then
  OLDDATE=`date  -d -1year-7days +20%g-%m-%d` # получаем дату -1 год и на7 дней
else
  OLDDATE=`date  -d -7days +20%g-%m-%d` # получаем дату -7 дней
fi

/sbin/zfs snapshot $ZPOOL@$NOWDATE
/sbin/zfs destroy $ZPOOL@$OLDDATE 2>/dev/null


Этот скрипт добавил в crontab для ежедневного запуска. Чтобы содержимое снапшота соответствовало его дате, скрипт лучше запускать ближе к концу суток. Например, в 23:55.

Четвертое число месяца выбрано почти случайно. Запускал я всё этого третьего августа и хотелось поскорее сделать бекап, который будет храниться год. Следующий день был четвертым.

Снапшоты будут сохраняться в каталоге /mnt/backup/.zfs/snapshot. Каждый снапшот – отдельный каталог с именем в виде даты на момент создания этого снапшота. Внутри снапшота полная копия каталога /mnt/backup в том виде, в котором он был в этот момент.

2. Rsync на сервере


Традиционно rsync настраивают для работы поверх ssh. На клиентах настраивается авторизация по ключам (и без пароля), а эти ключи складываются на бекап-сервер. Сервер ходит по ssh на клиентов и забирает с них файлы. Преимущество этого подхода – шифрование трафика. Но мне не нравится идея с беспарольным входом по ssh (особенно в свете последних уязвимостей в bash). Так же мне не нравится идея инициировать бекап со стороны сервера: иногда перед бекапом на клиенте хочется выполнить какой-нибудь скрипт (например, сбросить дамп mysql), и только после завершения этого скрипта начинать бекап. Поэтому мой выбор – rsync, запущенный демоном на сервере и запускаемый из crontab на клиентах.

Поставил на сервер rsync (штатный, из репозитария), и чтобы он запускался при старте системы, написал в /etc/default/rsync:

RSYNC_ENABLE=true


Создал на сервере /etc/rsyncd.conf такого содержания:

uid = nobody
gid = nogroup
use chroot = yes
max connections = 10
pid file = /var/run/rsyncd.pid

[kvm01]
path = /mnt/backup/kvm01
comment = KVM01 backups
hosts allow = 192.168.xxx.xxx
hosts deny = *
read only = no

[kvm02]
path = /mnt/backup/kvm02
comment = KVM02 backups
hosts allow = 192.168.xxx.yyy
hosts deny = *
read only = no


192.168.xxx.xxx и 192.168.xxx.yyy – это адреса тех серверов, которые будут бекапиться. Зовут их kvm01 и kvm02. Их файлы будут лежать в /mnt/backup/kvm01 и /mnt/backup/kvm02. Поэтому:

# mkdir /mnt/backup/kvm01
# mkdir /mnt/backup/kvm02
# chown nobody:nogroup /mnt/backup/kvm01
# chown nobody:nogroup /mnt/backup/kvm02


Запустил rsync:

# /etc/init.d/rsync start


3. Rsync на клиентах


Минимально необходимый скрипт для копирования файлов с клиента kvm02 на сервер с адресом 192.168.xxx.zzz будет выглядеть примерно так:

#!/bin/bash

RSYNCBACKUPDIR="rsync://192.168.xxx.zzz/kvm02"
LOCALDIR="/virt/files"
rsync -vrlptD --delete $LOCALDIR $RSYNCBACKUPDIR


Разумется, если речь идет о бекапе виртуальных машин, то этот скрипт стоит пополнить командами создания и удаления LVM-снапшота, монтирования и отмонтирования его содержимого и так далее. Но эта тема уже выходит за рамки данной статьи.

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


Для восстановления файлов из бекапа клиента KVM01 за 4 августа 2014 года достаточно будет на сервере перейти в каталог /mnt/backup/.zfs/snapshot/2014-08-04/kvm01/ и скопировать оттуда файлы любым привычным способом. Каждый конкретный бекап выглядит как обычный каталог, доступный только для чтения. Для поиска определенного файла в этом бекапе можно использовать стандартные утилиты, такие как find или grep.

5. Заключение


Сейчас на сервере 9 снапшотов: 7 ежедневных и 2 ежемесячных. Плюс сегодняшний бекап, снапшот с которого снимется вечером. Размер раздела с бекапами составляет 1.8T. Общий объем файлов — 3.06T. Физически занимают на диске они 318G. Суммарный объем сегодняшнего бекапа — 319G. Да, 10 бекапов на ZFS с компрессией и дедубликацией занимают места меньше, чем один бекап занимал бы на файловой системе без этих полезных свойств.

# zpool list
NAME     SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
backup  1.80T   310G  1.49T    16%  10.37x  ONLINE  -


# zfs list
NAME      USED  AVAIL  REFER  MOUNTPOINT
backup   3.06T  1.42T   318G  /mnt/backup


Поскольку сам rsync не занимается шифрованием передаваемых данных, высовывать такую схему без изменений в интернет небезопасно. Добавить шифрование можно, пустив трафик через ipsec или stunnel, например.

Выше я написал, что заметных проблем с ZFS у меня не было. На самом деле, одна проблема была. Однажды ночью, когда оба клиента активно бекапились, сервер дважды сообщил в dmesg, что task rsync blocked for more than 120 seconds. При этом оба бекапа успешно завершились, ничего не зависло, данные не потерялись. Подозреваю, что это проявление знаменитого бага 12309. Разнес бекапы по времени, с тех пор проблема не повторялась.
Поделиться публикацией
Комментарии 20
    +12
    We need more CRB (cron-rsync-bash) backup scripts!
      +2
      > На клиентах только стандартное и проверенное поколениями админов ПО.
      Почему не та же Bacula, к примеру?
      Конечно, есть у неё непрятные недостатки, но много и плюшек — дифферинциальные / инкрементальные бекапы по хэшу, гибкое расписание, SD-SD репликации, шифрование искоробки, более-менее вменяемые контейнеры, и т.д.
        +2
        Bacula отлично подходит, если не хотеть, чтобы файлы были «доступны без дополнительных инструментов и оболочек». Мне такого хотелось. Теперь в качестве софта для восстановления данных из бекапов можно использовать привычные grep, find или даже mc.

        Благодаря ZFS появился еще один инструмент, способный стать альтернативой традиционным системам резервного копирования. Разумеется, подойдет он не всем. Как минимум, описанный в статье способ не годится в случаях, когда критичен объем передаваемого при бекапе трафика.
        +3
        ZFS на mdraid… зачем?

        И кстати zfs set compression=lz4 backup или gzip-9.
          –2
          Процитирую себя же: «поскольку на этой машине уже есть одно зеркало (для корневого раздела) и оно сделано штатным mdadm, то и для второго зеркала я предпочту использовать его же». Просто для единообразия.

          Про lz4 почитал. Пишут, что он значительно лучше, чем используемый по умолчанию LZJB. Обязательно попробую.
          0
          В качестве бесплатной альтернативы относительно дорогим «энтерпрайз» продуктам для бэкапа вполне интерестное решение. Смущает только одно. Помимо процессов бэкапа и хранения резервных копий, есть еще процессы восстановления из этих бэкапов в случае сбоев. И тут скорость восстановления в пределах даже небольших организаций бывает критична. Простаивать сутки и более бизнес обычно не любит. Ну и кроме того сами сценарии восстановления продумывать и отрабатывать (тестировать) лучше заранее. Что бы понимать «куда бежать? и что делать?» в случае необходимости, а кроме того понимать сколько потребуется времени.
            0
            Спасибо за намёк. Вопрос восстановления из бекапа я совсем не рассмотрел. Добавил в статью отдельный пункт об этом.
              0
              Всегда пожалуйста.
              К сожалению, исходя из «отдельного пункта», как раз «узкие» IP каналы могут стать проблемой при необходимости восстанавливать большие объемы. Но это проблема не только конкретно вашего решения, но и многих коммерческих реализаций бэкапов.
            0
            а зачем эти всякие zfs и пр.?
            чем не работает

            basepath=/path/to/backup
            today=`date +%Y%m%d`
            yesterday=`date --date=«yesterday» +%Y%m%d`
            monthago=`date --date=«30 day ago» +%Y%m%d`

            todaydir=$basepath/$today
            yesterdaydir=$basepath/$yesterday
            monthagodir=$basepath/$monthago

            mkdir -p $todaydir

            cp -al $yesterdaydir $todaydir

            rsync -a --delete /path/to/files/ $todaydir

            rm -rf $monthagodir

            а ещё вот это вот место /path/to/backup можно подключить через vfs_shadow2 к ресурсу самбы и народ будет видеть в проводнике винды прошлые версии файла. И ничего не надо там разворачивать для того чтобы что-то найти. И ZFS тут нигде не нужен.
              +2
              Предположим вам надо бэкапить огромную кучу почти идентичных виртуалок, в вашем случае будет огромный оверхед по занимаемому месту, т.к. никакого намека на дедубликацию в этом скрипте нет, во вторых нет инкрементальных и дифф бэкапов, если вам надо бэкапить полтора хоста, то решение годное, если счет давно перевалил за сотню, то приходится искать альтернативы, чтоб не добавлять новую дисковую полку на каждый лишний день бэкапов.
                0
                А вы маны то читали по cp и rsync? cp -al создает жесткие ссылки на существующие файлы, сами файлы не копирует. директории создает новые, да, но это мизер. rsync в новую директорию копирует только модифицированные файлы. --delete удаляет жесткие ссылки если файлы были удалены. Где оверхед?
                  0
                  Покажу на примере:
                  Один из образов виртуальных машин занимает 74G. За день он меняется незначительно (предполагаю, что не более чем на 1G). Но меняется. Семь ежедневных копий этого файла займут 518G. А на хранилище с дедубликацией — всего 80G.
                    0
                    Data deduplication требует конских объемов ОЗУ для своей работы. Это не на любом сервере уместно.
                      0
                      О это да 640 гигабайт, хватит каждому. Но часто оно того стоит, понятно что решение не для всех задач, эх вот бы найти такое чтоб для всех подходило, но я вот еще держу фряхи только из-за ZFS, не знаю как ща на линуксе, но пару лет назад было ужасно.
                    0
                    Для виртуалок это не работает, я потому и заострил внимание на виртуалках, ваше решение из мира одиночных серверов, там где облака и кластеры гипервизоров оно не применимо. Маны читал, не считайте заранее незнакомых вам людей идиотами даже не вникнув в суть, а вот вы маны по дедубликации в общем и работе системы ZFS в частности читали?
                      0
                      ок ок. Да, для вашего случая это правильное решение.
                  0
                  В ZFS тоже ничего не надо разворачивать, зашел в /.zfs/snapshots и все тут как тут.
                  Надо примонтировать? Клонируем и монтируем.
                  0
                  Это не Вы рассказывали на одном из SPbLUG-ов о своем опыте использования ZFS под Linux где-то год-полтора назад? Кажется тогда речь шла о том, что был убит целый год, опробовано куча вариантов, но ни один так и не оказался годным для промышленного применения? Неужели он теперь нормально работает под Linux? И вообще — зачем он там нужен когда есть нативный btrfs? Хотете ZFS — используйте те ОС, где он работает нативно.
                    0
                    Нет, не я рассказывал.
                    Для моей задачи ZFS оказалась вполне годной. Даже на Linux.
                      0
                      Если в кратце, то человек там перепробовал все возможные способы использования ZFS под Linux. Пробовал даже такие шутки, как openindiana. Но были проблемы, в т.ч. серьезные.

                      А вообще при использовании ZFS нужно иметь в виду следующее:
                      Data deduplication требует примерно 5Gb RAM на каждый Тб данных. Память должна обязательно быть с ЕСС. ZFS должен иметь полный доступ к диску, т.е. диски должны быть подключены через HBA (это важно!), а не через RAID контроллер. Крайне желательно наличие UPS т.к. при потери питания весь пул может разрушится. Данные при этом восстановить будет невозможно. Так же надо понимать, что в случае kernel panic или подобной ситуации вы так же можете потерять все данные на ZFS. По этому разумно будет кроме ZFS не гонять ни каких служб на машине.

                      Самый простой способ получить все плюшки ZFS — это поставить FreeNAS или его аналог. Его настройка не сложнее настройки обыкновенного SOHO роутера вроде dlink. У меня под наблюдением есть сервак на FreeNAS где установлены 8 дисков по 4Тб, 32Гб ОЗУ, 4 сетевухи и Xeon не помню какой. Все это хозяйство работает файлсервером в обычном понимании этого слова, а так же хранит днные от кластера виртуализации. Отлично работает уже более полугода в такой связке.

                      Так же настоятельно рекомендую ознакомится вот с этой презентацией forums.freenas.org/index.php?threads/slideshow-explaining-vdev-zpool-zil-and-l2arc-for-noobs.7775/
                      Там подробно разъясняют терминологию ZFS, как надо строить пулы и как не надо и почему.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое