Глава 4. Репликация

Содержание

4. Репликация
Но у меня есть Rsync!
Зачем нужны репликации?
Основы репликаций
Локальная репликация
Просмотр копий
Удалённая репликация
Пользователи и наборы данных репликации
Полная удалённая репликация набора данных
Инкрементальная репликация
Допущения инкрементальной репликации
Дифференциальная репликация
Ограничения пропускной способности SSH
Сложности инкрементальных репликаций
Рекурсивные репликации
Дополнительные параметры отсылки
Отсылка свойств
Дедуплицированный поток данных
Отладка и тестирование
Большие и маленькие блоки
Дополнительные параметры приёма
Управление путём и монтированием
Изменение отката
Отладка и тестирование
Клонирование по предписанию
Закладки
Возобновляемая отсылка
Автоматизация репликаций
Применение zxfer
Режим извлечения zxfer
Циклическая замена снимков
Сохранение старых снимков
Свойства и аварийное восстановление
Дополнительные параметры zxfer

Итак, что жет такое в точности [/ˌrepləˈkāSH(ə)n/]? В ZFS это означает точную копию вашей файловой системы, где- либо ещё. Это другое место может быть другим набором данных в вашем пуле, вторым пулом в вашей системе, внешним диском, удалённой системой, лентой или просто файлом. Вы можете просто определить "Я хочу эту файловую систему в этом месте," и создание выполнится. Репликация ZFS имеет некоторые свойства архитектуры, которые делают её особенно мощной.

Программы подобные dump(8) и rsync(1) рассчитывают получить неким образом уведомление подтверждения получения данных. Процесс репликации ZFS является однонаправленным - отправитель не нуждается в обратной связи с принимающей стороной. Поскольку репликация не ожидает никакого подтверждения, получателю ZFS не требуется никакая интеллектуальность; он должен только принять поток байт и сделать с ним что-то.

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

Функциональность репликации ZFS разработана для полного использования ваших дисков. Единственное ограничение того, как быстро вы можете реплицировать данные между машинами состоит в скорости соединения вашей сетевой среды.

Репликация ZFS состоит из двух частей: zfs send, которая преобразует в последовательную форму снимок или последовательность снимков в единый поток данных, а также zfs receive, который возвращает этот поток назад в файловую систему ZFS.

 Но у меня есть Rsync!

В течение десятилетий rsync(1) был стандартным инструментом для синхронизации между машинами. Чтобы синхронизировать файлы, rsync обходит ваше дерево каталога, вычисляя временные штампы и криптографические контрольные суммы каждого файла и сравнивает их с соответствующими файлами на удалённой стороне. Многие организации разработали громадные инфраструктуры на основе rsync.

ZFS разработана для максимизации производительности диска. Она побивает rsync настолько сильно, что маме rsync требуется срочная медицинская помощь. ZFS поддерживает список блоков диска которые отличаются между каждым последующим снимком. Процесс репликациине требует определять какие файлы были изменены - наша файловая система уже имеет эту информацию. Процесс репликации начинает отправку этих блоков настолько быстро, насколько это возможно, немедленно. Так как изменённые блоки содержат все метаданые для пересборки данных файлов, процесс репликации даже не нуждается в знании того, какие файлы соотносятся с этими блоками.

Пока rsync обходит вашу файловую систему, просматривая каждый файл, проверяя его временной штамп, вычисляя контрольную сумму и сравнивая их с версиями на вашей другой стороне, ZFS уже завершит свою работу. Если у вас имеется 10ТБ данных, причём только 1ГБ изменён, rsync всё- таки вынужден проверять каждый файл. ZFS только захватывает 1ГБ изменённых блоков и отправляет их.

Системный администратор, которому нужна более быстрая синхронизация rsync, могут предписывать rsync жульничать и предполагать что если последнее время модификации на обиех сторонах, и локального и удалённого файлов, одно и то же, то файлы не изменялись. (Это в действительности не всегда истинно, однако не фиксируйте это против rsync - системные администраторы должны лучше знать что делают.) Когда временной штамп был изменён, rsync вычисляет контрольные суммы на порциях данного файла на обеих сторонах и сравнивает эти контрольные суммы. Если он находит разницу, он затем вычисляет дельту и пересылает её. Это означает, что если вы делаете небольшие изменения в большом файле, rsync должен прочитать и вычислить контрольную сумму всего файла с обеих, локальной и удалённой сторон. Применяя rsync для поддержки копии такого образа диска ВМ в 500ГБ на машине резервной копии съедает всю связку дисковой производительности и процессорного времени.

Каждый блок в ZFS имеет дату рождения (birthtime), идентификатор группы транзакции момента создания блока. Процесс репликации отправляет все блоки новее чем последнее время выполнения репликации. При этом не имеет значения, получается ли данный блок из нового файла, или же из середины огромного файла.

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

Rsync(1) поддерживает режим резервного копирования снимка (snapshot). Однако, снимки в rsync полностью отличаются от снимков ZFS. При снимках rsync, если вы изменили 1 байт файла в 1ГБ, rsync сохраняет две полные копии этого файла. ZFS, с другой стороны, сохраняет две различные копии одного блока. Обе версии этого файла совместно используют остальные блоки.

В защиту rsync скажем, что он является межплатформенным, совместимым с различными файловыми системами инструментом. Вы можете применять rsync для синхронизации деревьев каталогов между операционными системами и между файловыми системами. Лукас применял rsync для синхронизации деревьев каталогов между сильно различающимися Unix- подобными платформами, например, FreeBSD, и AIX, и Linux.

Однако, если вы применяете ZFS, репликация уникально подогнана для работы с ZFS. Репликация понимает и дублирует свойства ZFS. Она может поддерживать взаимосвязь между клоном и его родителем, в то время как rsync потеряет эту связь и откажется от всех ваших сохранений пространства. Rsync(1) работает не так хорошо на сырых блочных устройствах, в то время как ZFS работает с zvol. Репликация также применяет интегрированные в файловую систему контрольные суммы, поэтому отсутствует риск того, что ваша файловая система получит что-то отличающееся от своих оригиналов.

Репликация ZFS также безразлична к версии. Свойства нового пула разрешены только если вы преднамеренно добавите флаги командной строки при запросе к нему. Это позволяет репликации ZFS легко перемещать данные между пулами с различными версиями.

 Зачем нужны репликации?

Репликации вступают в игру различными способами: наиболее очевидный заключается в резервном копировании, а также в тестировании, виртуализации и при миграциях данных.

Вы на самом деле помните, что RAID не является резервной копией, так? Даже RAID-Z3 не является соответствующей резервной копией. Когда ваша машина попала в пожар, когда закон принуждает конфисковать всё оборудование у вашего поставщика услуг, или когда вы случайно удаляете все жизненно важные наборы данных, RAID-Z3 не поможет вам. Выполните репликацию вашего важного пула на внешний диск, на машину резервных копий или в ленточную библиотеку. Теперь вы можете получить её назад даже после полной утраты вашего оборудования. Привлекательность ZFS состоит в том, что после начальной репликации каждая резервная копия может быть инкрементальной.

Давайте сделаем шаг вперёд. Может оказаться, что простой способности восстановления ваших данных будет недостаточно. Вы должны гарантировать чтобы ваши данные были всегда доступны, 24x7x365. Вам нужна высокая доступность (High Availability). Реплицируйте ваши данные на второй и третий серверы, причём с инкрементальными снимками через каждые несколько минут. Теперь у вас всегда имеются готовые данные для работы на n+2 серверах горячей замены. Поместите один из этих серверов резервных копий в удалённое местоположение и вы защититесь даже от полного разрушения оборудования. (Поддержка географической высокой доступности для вашего ИТ персонала является отдельной проблемой. Мы рекомендуем разрешать всем работать из своего дома. Для достижения наилучших результатов, купите им дома в местах, подобных Фиджи и Сейшелам. Воткните непопулярных парней в Отрыжку лося на Аляске.)

