Пришлось наконец столкнуться на практике с передачей сравнительного большого
снимка 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

 

 

 

7 комментариев на запись “Передача снапшота ZFS по сети”

  1. frol пишет:

    Вместо mbuffer можно использовать ttcp(1) из поставки.

  2. AnViar пишет:

    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
    Это максимм что смог по ней найти. Как ей пользоваться?

  3. ikorolev пишет:

    Утилита ttcp в Solaris относится к ToolTalk
    # ttcp -v
    ttcp version: 1.3
    ToolTalk library version: 1.3

    В остальных ОС обычно утилита ttcp (test tcp) служит для тестирования скорости канала передачи данных..
    Как можно использовать ее вместо mbuffer не понятно.

  4. Qwerty пишет:

    Lanfile+openvpn ?

  5. Юрий пишет:

    И, кстати сказать, у SSHD есть вариант с high performance патчем. Я бы не советовал передавать снапшоты без криптования, поскольку стримы ZFS легко читаются.

    Что касается скорости, то gzip -9 для снапшота спасет гиганта мысли. Дисковый формат ZFS имеет выраженную регулярную структуру и весьма хорошо компрессируется.

  6. tiger пишет:

    а покажите как вы через ssh делали что такие скорости плохие.
    ну и, ради интереса, в какие ресурсы уперлись?

  7. AnViar пишет:

    Юрий,
    Ставить левые патчи на 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,
    Это вообще к чему?