WWW.LUSHNIKOV.NET

linux

Организация 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 будет выглядеть примерно так:

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

Разумется, если речь идет о бекапе виртуальных машин, то этот скрипт стоит пополнить командами создания и удаления LVM-снапшота, монтирования и отмонтирования его содержимого и так далее. Обязательно дописать к rsync опцию “–inplace”, которая заставит его переписывать в файле только изменившиеся блоки (что позволит избежать повторной дедубликации неизменившихся блоков). Но эта тема уже выходит за рамки данной статьи.

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

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

P.P.S. Выше я написал, что заметных проблем с ZFS у меня не было. На самом деле, одна проблема была. Однажды ночью, когда оба клиента активно бекапились, сервер дважды сообщил в dmesg, что task rsync blocked for more than 120 seconds. При этом оба бекапа успешно завершились, ничего не зависло, данные не потерялись. Подозреваю, что это проявление знаменитого бага 12309. Разнес бекапы по времени, с тех пор проблема не повторялась.

P.P.P.S. Чтобы увидеть в выводе zfs list, сколько занимает каждый конкретный снапшот, можно сделать так:

zpool set listsnapshots=on backup
Tags:

Leave a Reply