Таким образом, там у вас будет прекрасный набор данных пользовательской информации. Вы захотите протестировать самую новую версию вашей биллинговой системы с ней. Вместо того, чтобы клонировать данные на той же самой машине, вам нужна полностью отделённая копия в новой среде разработки. Будет ли получателем удалённая машина, или новый набор данных в том же самом пуле, репликация ZFS является самым быстрым и надёжным способом копирования данных.

У вас имеются десятки и сотни идентичных машин, ВМ или контейнеров? Применяйте репликацию ZFS для развёртывания вашего идеально изготовленного вручную образа повсеместно. Если вы разработали свою систему должным образом, вы можете даже применять инкрементальные репликации для развёртывания обновлений.

Репликация также великолепно упрощает миграцию данных, даже огромные объёмы данных на нелепые расстояния. Может быть вам придётся выполнять миграцию массивного набора данных на другую сторону страны, или даже через всю планету. При достаточном объёме данных даже 10Gb/s Ethernet в том же самом центре обработки данных кажется слишком медленным! Предположим, у вас есть много терабайт данных, которые всегда используются и подвергаются постоянным незначительным перемешиваниям, например, как в случае пользовательских баз данных. Копирование этих данных через интернет в другой конец страны, или даже мира, займёт дни - но к тому времени данные уже изменятся. Процесс репликации на основе rsync займёт столько времени, что он, скорее всего, никогда не нагонит изменения. Ваши администраторы умные люди и, скорее всего, придумают хитроумный план перемещения ваших данных с какого- либо сорта сложной схемой сегментации. Эти планы могут успешно выполняться, однако увеличивают риск и всегда привносят высокую нагрузку и чувство неудовлетворённости.

Если пропускная способность доступная для синхронизации превосходит скорость обмена данных, применяйте вместо этого ZFS. Ваша первая репликация ZFS, которая содержит каждый кусочек информации из этого гигантского набора данных, может занять несколько дней или недель. Вы можете даже посчитать более практичным выполнить синхронизацию на ленту с ночной доставкой. {Прим. пер.: Курьерская служба доставки всё ещё конкурентоспособна для перемещения гигантских объёмов информации на большие расстояния!} Однако, когда эта синхронизация завершится, вторая репликация нового снимка будет не столь продолжительной. При помощи нескольких репликаций, по мере того, как ваша скорость изменений станет медленнее доступной для резервного копирования полосы пропускания, репликации ZFS догонят практически работу в реальном масштабе времени.

В День Большого Переключения заморозьте свой нбор данных на несколько мгновений пока вы выполняете репликацию самых последних изменений. Вероятно, вы получите несколько мгновений паники по поводу балансировщиков нагрузки, межсетевых экранов, новых серверов и всех прочих гаджетов необходимых для поддержки такого массивного набора данных, однако сами данные не создадут вам проблем.

 Основы репликаций

ZFS не реплицирует наборы данных. Она выполняет репликацию снимков. Снимки не изменяются в процессе репликации (или в любое другое время), поэтому они гарантирую внутреннюю непротиворечивость. Начните с создания снимка ваших данных.


# zfs snapshot mypool/somedata@snappycomeback
 	   

Теперь давайте выполним репликацию этого снимка и локально, и на удалённый хост.

  Локальная репликация

Репликация ZFS имеет одно направление, что означает, что она не нуждается ни в каком обратном отклике от получателя. Это подразумевает, что вы можете сбрасывать снимок в любую другую программу, применяя стандартное перенаправление оболочки Unix и конвейеры (pipe). В нашем примере я подаю вывод zfs send в обычный файл. (Если вы добавите флаг -v, zfs send будет выводить каждую секунду сводку прохождения.)


# zfs send mypool/somedata@snappycomeback > backup_file
 	   

Этот файл является нашим первым применением репликации ZFS, поэтому он не инкрементальный. Он содержит всё из данного снимка. Он примерно того же размера что и сам набор данных. Это не очень полезно в том виде как есть, однако - очень мало людей смогут прочитать потоковую файловую систему без её обратного превращения в файловую систему. (Люди, которые могут читать потоковую файловую систему не превращая её обратно в файловую систему, имеют гораздо лучшее применение своему времени.) Поэтому давайте вернём этот набор данных назад в ZFS при помощи zfs receive.


# zfs receive mypool/copy < backup_file
 	   

Zfs(8) прочитает поток репликации из backup_file и создаст новый набор данных из него, точный дубль оригинального набора данных.

Вам не обязателен некий файл в промежутке локальной репликации. Это Unix- подобная система. У нас существует магия конвейеров. Данный хост имеет домашние каталоги в корне пула, однако я перемещаю копию в новый пул.


# zfs send zroot/home@weds | zfs receive mypool/home
 	   

Теперь я могу перетасовать пару точек монтирования набора данных и переместить свой домашний каталог в свой новый пул.

Однонаправленная природа ZFS делает возможным выполнять репликацию в любое место, куда нацеливается команда, например, на ленту. При помощи конвейера вы можете слить zfs send через SSH в zfs receive, позволяя вам реплицировать набор данных на удалённую машину.

  Просмотр копий

Хотите заглянуть вовнутрь файла потока? Утилита zstreamdump(8) опросит потоки и раскроет подробности. Вы можете опрашивать сам файл или читать напрямую из zfs send.


# zstreamdump < backup_file
 	   

Программа zstreamdump отвечает одним разделом подобным приводимому для всех и каждого снимка в пределах потока zfs send.


BEGIN record
 hdrtype = 1
 features = 4
 magic = 2f5bacbac
 creation_time = 56a53713
 type = 2
 flags = 0x0
 toguid = 424654598740125b
 fromguid = 0
 toname = mypool/somedata@snappycomeback
END checksum = 14035a747cefd2/65f5a463eb5427f0/
3e70de6ff7d7456/497949c053fadcb3
 	   

Этот вывод имеет группу информации о потоке zfs send. Тяжёлая участь в том, что ничто из этого не представлено дружелюбным человеку образом. Даже при таких обстоятельствах мы можем выделить несколько порций информации из него.

Поле creation_time даёт время выполнения zfs send, в принятом измерении секунд от эпохи Unix - в шестнадцатеричном представлении, естественно, потому как почему бы не применять шестнадцатеричное представление для дат? Преобразуем это значение (56a53713) в читаемое по- человечески значение при помощи date(1). Поместим 0x в начало значения для обозначения того, что это шестнадцатеричное значение.


$ date -r 0x56a53713
Sun Jan 24 15:41:55 EST 2016
 	   

На хостах с не FreeBSD date может не принимать шестнадцатеричные значения. Хотя существует множество способов преобразования, вы можете попробовать что-то подобное следующему.


$ printf "%d\n" 0x56a53713 | xargs date -r
 	   

Каждый снимок имеет читаемое человеком имя, определяемое в toname. Данный снимок называется mypool/somedata@snappycomeback, и высвечивает важность применения значимых имён для наборов данных и снимков.

Каждый снимок в пределах потока имеет глобальный уникальный идентификатор, или GUID. GUID данного снимка появляется в поле toguid.

Поле fromgid применяется для инкрементальных отправок ZFS (см. раздел Инкрементальная репликация позже в этой главе), включая только изменения между двумя снимками. В данном примере оно установлено в ноль, что означает, что данный поток zfs send содержит полный снимок. Он не является инкрементальным. Поскольку он является полным снимком, восстановление этого zfs send в работающий набор данных будет иметь смысл. (Вы можете восстанавливать инкрементальный поток ZFS, однако вам необходимо скопировать снимок, на котором он основан.)

