Передача снапшота ZFS по сети
18.11.2011
Пришлось наконец столкнуться на практике с передачей сравнительного большого
снимка ZFS по сети. В учебных материалах и официальной документации сказано, что
для передачи по сети следует использовать команды send\recv в сочетании с ssh
через пайп. На практике же это решение оказывается абсолютно не работоспособным
для больших объемов. Лично у меня скорость передачи уперлась примерно в 8 MB/sec
по гигабитной сети, что привело к тому что за 12 часов скопировалось лишь 300
гигабайт данных.
Что же делать?
Во-первых, требуется
собрать на обеих машинах программу mbuffer. Отличная альтернатива
ssh для передачи данных в защищенной сети.
Делаем снапшот:
# zfs snapshot
tank/tones@$(date +%y%m%d%H%M)
Запускаем на приемнике ожидание потока
данных
# /usr/local/bin/mbuffer -s 128k -m 1G -I 9090 | zfs receive
zshare/test
Запускаем передачу снимка на передатчике
# zfs send
tank/tones@1105101812 | /usr/local/bin/mbuffer -s 128k -m 1G -O
10.99.88.55:9090
Подробное описание ключей прочитаете в манах к mbuffer — там
все понятно. Наблюдаем около сотни метров в секунду, радуемся.
Если же вы все
же решили передать снимок по ssh (малый объем\незащищенная сеть), то делать надо
это следующим образом.
Делаем снимок как сказано выше. На приемнике даем
следующие разрешения пользователю, под которым происходит соединение
# zfs
allow user create,mount,receive zshare
Запускаем передачу на источнике
#
zfs send tank/tones@1105101812 | ssh -C -b 10.0.64.50 user@10.99.88.55
/usr/sbin/zfs recv zshare/tones
Вторая задача: поддерживать 2 датасета на разный хостах в состоянии максимально
возможной идентичности. Используем возможность передачи
инкримента двух снапшотов.
Вначале был передан полный снапшот объемом около террабайта с помощью mbuffer, как это было описано в выше. Также предоставлены соответствующие права пользователю и
прописаны rsa-ключи. Процесс занял примерно 4 часа по гигабитному
каналу.
Дальше в планировщик добавляем вот такой скрипт:
#!/usr/bin/bash
#=== Options ==============
zfs_pool=zshare
zfs_dataset=dataset
lockfile=
"/var/run/zfs_operation.lock"
zsnapname=auto_$(
date
+%y%m%d%H%M)
mail_recipients=
"admin@tele2.com"
RHOST=192.168.0.1
RUSER=snapuser
#==========================
function
check_result {
last_comm_res=$?
if
[[
"${last_comm_res}"
-
ne
0 ]]
then
echo
"Script: an error occurred"
cat
/var/log/tones_backup
.log|mailx -s
"${HOSTNAME}:Pool backup error"
${mail_recipients}
exit
${last_comm_res}
fi
}
if
[ -f ${lockfile} ]
then
echo
"Previous runjob does not complitted successfully"
exit
1
fi
touch
${lockfile}
if
[[ ! -z $(
ps
-ef|
grep
zfs|
grep
send|
grep
${zfs_pool}) ]]
then
echo
"Sending data from pool ${zfs_pool} detected! Try again later!"
exit
1
fi
rlast_snapshot=$(
ssh
${RUSER}@${RHOST}
"/usr/sbin/zfs list -o name -r ${zfs_pool}/${zfs_dataset}|tail -1"
|
awk
-F@
'{print $2}'
)
zfs list -o name ${zfs_pool}/${zfs_dataset}@${rlast_snapshot} ; check_result
zfs snapshot ${zfs_pool}/${zfs_dataset}@${zsnapname} ; check_result
zfs send -i ${zfs_pool}/${zfs_dataset}@${rlast_snapshot} ${zfs_pool}/${zfs_dataset}@${zsnapname} |
ssh
${RUSER}@${RHOST}
"/usr/sbin/zfs recv -F ${zfs_pool}/${zfs_dataset}"
check_result
rm
${lockfile}
Частоту вызова данного скрипта следует выбирать исходя из следующих факторов:
- Скорость роста снапшотов
- Ширина канала между хостами
- Нагрузка на активном пуле
Ориентировочно: двухгигобайтный инкримент
у меня передался примерно за 12 минут по гигабитному каналу. Причем узким местом
была не сеть. Скорее всего это была реализация инкриментации в самом zfs,
глубоко не копал.
Так же на приемнике следует подчищять старые снапшоты,
чтобы их число не росло бесконечно, что быстро приведет к исчерпанию свободных
блоков. Но при этом требуется оставлять как минимум последний снимок, чтобы
иметь возможность накатить следующий инкримент.
#!/usr/bin/bash
#=== Options ==============
zfs_pool=zshare
zfs_dataset=dataset
#=========================
nsnap=$(zfs list -o name -r ${zfs_pool}/${zfs_dataset}|
egrep
"@auto_1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"
|
wc
-l)
if
[[ ${nsnap} -gt 3 ]]
then
let
"nsnap_destroy = $nsnap - 2"
snap_destroy_list=$(zfs list -o name -r ${zfs_pool}/${zfs_dataset}|
egrep
"@auto_[0-9]10"
|
head
-n ${nsnap_destroy})
for
dsnap
in
${snap_destroy_list}
do
zfs destroy ${dsnap}
done
fi
20.11.2011 в 08:21
Вместо mbuffer можно использовать ttcp(1) из поставки.
22.11.2011 в 13:42
bash-3.2# /usr/dt/bin/ttcp -h
Usage: ttcp [-pL] file1 file2
ttcp [-prRL] path1 [path2 …] dir
ttcp -v
ttcp -h
-L do not perform a cp(1)
-v print the version number and quit
-h print this message
Это максимм что смог по ней найти. Как ей пользоваться?
22.11.2011 в 16:39
Утилита ttcp в Solaris относится к ToolTalk
# ttcp -v
ttcp version: 1.3
ToolTalk library version: 1.3
В остальных ОС обычно утилита ttcp (test tcp) служит для тестирования скорости канала передачи данных..
Как можно использовать ее вместо mbuffer не понятно.
29.12.2011 в 03:20
Lanfile+openvpn ?
29.12.2011 в 08:52
И, кстати сказать, у SSHD есть вариант с high performance патчем. Я бы не советовал передавать снапшоты без криптования, поскольку стримы ZFS легко читаются.
Что касается скорости, то gzip -9 для снапшота спасет гиганта мысли. Дисковый формат ZFS имеет выраженную регулярную структуру и весьма хорошо компрессируется.
29.12.2011 в 09:32
а покажите как вы через ssh делали что такие скорости плохие.
ну и, ради интереса, в какие ресурсы уперлись?
29.12.2011 в 10:35
Юрий,
Ставить левые патчи на sshd в продуктовой среде? неее…
Снапшот я передаю внутри доверенной сети, я это оговорил. Так что странный совет.
gzip тут совсем не к месту- читайте внимательно, утилизация канала была минимальна. Вообще про архиваторы это тема для отдельной статьи- ikorolev в курсе ^_^
tiger,
Примерно так, как сказано в документации:
zfs send tank/tones@1105101812 | ssh -C -b 44.33.22.11 bercut@11.22.33.44 /usr/sbin/zfs recv zshare/tones
пробывал с компрессией и без. Уперся не в сеть точно, похоже скорее на реализацию ssh.
Qwerty,
Это вообще к чему?