Если поток имеет множество снимков внутри - скажем, для инкрементального или рекурсивного zfs send - вы можете применять значения toguid и fromguid для воссоздания того, как снимки подгоняются друг к другу. Однако, возможно, будет проще восстановить поток zfs send в набор данных посмотреть на него таким образом.

Каждый раздел завершается checksum. Вы не можете использовать контрольную сумму для проверки вручную снимка в этом разделе, однако прекрасно знать что ZFS использует контрольные суммы.

После детализации каждого снимка, zstreamdump выводит резюме.


SUMMARY:
 Total DRR_BEGIN records = 5
 Total DRR_END records = 6
…
 Total records = 170
 Total write size = 10523136 (0xa09200)
 Total stream length = 10554216 (0xa10b68)
 	   

Это резюме включает целую группу внутренних метаданных ZFS. Наиболее интересной частью здесь является число записей DRR_BEGIN, которое соответствует числу снимков в данном потоке. Размер в конце представлен в байтах. Записываемый размер является размером данных, включённых в данный поток, в то время как длина потока это размер самого потока. (Поток zfs send имеет метаданные для восстановления данных на диск которые не должны записываться на этот диск.)

 Удалённая репликация

Чтобы реплицировать ZFS на удалённый хост, этому удалённому хосту потребуется пользователь, который может получить доступ к репликации и безопасному конвейеру к этому удалённому хосту. Наиболее общим типом безопасного конвейера является SSH, поэтому мы предполагаем его вашим инструментом. В долгосрочном периоде, самым простым способом применения SSH является аутентификация на основе ключей. Если вы не знакомы с аутентификацией на основе ключей, справьтесь в любом из бесчисленных руководств иои в книге Лукаса SSH Mastery (Tilted Windmill Press, 2012). {Прим. пер.: на нашем сайте см. перевод статьи Приступая к работе с SSH Киммо Суоминен}.

Для получения потоков репликаций вы можете использовать учётную запись root, однако это означает допуск регистрации SSH с правами root. SSH с правами root это плохая идея. И на самом деле, вы хотите чтобы некий сценарий оболочки сопровождаемый этим случайным парнем не пойми откуда из интернета пасся с правами root на всех ваших машинах? Вместо этого создайте пользователя без привилегий и назначьте ему права на репликации, как это обсуждалось в Главе 2.

Аналогично, хотя вы и можете отсылать наборы данных с правами root, вы можете захотеть чтобы обычный оператор или нормальный пользователь мог иметь возможность отправлять наборы данных.

  Пользователи и наборы данных репликации

На обоих хостах, отправляющем и принимающем, мы создаём пользователя, выделенного для репликации. В нашем примере пользователь имеет им replicator. Ему требуется оболочка, но при этом никакого специального участия в группах.


local# pw user add replicator -m -s /bin/sh
remote# pw user add replicator -m -s /bin/sh
 	   

На отправляющем хосте пользователю репликации нужны полномочия send и snapshot для пересылаемого набора данных. Ниже мы предоставляем replicator эти полномочия на домашние каталоги пользователей.


# zfs allow -u replicator send,snapshot zroot/usr/home
 	   

Отправляющему пользователю требуется пара ключей SSH. Пользователь, который применяет свою учётную запись и на отправляющей, и на принимающей сторонах может применять свои собственные ключи SSH для этого. Для выделенных учётных записей сгенерируйте пару ключей при помощи ssh-keygen(1).


# su replicator
$ ssh-keygen
 	   

Программа ssh-keygen предложит вам ввести идентификационную фразу (passphrase). Если в пересылке наборов данных ZFS будут принимать участие люди, воспользуйтесь идентификационной фразой. Если вы делаете это для процесса автоматизации, применяйте пустую идентификационную фразу.

Ключом будет файл .ssh/id_rsa.pub в домашнем каталоге учётной записи этого пользователя. Также мы рекомендуем ограничить хосты, с которых этот ключ может регистрироваться на данной удалённой машине, чтобы помочь защитить этот удалённый хост, а также ваши резервные копии на случай кражи данного ключа.

Теперь застваим этого непривилегированного пользователя установить его общедоступный ключ в его учётную запись на удалённой машине. Здесь мы отправим новый ключ в учётную запись с тем же именем пользователя на наш хост hotspare.


$ ssh-copy-id -i .ssh/id_rsa.pub hotspare
 	   

Проверим что мы можем зарегистрирваться на принимающем хосте в качестве этого пользователя.

На принимающем хосте такой пользователь должен владеть точкой монтирования для получаемого набора данных. Система также должна разрешать непривилегированным пользователям монтировать файловые системы в каталоги, которыми они владеют, при помощи vfs.usermount sysctl.


# zfs create -o mountpoint=/backup remotepool/backup
# chown replicator:replicator /backup
# sysctl vfs.usermount=1
 	   

Нашему непривилегированному пользователю требуются полномочия ZFS compression, create, mount, mountpoint и receive на целевом наборе данных. Здесь я назначаю пользователю replicator привелегии для набора данных remotepool/backup. Если вы собираетесь автоматизировать репликации ZFS, включая разрушение снимков с истекшей датой, вы захотите также добавить свойство destroy.


# zfs allow -u replicator compression,mountpoint,create,mount,receive remotepool/backup
 	   

Такой непривилегированный пользователь может теперь выполнять репликации этого набора данных.

Если вы хотите выполнять репликации всех свойств набора данных, вы должны разрешить пользователю replicator устанавливать все эти свойства. С подробностями того, как создавать набор полномочий вы можете ознакомиться в Главе 2.

  Полная удалённая репликация набора данных

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


$ zfs snapshot zroot/usr/home@monday
 	   

Теперь применим zfs send для передачи данного снимка, подключив его к конвейеру SSH и сбросив его в zfs receive. Запомните, ssh(1) позволяет вам выполнять команды на вашем удалённом хосте. Поскольку это первый раз, когда мы реплицируем данный набор данных, отправляемый поток включает все блоки в данном снимке.


$ zfs send zroot/usr/home@monday | \
      ssh user@host zfs receive remotepool/backup
 	   

Помимо реплицирования в пул на другой машине вы можете выполнять репликацию в тот же самый пул или во второй пул на той же машине, в файл или в конвейер (pipe). Реплицирование в файл или конвейер может быть полезным для резервных копирований, например, на ленту, или в случае различных файловых систем.

Вы можете заставить хост зарегистрироваться на другом хосте, чтобы переключить zfs send если вам это нужно, изменив выполнение репликаций ZFS с модели активной доставки (push) на извлечение по запросу (pull).


$ ssh user@host zfs send zroot/usr/home@monday | \
      zfs receive remotepool/backup
 	   

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

  Инкрементальная репликация

Действительную силу мы получаем от инкрементальных репликаций. Теперь, когда у нас имеются все реплицированные данные из нашего набора данных на понедельник, репликация во вторник требует отправки только изменённых блоков. Сторона команды receive не изменялась вовсе, однако на стороне send мы применим флаг -i, чтобы указать на необходимость отправки самого последнего снимка.


$ zfs snapshot zroot/usr/home@tuesday
$ zfs send -i @monday zroot/usr/home@tuesday | \
      ssh user@host zfs receive remotepool/backup/home
 	   

ZFS отправит только блоки которые были изменены между снимками @monday и @tuesday, сохраняя время и пропускную способность.

Теперь взглянем на наш набор данных в принимающей системе.


# zfs list -t snap -r zroot/backup
NAME                         USED  AVAIL  REFER  MOUNTPOINT
zroot/backup/usrhome@monday    8K      -  49.0M           -
zroot/backup/usrhome@tuesday    0      -  49.0M           -
 	   

Теперь отображены два снимка.

Одна распространённая ошибка при инкрементальных резервных копиях заключается в отсутствии определения самого последнего снимка, который существует на вашей удалённой системе. Если вы не определите самый последний снимок который был передан, вы получите ошибку.


# zfs send zroot/usr/home@tuesday | \
      ssh hotspare zfs recv remotepool/backup/usrhome
cannot receive new filesystem stream: destination
remotepool/backup/usrhome’ exists
must specify -F to overwrite it
 	   

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

Применяя -i, вы можете опускать знак @ в начале имени снимка. Флаг -i означает "это снимок", так что можно смело предполагать, что вы имели в виду поместить @ в начале имени, но просто решили не беспокоиться об этом.

  Допущения инкрементальной репликации

Инкрементальные резервные копии на ленту почти можно исправлять: вы можете перезаписывать их, но кто в 21 веке будет выполнять исправления файла напрямую на ленте. Инкрементальные резервные копии на диск, однако, очень легко изменять.

Репликации приращениями требуют, чтобы принимаемая копия набора данных не менялась между выполнениями репликации. Изменения в этих копиях развалят весь процесс. Если вы измените резервную копию своего набора данных, следующее обновление приращения больше не будет подходить к вашей резервной копии. Если вы вздумаете редактировать реплики набора данных на машине резервных копий, создайте клон всех полученных наборов данных и только после этого редактируйте. Если кто-то случайно или по незнанию изменил реплику, откатите изменения назад к последнему общему снимку. Заставьте получатель принудительно выполнить откат к соответствующему удалённому (расположенному на стороне) снимку добавив флаг -F в свою команду zfs receive.


# zfs send -i @monday zroot/usr/home@tuesday | ssh \
     user@hotspare zfs receive -F remotepool/backup/home
 	   

Предотвратите изменения в репликах наборов данных установив свойство ZFS readonly в значение on для реплицируемых данных. Имея данные ранее полномочия, пользователь может добавлять снимки в наборы данных только для записи.


# zfs set readonly=on remotepool/backup
 	   

Всё- таки вы ещё можете добавлять снимки в remotepool/backup. Вы можете опрашивать эти файлы в своём наборе данных. Однако никто не сможет изменять эти файлы не изменив значение свойства ZFS readonly. И каждый с подобным доступом обязан лучше знать или иметь крайне насущную необходимость чтобы сделать такой набор данных рабочим прямо сейчас.

  Дифференциальная репликация

Репликация ZFS может быть выполнена на любых двух снимках одного и того же набора данных, таким образом, вы можете также выполнять дифференциальные резервные копии. Применение флага -I (i в верхнем регистре), вместо -i отправит все существующие между определяемыми двумя снимками снимки.

Предположим, репликация снимка вторника отказала из- за случайного сетевого происшествия (Системные администраторы могут обвинять любую трудность как возникшую в результате "случайной сетевой проблемы", это занесено в Кодекс Поведения). В среду вы хотите отослать оба снимка вторника и среды.


# zfs send -I @monday zroot/usr/home@wednesday | \
      ssh hotspare zfs recv remotepool/backup/usrhome
 	   

Получетель теперь имеет снимок вторника, даже хотя вы никогда намеренно его не отсылали.

Опытные в выполнении резервного копирования люди реализуют то, что мы используем в cловах "инкременталное" и "дифференциальное" слегка отличным способом, чем это делает большая часть программного обеспечения резервного копирования. Программное обеспечение резервного копирования написано для отправки блоков на ленту и минимизирует число лент, которое вам необходимо для восстановления файлов. Мы можем изобрести новый язык, мы можем рыть глубже для точно подходящих, но незнакомых слов (Лукаса сильно радует, если принимаетесь узнавать какое-то непонятное слово, которое отлично соответствует резервному копированию ZFS, вероятно, из языка тональностей, причём с добавлением щёлкающих звуков и Банту, и по-Койсански, Джуд считает что у Лукаса нет на то прав), или мы можем растянуть только слегка существующий язык.

  Ограничения пропускной способности SSH

Вы можете обнаружить, что соединение SSH является недостаточно быстрым для ваших потребностей. Те из вас, кому нужны репликации быстрее чем пара сотен мегабайт в секунду возможно должны рассмотреть внешние решения для безопасности, например, выделенный VPN. SSH не может обрабатывать данные так быстро без очень специфичных изменений, поэтому рассмотрите возможности mbuffer(1).

 Сложности инкрементальных репликаций

Репликация ZFS является однонаправленной, от отправителя к получателю. Отправитель не получает никакой обратной связи от получателя, позволяя сброс потока каким угодно образом. Это становится существенным при выборе между инкрементальной и дифференциальной репликацией.

Инкрементальное резервное копирование (с -i) отправляет все блоки, которые были изменены между датой рождения первого снимка и последнего снимка, без отправки каких бы то ни было снимков, которые существуют между ними. Если набор данных имеет снимок для каждого дня недели, zfs send -i monday zroot/usr/home@thursday создаёт поток который зависит от вашего существующего на принимающей стороне снимка @monday, а результатом будет создаваемый там снимок @thursday. Никакие промежуточные снимки не реплицируются.

Дифференциальные резервные копирования (с -I) работают в точности как инкрементальные резервные копирования, однако они создают все промежуточные снимки. Команда навроде zfs send -I @monday zroot/usr/home@thursday требует чтобы снимок @monday существовал на удалённой стороне, и она создаёт при своём проходе отсутствующие снимки @tuesday и @wednesday.

Предположим, вы автоматически берёте ежедневные снимки набора данных и вы хотите отправлять их на удалённый сервер. Выполните репликацию снимка @monday в свой удалённый пул.


# zfs send zroot/usr/home@monday | \
      zfs receive hotspare remotepool/backup/usrhome
 	   

Проверьте на вашем удалённом хосте наличие снимка @monday.


# zfs list -t all -r remotepool/backup/usrhome
NAME                           USED  AVAIL  REFER  MOUNTPOINT
remotepool/backup/usrhome     19.5K   472M  19.5K  /remotepool/weekday
remotepool/backup/usrhome@monday  0      -  19.5K  -
 	   

Теперь инкрементально реплицируйте снимок @tuesday.


# zfs send -i monday remotepool/backup/usrhome@tuesday \
      | zfs receive remotepool/weekday
 	   

Проверьте свой удалённый хост, вы найдёте оба снимка.


# zfs list -t all -r remotepool/backup/usrhome
NAME                               USED  AVAIL  REFER  MOUNTPOINT
remotepool/backup/usrhome           29K   472M  19.5K  /remotepool/weekday
remotepool/backup/usrhome@monday  9.50K      -  19.5K  -
remotepool/backup/usrhome@tuesday     0      -  19.5K  -
 	   

В среду вы были отключены на ухаживания - о-э-э, я имею в виду "заболели" - поэтому вы не сделали репликацию. В четверг вы хотите догнать, поэтому выполняете дифференциальную репликацию снимка @thursday.


# zfs send -I tuesday zroot/usr/home@thursday | \
      zfs receive remotepool/backup/usrhome
 	   

Наш хост горячего резерва теперь имееет четыре снимка.


# zfs list -t all -r remotepool/backup/usrhome
NAME                                  USED  AVAIL  REFER  MOUNTPOINT
remotepool/backup/usrhome              48K   472M  19.5K  /remotepool/weekday
remotepool/backup/usrhome@monday     9.50K      -  19.5K  -
remotepool/backup/usrhome@tuesday    9.50K      -  19.5K  -
remotepool/backup/usrhome@wednesday  9.50K      -  19.5K  -
remotepool/backup/usrhome@thursday       0      -  19.5K  -
 	   

Однако, предположим, что нанесённые увечья беспредельных коала стоили вам сна ночи в четверг. Шатаясь утром в пятницу вы решаете выполнить этот день чтобы ничего не разрушить. Настраивая репликацию текущего дня вы случайно пытаетесь выполнить инкрементальное (-i) zfs send с @monday по @friday.


# zfs send -i monday mypool/weekday@friday | \
      zfs receive remotepool/weekday
cannot receive incremental stream: destination
remotepool/weekday has been modified since most recent
snapshot.
 	   

Возможно вы чертовски хорошо знаете, что вы не изменяли эти снимки. Никто не имеет права входить на эту машину. Однако они были изменены - снимки @tuesday, @wednesday и @thursday находятся в пути.

Если вы не уверены что снимки могут существовать на вашей удалённой стороне, вы можете воспользоваться -I для отправки всех промежуточных снимков. В качестве альтернативы вы можете определить -F в своей команде zfs receive для принуждения её удалять всё что стоит на пути.


# zfs send -i @monday zroot/usr/home@friday | \
zfs receive -F remotepool/backup/usrhome
 	   

Нежелательной стороной эффекта применения zfs receive -F "удалять всё, что стоит на пути" заключается в разрушении промежуточных снимков.


# zfs list -t all -r remotepool/weekday
NAME                               USED  AVAIL  REFER  MOUNTPOINT
remotepool/backup/usrhome           29K  472M   19.5K  /remotepool/weekday
remotepool/backup/usrhome@monday  9.50K     -   19.5K  -
remotepool/backup/usrhome@friday      0     -   19.5K  -
 	   

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


# zfs destroy remotepool/backup/usrhome@friday
 	   

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


# zfs send -i monday mypool/weekday@tuesday | \
      zfs receive -F remotepool/weekday
 	   

Факт состоит в том, что репликация является однонаправленной означает что при дифференциальном резервном копировании вы можете отправлять перекрывающиеся снимки, передавая снимок, который уже существует на удалённой стороне. Если мы отправляем все снимки между @monday и @friday, в то время как @tuesday уже существует в удалённом пуле, ваш источник отправит все изменённые данные, даже те блоки, которые уже имеются на удалённой стороне. Удалённая сторона быстро пройдёт вперёд через уже имеющиеся блоки, а затем создаст отсутствующие снимки - в нашем случае с @wednesday по @friday.

Лучшей практикой в этом случае будет избегать коал. А ещё их хаоса.

 Рекурсивные репликации

ZFS также поддерживает рекурсивные репликации, которые реплицируют набор данных и всех его потомков в одной команде. Вот пример пула с тремя наборами данных.


NAME            USED  AVAIL  REFER  MOUNTPOINT
mypool          401M  3.09T   192K  /mypool
mypool/family  50.2M  3.09T  50.2M  /mypool/family
mypool/home     150M  3.09T   150M  /mypool/home
mypool/work     200M  3.09T   200M  /mypool/work
 	   

Возьмём рекурсивный снимок этого набора данных и его потомков.


# zfs snapshot -r mypool@first
# zfs list -t all -r mypool
NAME                USED  AVAIL  REFER  MOUNTPOINT
mypool              401M  3.09T   192K  /mypool
mypool@first           0      -   192K  -
mypool/family      50.2M  3.09T  50.2M  /mypool/family
mypool/family@first    0      -  50.2M  -
mypool/home         150M  3.09T   150M  /mypool/home
mypool/home@first      0      -   150M  -
mypool/work         200M  3.09T   200M  /mypool/work
mypool/work@first      0      -   200M  -
 	   

Теперь мы выполним репликацию этого снимка и всех его потомков одновременно, применяя рекурсивную отправку.


# zfs send -Rv mypool@first | \
      zfs receive remotepool/backup
send from @ to mypool@first estimated size is 9.50K
send from @ to mypool/work@first estimated size is 200M
send from @ to mypool/family@first estimated size is 50.1M
send from @ to mypool/home@first estimated size is 150M
total estimated size is 401M
…
 	   

Рекурсивная отправка также рабоает с инкрементальными (-i) и дифференциальными (-I) резервными копиями, в точности таким же образом. Теперь вы можете принудительно разрушить любой набор данных и его потомков одновременно!

 Дополнительные параметры отсылки

Отправитель может изменять различными способами то, как он отправляет наборы данных.

  Отсылка свойств

Чтобы отправлять свойства так же как и сами актуальные данные, добавьте флаг -p. Когда свойства принимаемого набора данных отличаются от уже имеющихся в этом наборе данных, zfs receive пытается изменить свойства в соответствии с отправляемыми. То есть, если вы реплицируете свойства из набора данных, который применяет сжатие lz4 для набора данных, который уже использует lz4, zfs receive ничего не делает с этим свойством. Однако, если отправитель применяет сжатие gzip-9, получатель произведёт изменения для соответствия оригиналу.

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

Предположим, наш исходный набор данных имеет dedup установленное в значение on и compression установленное в gzip-9. Принимающий набор данных имеет dedup установленное в значение off и compression установленное в lz4. Мы хотим, чтобы принимающий набор данных использовал то же самое свойство compression, но не установки dedup. Мы разрешаем нашему пользователю репликаций изменять compression.


# zfs allow -u replicator compress zroot/backup
 	   

Когда мы отправляем свой набор данных мы получаем ошибку.


cannot receive compression dedup on remotepool/backup:
permission denied
 	   

Это прекрасно - мы не хотим устанавливать свойство dedup на нашей реплике. Однако, свойство compression реплицируется как ожидалось.

Зачем нам реплицировать свойства вместо того чтобы просто устанавливать их на получателе? Ручная настройка может быть прекрасна для простых свойств подобных compression и dedup, однако не так удобно для сложных свойств подобных sharenfs или любым из имеющихся квот.

  Дедуплицированный поток данных

Дедуплицированы ли ваши данные? Пригодны ли они для дедупликации? ZFS позволяет вам дедуплицировать поток данных zfs send. Применение -D отсылает каждый уникальный блок только один раз. Это не изменяет то, что адресат записывает на диск, а влияет только на сам поток данных.

Дедупликация потока данных применяет отличный набор памяти дедупликации от используемого дедупликацией на диске. Если ваши данные могут быть эффективно дедуплицированы, однако эта дедупликация использует многие гигабайты оперативной памяти, то оба участника, и хост отправителя, и хост получателя нуждаются в аналогичном объёме памяти для дедупликациии потока данных. Не так легко дедуплицировать в zfs send!

  Отладка и тестирование

zfs send поддерживает пару параметров которые могут помочь с отладкой, тестированием и мониторингом.

Параметр -v делает zfs send многословным. Он выдаёт информацию о данных которые подлежат отправке и добавляет регулярные обновления состояния.

Флаг -P выводит информацию о правах отправляемых потоков когда поток начинает своё течение. Руководство описывает эту информацию как "машинно- читаемую". Эту информацию могут читать люди, однако она не очень хорошо табулироана. Однако, она исключительно питает ваши сценарии.

Флаг -n предотвращает реальную отсылку каких- либо данных zfs send. Вместо этого, в комбинации с -v и -P

, он выдаёт статистику о том, что zfs send будет делать если он будет реально выполняться.

 

Большие и маленькие блоки

Более новые версиии ZFS могут поддерживать блоки дисков больше чем 128кБ при помощи функциональности zpool(8) large_blocks. Флаг -L позволяет zfs send включать большие блоки вместо того, чтобы дробить их на блоки меньшего размера. Принимающий пул также должен поддерживать большие блоки.

Для хостов, которые в действительности имеют маленькие блоки, -e усекает размер потока данных с помощью свойства embedded_data. Пул назначения должен также поддерживать флаг свойства embedded_data.

  Дополнительные параметры приёма

Получатель может корректировать как он сохраняет приходящий поток ZFS посредством параметров для zfs send.

 

Управление путём и монтированием

Принимаемый поток ZFS содержит путь пула и набора данных источника. Вы можете либо сохранять этот путь, либо отбирать его.

Добавляя флаг -d, вы предписываете zfs receive применять полный путь его источника (за исключением имени пула) в качестве пути к набору данных получателя вместо того, чтобы запрашивать системного администратора определять набор данных получателя. Ранее мы реплицировали zroot/usr/home в remotepool/backup/usr/home. Применяя здесь -d, мы сообщаем zfs receive что он должен использовать путь источника на получателе.


$ zfs send zroot/usr/home@monday | \
      ssh hotspare zfs receive -d remotepool/backup
 	   

Получатель создёт remotepool/backup/usr/home и запихивает туда снимок @monday. Эта функция очень полезна при выполнении репликации многих уровней наборов данных.

Альтернативно вы можете отбирать большую часть информации вашего пути. Добавляя флаг -e вы одаёте указание zfs receive использовать самую последнюю часть пути для именования этого набора данных. Здесь мы выполним то же самое резервное копирование, однако отнимем большую часть вашего пути.


$ zfs send zroot/usr/home@monday | \
      ssh zfs2 zfs receive -e remotepool/backup
 	   

Команда zfs receive выполняет поиск в пути zroot/usr/home и отбрасывает всё кроме последней порции, home. Получаемый поток данных уходит в remotepool/backup/home.

Наконец, параметр -u предписывает zfs receive не монтировать получаемые снимки. Данные существуют для монтирования, если пожелает системный администратор, однако монтироание набора данных может приводить к изменению этих данных.

 

Изменение отката

Если кто- то изменил принятый набор данных, попытка инкрементально добавить новый снимок к этой реплике провалится. Набор данных принимаемого снимка должен быть нетронутым для того, чтобы zfs receive принимал инкрементальные или дифференциальные обновления.

Флаг -F предписывает zfs receive откатить назад любые изменения, которые препятствуют принятию этого снимка.

 

Отладка и тестирование

Во многом схоже с zfs send, zfs receive поддерживает параметры подробностей и без результатов.

Параметр -v делает zfs receive многословным. Он выдаёт информацию о принимаемых данных и добавляет регулярные обновления состояния.

Флаг -n предотвращает реальную запись каких- либо данных zfs receive на диск. Вместо этого, в комбинации с -v он выдаёт статистику о том, что zfs receive будет делать если он будет реально выполняться.

Хотя многословность может быть полезной, параметр -n ограничивает утилиту в приёме данных. Хост получает отсылаемые по сети на этот хост данные, и получатель выполнит некоторый численный анализ, а затем отвергнет эти данные. Чтобы записать эти данные на диск вы должны пересылать их повторно.

 

Клонирование по предписанию

Вам может понадобиться отправка набора данных, который, как вы знаете, вы захотите смешать с навозом. В версии FreeBSD 10.3 вы можете предписать zfs receive сохранять приходящий поток репликации в виде клона вместо того чтобы делать его снимком. Клонирование по предписанию работает только с инкрементальными репликациями.

Чтобы заставить zfs receive создавать клон, добавьте флаг -o и определите источник как набор данных, который вы хотите клонировать. Команда zfs receive возьмёт этот набор данных, добавит приходящий снимок к нему и отделит клон от вашего оригинала.

На протяжении этой главы мы выполняли резервное копирование zroot/usr/home на удалённый сервер. Предположим, что нам нужен клон для чтения- записи снимка среды. Мы начнём клонирование со снимка вторника.


$ zfs send -i @tuesday zroot/usr/home@wednesday | \
      ssh hotspare zfs receive \
      -o origin=remotepool/usr/home@tuesday \
      remotepool/usr/wedshome
 	   

оператор -o origin сообщает zfs receive что мы начинаем со снимка remotepool/usr/home@tuesday и создаём клон. Последний параметр определяет имя клона, remotepool/usr/wedshome. Мы можем теперь перейти в /remotepool/usr/wedshome и выполнить любые нужные нам изменения без какого- либо воздействия на последующие репликации.

Запомните, что создание такого клона, однако, не добавляет переданный снимок к снимкам в первоначальном местоположении. Если мы хотим также создать remotepool/usr/home@wednesday, мы должны осуществить пересылку повторно, без параметра -o origin.

  Закладки

Снимки могут потреблять большое пространство, в особенности на занятой файловой системе. Если у вас есть пользователи, разрабатывающие новое программное обеспечение, загружают ISO, а затем отбраковывают их и повсеместно сбрасывают файлы ядра, тогда снимки могут получить достаточно много. К сожалению, инкрементальные репликации строятся из снимков. Закладки (bookmark) являются способом обходить необходимость сохранить старые снимки, в то же время выполняя инкрементальные репликации.

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

Создадим закладку снимка @friday на наборе данных дней недели. Имена закладок начинаются с символа решётки (#).


# zfs bookmark zroot/usr/home@friday \
      zroot/usr/home#bm-friday
 	   

Просмотрите свою закладку при помощи zfs list.


# zfs list -t all -r mypool/weekday
NAME                    USED  AVAIL  REFER  MOUNTPOINT
zroot/usr/home          360K  13.5G    96K  /mypool/weekday
zroot/usr/home@monday    64K      -    96K  -
zroot/usr/home@tuesday   64K      -    96K  -
zroot/usr/home@wednesday 64K      -    96K  -
zroot/usr/home@thursday  64K      -    96K  -
zroot/usr/home@friday     8K      -    96K  -
zroot/usr/home#bm-friday   -      -      -  -
 	   

Теперь удалим все снимки из пула источника:


# zfs destroy -v zroot/usr/home@%
will destroy zroot/usr/home@monday
…
 	   

На текущий момент у вас осталась только закладка.


# zfs list -t all -r mypool/weekday
NAME                     USED  AVAIL  REFER  MOUNTPOINT
zroot/usr/home            96K  13.5G    96K  /mypool/weekday
zroot/usr/home#bm-friday    -      -      -  -
 	   

В субботу испеките свежий снимок.


# zfs snapshot zroot/usr/home@saturday
# zfs list -t all -r zroot/usr/home
NAME                    USED  AVAIL  REFER  MOUNTPOINT
mypool/weekday           96K  13.5G    96K  /mypool/weekday
mypool/weekday@saturday    0      -    96K  -
mypool/weekday#bm-friday   -      -      -  -
 	   

Не предусмотрительно закладки выводятся в списке после снимков, даже когда они старше чем эти снимки. Однако, командная строка ZFS очень выразительна. Чтобы сделать вещи проще, давайте используем -t чтобы указывать ей выводить только снимки и закладки. Флаг -s предписывает zfs(8) сортировть наш вывод, поэтому мы выполним сортироваку по свойству creation (дате создания). Чтобы игнорировать снимки дочерних наборов данных, добавьте 1 в максимальную глубину рекурсии {-d}.


# zfs list -t snapshot,bookmark -s creation \
      -d 1 zroot/usr/home
NAME                     USED  AVAIL  REFER  MOUNTPOINT
zroot/usr/home#bm-friday    -      -      -  -
zroot/usr/home@saturday   64K      -    96K  -
 	   

Теперь реплицируем снимок @saturday на удалённый хост, применяя закладку bm-friday в качестве fromsnap.


# zfs send -i #bm-friday zroot/usr/home@saturday | \
ssh hotspare zfs receive remotepool/backup/usrhome
 	   

Удалённый хост захватывает снимок @saturday в качестве инкрементального снимка, даже несмотря на то, что хост источника больше не имеет снимка пятницы.


# zfs list -t all -r remotepool/usrhome
NAME                                 USED  AVAIL  REFER  MOUNTPOINT
remotepool/backup/usrhome           58.5K   472M  19.5K  /remotepool/weekday
remotepool/backup/usrhome@monday    9.50K      -  19.5K  -
remotepool/backup/usrhome@tuesday   9.50K      -  19.5K  -
remotepool/backup/usrhome@wednesday 9.50K      -  19.5K  -
remotepool/backup/usrhome@thursday  9.50K      -  19.5K  -
remotepool/backup/usrhome@friday       1K      -  19.5K  -
remotepool/backup/usrhome@saturday      0      -  19.5K  -
 	   

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

  Возобновляемая отсылка

Только то, что ZFS делает репликацию простой, не означает что реальный мир будет с вами сотрудничать. По мере роста набора данных в размере растёт вероятность того, что некая кратковременная проблема разорвёт ваше соединение и прервёт ваш поток. Если вы уже почти завершили выполнение передачи потока данных в 40ГБ через интернет, двухминутный перебой в работе вашего интернет- провайдера может вызвать некую вполне заслуженную ярость. Не ходите после этого как носильщик с топором; вместо этого воспользуйтесь возобновляемыми zfs send, позволяя возобновить прерванные репликации. Возобновляемые zfs send впервые появились в FreeBSD 10.3 в начале 2016.

Чтобы сделать поток ZFS возобновляемым, добавьте флаг -s в zfs receive.

Набор данных mypool/from имеет размер в несколько гигабайт. Добавив -s в оператор zfs receive, однако, мы делаем это поток возобновляемым. Что хорошо, потому что мы собираемся прервать передачу при помощи CTRL-C.


local# zfs snapshot mypool/from@resumeme
local# zfs send -v mypool/from@resumeme | \
       ssh hotspare zfs receive -s remotepool/to
full send of mypool/from@resumeme estimated size is 2.00G
total estimated size is 2.00G
TIME      SENT   SNAPSHOT
17:12:43  279M   mypool/from@resumeme
17:12:44  529M   mypool/from@resumeme
17:12:45  786M   mypool/from@resumeme
^C
 	   

Конечно, поскольку репликация ZFS однонаправленная, отправитель не имеет никакого понятия о том, какие блоки получатель в действительности захватил и записал на свой диск. Без возобновляемой отправки вы должны запустить всю передачу заново.

На принимающем хосте, частично полученный набор данных имеет новое свойство, receive_resume_token. Отправителю требуется значение этого свойства для того, чтобы уловить сколько он может пропустить.


remote# zfs get -H -o value receive_resume_token \
        remotepool/to
1-db9a171a3-c8-789c636064000310a500c4ec50360710e72765a5269740d80cd8e4d3d28a534b40320b-4c61f26c48f2499525a9c540da20ecb02936fd25f9e9a599290c-0cae0dba41478e981fb24092e704cbe725e6a6323014a5e6e-697a416e4e7e7e8a715e5e73a14a51697e6a68264100000648b1d2c
 	   

Теперь предоставим этот маркер (token) отправителю при помощи флага -t. Вам не нужно включать набор данных источника, поскольку этот маркер уже содержит всё необходимое для zfs send. Добавление -v, однако, насыпет больше подробностей о передаче.


local# zfs send -v -t 1-db9a171a3-c8-789c636064000310a-500c4ec50360710e72765a5269740d80cd8e4d3d28a534b40320b4c61f-26c48f2499525a9c540da20ecb02936fd25f9e9a599290c0cae0dba41478e981fb24092e704cbe725e6a6323014a5e6e697a416e4e7e7e-8a715e5e73a14a51697e6a68264100000648b1d2c | zfs receive -s remotepool/to
resume token contents:
nvlist version: 0
 object = 0x8
 offset = 0x35a00000
 bytes = 0x35c35630
 toguid = 0xc237c4c4522d8045
 toname = mypool/from@resumeme
full send of mypool/from@resumeme estimated size is 1.16G
TIME       SENT  SNAPSHOT
17:38:20   263M  mypool/from@resumeme
17:38:21   472M  mypool/from@resumeme
…
17:42:04  1.16G  mypool/from@resumeme
 	   

Когда zfs receive завершится, это свойство очистится.


# zfs get receive_resume_token remotepool/to
NAME           PROPERTY              VALUE    SOURCE
remotepool/to  receive_resume_token      -    -
 	   

Если вы не возобновите эту отправку, пул назначения получит неиспользуемый, незавершённый набор данных у себя, занимая место, которое может быть лучше использовано, ну..., да чем угодно. Удалите это при помощи -A.


remote# zfs receive -A remotepool/to
 	   

Таким образом мы удаляем частично приняты поток и освобождаем это пространство.

  Автоматизация репликаций

Все хотят резервные копии, однако резервные копии, которые должны выполняться вручную не являются резервными копиями - потому что они не будут происходить. Несомненно, вы сделаете их один или два раза, однако в один прекрасный день кофейник прервёт вас и вы едва ли сможете вспомнить когда вы забывали о своём раздражении. Надёжные резервные копии требуют автоматизации и тестирования. Тестирование всегда является именно вашей задачей, однако для автоматизации у нас есть zxfer

Zxfer(8) опрашивает выбранные локальные и удалённые наборы данных, определяет какие снимки должны быть реплицированы чтобы синхронизировать эти два набора данных, и пересылает эти наборы данных. Она также может удалять снимки на удалённой стороне если они были удалены из вашего локального пула.

FreeBSD не содержит zxfer по умолчанию, однако вы легко можете установить его при помощи pkg. zxfer может работать и в режиме активной доставки (push) и в режиме на извлечение по запросу (pull), вам только необходимо установить его в одной из ваших систем. Для целей нашей демонстрации мы установим его на обоих узлах.


# pkg install zxfer
 	   

Команда zxfer в настоящее время не поддерживает ни закладки, ни возобновляемые репликации. Она также не устанавливает учётные записи пользователя репликации. Вы должны настроить эти учётные записи, создать ключи SSH, и установить полномочия в точности, как если бы вы выполняли обычную репликацию.

 

Применение zxfer

Все наши примеры использовали режим активной доставки (push); хост с текущими наборами данных продвигает их на получателя репликации. Мы начнём применять zxfer аналогичным образом zxfer. Сделаем доступным режим активной доставки (push) при помощи -T и зарегистрируемся на нашем удалённом хосте.

Применение zxfer требует чтобы вы определяли хотите ли вы реплицировать только один набор данных, или набор данных вместе с его потомками. Флаг -R делает возможной рекурсию, в то время как -N указывает на единственный набор данных и его снимки. Для резервного копирования практически всегда верен режим рекурсии.

Для получения деталей вы также можете добавить -v.


$ zxfer -v -T user@host -R localpath remotepath
 	   

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

Один момент, который следует помнить, состоит в том, что аргументы, которые принимают аргумент сами по себе не могут быть объединены с аргументами, которые не требуют этого. Вы можете применить -v -T user@host, однако -vT user@host заставит zxfer горько жаловаться. (Так как zxfer является сценарием оболочки, он применяет getopt(1) для обработки аргументов командной строки, вместо того чтобы обрабатывать причудливые параметры, доступные в более сложных языках.)

Здесь мы реплицируем набор данных zroot/somedata в пул remotepool/backups на нашем хосте remote.


local$ zxfer -T replicator@remote \
      -R mypool/somedata remotepool/backups
 	   

Если вы добавите -v для многословного режима, вы обнаружите, что zxfer пересылает каждый снимок.


Sending zroot/somedata@snappy to remotepool/backups/somedata.
Sending zroot/somedata@reply to remotepool/backups/somedata.
(incremental to zroot/somedata@snappy.)
Sending zroot/somedata@more to remotepool/backups/somedata.
(incremental to zroot/somedata@reply.)
 	   

Когда zxfer выйдет, ваш хост remote имеет все необходимые снимки.


remote$ zfs list -t all -r remotepool/backups/somedata
NAME                                USED  AVAIL  REFER  MOUNTPOINT
remotepool/backups/somedata        10.1M  15.0G  10.1M  /remotepool/backups/somedata
remotepool/backups/somedata@snappy    8K      -  10.1M  -
remotepool/backups/somedata@reply     8K      -  10.1M  -
remotepool/backups/somedata@more      8K      -  10.1M  -
 	   

Последующие репликации поверх этих снимков могут выполняться как в режиме активной доставки (push), так и в режиме на извлечение по запросу (pull). Давайте попробуем следующим режим извлечения.

 

Режим извлечения zxfer

В режиме извлечения (pull), zxfer регистрируется на удалённой машине через SSH и выполняет zxfer send для передачи снимков назад на хост, выполняющий zxfer. Воспользуйтесь флагом -O с регистрационным именем и именем хоста для обозначения режима извлечения. Всё остальное является в точности таким же.


$ zxfer -v -O user@host -R localpath remotepath
 	   

Теперь создадим дополнительный снимок на хосте источника.


local$ zfs snapshot mypool/somedata@new
 	   

На машине назначения выполним zxfer для затягивания снимка. Здесь мы добавляем -v чтобы видеть дополнительные прдробности того, что происходит в действительности.


remote# zxfer -v -O replicator@local \
        -R zroot/somedata remotepool/backups
Sending mypool/somedata@new to zroot/backups/somedata.
(incremental to zroot/somedata@more.)
 	   

Смонтироанный набор данных обновлён новым снимком.

 

Циклическая замена снимков

Если вы сохраняете отправляемые снимки, рано или поздно ваш удалённый пул заполнится. Вероятнее всего, вы хотите уничтожать удалённые (расположенные вовне) снимки, которые больше не существуют на машине источника. Чтобы выполнять это применяйте -d. Начните с удаления некого старого снимка.


local# zfs destroy zroot/somedata@reply
 	   

Применяйте флаг -d для подрезки всех удалённых снимков с получателя.


local$ zxfer -vd -T remote \
       -R zroot/somedata remotepool/backup
 	   

В режиме с выводом подробностей zxfer отобразит каждый набор данных, который он разрушит также как и те наборы, которые он создаёт.


Destroying destination snapshot
      remotepool/backup/somedata@reply.
 	   

Вы можете наблюдать как ваша опрометчиво набранная команда разрушает ваши возлюбленный данные.

 

Сохранение старых снимков

Общеупотребимый режим снимка вызывается для изготовления снимка каждые 15 минут, а также каждые час, день, неделю и месяц. (Мы обсуждали такую циклическую схему в разделе Циклическое расписание первой книги по ZFS.) Хост отбрасывает 15- минутные снимки после нескольких часов, снимки каждого часа после пары дней и так далее. Несомненно, вы захотите отбрасывать такие 15- минутные снимки на своём удалённом хосте, однако вы можете захотеть, чтобы ваш удалённый хост оставлял некоторые снимки даже после того, как источник их разрушит. Многие из нас хотят сохранять еженедельные и ежемесячные снимки в виде долговременных резервных копий.

Флаг -g позволит вам защищать наиболее старые резервные копии с аргументом числа дней. Например, -g 375 сообщит zxfer не удалять снимки которые хранятся 375 дней или более.

Допустим, вы хотите сохранять все свои ежемесячные снимки, однако автоматически удаляете все прочие снимки, которые были удалены на источнике. Источник удаляет ежемесячные снимки по прошествии трёх месяцев, а еженедельные снимки после шести недель. Шесть недель это 42 дня. Добавим дополнительную неделю для системных аномалий, получим 49 дней. Использование -g с значением 50 сообщит zxfer не удалять никакие снимки имеющие возраст 50 дней или старше.


local$ zxfer -vd -g 50 -T remote \
       -R zroot/somedata remotepool/backup
 	   

В конечном счёте ваш пул резервных копий переполнится. Вам придётся прийти и почистить ваши снимки, которые стары настолько, что они больше не несут в себе никакой пользы. Это не имеет никакой разницы с чисткой корпоративного чулана с лентами.

 

Свойства и аварийное восстановление

Часто вы будете хотеть реплицировать сложные свойства, например, sharenfs и любые из ваших квот. Параметр -P сообщает zxfer о необходимости установить свойства в получателе в соответствии с его источником.

В некоторых случаях вы хотите знать значения свойств, но не хотите восстанавливать их сразу после репликации. команда zxfer может копировать свойства набора данных в некий текстовый файл, делая возможным восстанавливать их из этого файла позже.

Флаг -k предписывает zxfer создавать текстовый файл свойств, причём в корневом каталоге данной реплики. Этот файл будет иметь имя .zxfer_backup_info с последующей точкой и именем пула. Если вы реплицируете весь пул zroot хоста web5 в remotepool/web5 на хосте резервного копирования, ваш файл резервных копий свойств будет находиться в remotepool/web5/.zxfer_backup_info.zroot.

Для восстановления набора данных и свойств пула из текстового файла применяйте флаг -e.

Обычная конфигурация для хоста предполагает иметь набор пула отдельно для приёма резервных копий и затем выделить набор пула отдельно для аварийного восстановления. Если машина источник выходит из строя, вы можете применить zxfer локально для копирования самой последней резервной копии в пул аварийного восстановления. Вы найдёте ровно такой пример в странице руководства zxfer(8), однако мы приведём общий пример, содержащий восстановление свойств. Я восстанавливаю нашу резервную копию хоста web5 в пул, тоже имеющий имя web5.


# zxfer -deFPv -R remotepool/web5/ web5
 	   

Загрузитесь из нового пула web5 и вы восстановили службу!

 

Дополнительные параметры zxfer

Программа zxfer имеет целую массу опций для копирования в раздращающих обстоятельствах.

Если у вас сложная настройка SSH, вам может понадобиться установить некоторые опции клиента для zxfer в $HOME/.ssh/config пользователя. В качестве альтернативы вы можете добавлять эти опции в одиночных кавычках к -O и -T.

Флаги -O и -T могут также применяться для внутреннего ввода (inject) опций SSH, а также аргументов командной строки. Дополнительные параметры перед пользователем или хостом будут переданы в SSH, в то время как все команды после пользователя и хоста ставятся в начале команды zfs(8). (Однако, вам лучше обслужить настройки полномочий набора данных ZFS, чем применять sudo.)


-O ‘-oPort=1022 -i /path/to/key/file \
      replication@hotspare sudo’
 	   

Флаг -F предписывает zfs receive откатить назад все наборы данных, которые блокируют репликацию. Если вы изменили реплицируемый набор данных, -F снесёт эти изменения.

Вы можете заставить zxfer выполнять снимок автоматически перед выполнением. Это не удалит старые снимки, поэтому это не является должным режимом циклической замены снимка. Однако, это работает для создания немедленной резервной копии, оставляя проблемы с очисткой на другой день. Добавьте -s чтобы заставить zxfer выполнять снимки каждого реплицируемого набора данных.

Наконец, флаг -n переключает режим без реального выполнения (no-op). Программа zxfer не передаёт и не удаляет никакие снимки. Вместо этого она выполняет свои анализы и выводит то, что она делала бы если бы -n не был установлен.

Теперь, когда мы прошли сквозь репликации, эссе о томах ZFS должно показаться лёгким в сравнении с этим. Или, может быть, нет...