Репликация ZFS с помощью команд send и receive — это не просто альтернатива традиционным методам резервного копирования, а надежный, эффективный и атомарный механизм для создания точных удаленных копий ваших данных и моментальных снимков. Это руководство предоставляет готовое, проверенное на практике решение для немедленного внедрения, начиная с основ и заканчивая продвинутыми сценариями для 2026 года. Вы научитесь настраивать как однонаправленную, так и двунаправленную репликацию, автоматизировать процесс через cron и скрипты, а также четко действовать при восстановлении данных из реплики после сбоя. Мы детально разберем ключевые параметры команды zfs send (-I, -R, -w), что даст вам полный контроль над передачей данных и обеспечит актуальность ваших резервных копий.
Основы репликации ZFS: почему send/receive — ваш надежный инструмент
Перед погружением в настройку важно понять, почему механизм zfs send/receive превосходит традиционные методы, такие как файловые копии или rsync. Ключевое отличие — работа не с файлами, а с атомарными снапшотами ZFS. Это значит, что реплицируется не набор отдельных файлов на момент начала копирования, а целостное состояние всей файловой системы на конкретный момент времени. Это исключает проблему «разбегающихся» данных, когда файлы изменяются во время длительного процесса копирования.
Основные преимущества ZFS репликации:
- Атомарность и консистентность: Передается точная копия снапшота, гарантирующая целостность данных.
- Инкрементальная передача: После первой полной синхронизации передаются только изменения между снапшотами, что экономит время и сетевой трафик на 99% и более в зависимости от активности данных.
- Сохранение всех свойств ZFS: Репликация переносит не только данные, но и все атрибуты ZFS: компрессию, дедупликацию (если она включена на уровне пула), квоты, права доступа и историю снапшотов.
- Эффективность на уровне блоков: ZFS отслеживает изменения на уровне блоков данных, а не файлов, что делает инкрементальную передачу максимально эффективной даже при переименовании или перемещении больших файлов.
Ключевые термины, которые будут использоваться:
- Initial send (первоначальная отправка): Полная передача всех данных из базового снапшота.
- Incremental send (инкрементальная отправка): Передача только тех данных, которые изменились между двумя указанными снапшотами.
- Общий снапшот (common snapshot): Снапшот, который существует как на исходной, так и на целевой системе. Он является точкой отсчета для инкрементальной репликации.
Подготовка инфраструктуры: безопасное соединение и создание пулов
Перед началом репликации необходимо обеспечить безопасный и автоматизированный канал связи между серверами, а также проверить совместимость и наличие пулов. Пропуск этого шага — самая частая причина сбоев автоматизации.
Настройка SSH-ключей для безопасной и автоматизированной передачи
Для автоматической работы скриптов репликации необходим безпарольный SSH-доступ от исходного сервера (source) к целевому (target). Рекомендуется создать отдельного системного пользователя (например, zfsbackup) для этих целей, но для простоты примера будем использовать root. Выполните на исходном сервере:
# Генерация SSH ключа (если его нет)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_zfs -N ''
# Копирование публичного ключа на целевой сервер (замените target_host)
ssh-copy-id -i ~/.ssh/id_ed25519_zfs.pub root@target_host
# Тестирование подключения
ssh -i ~/.ssh/id_ed25519_zfs root@target_host 'echo "SSH connection successful"'
Важно для безопасности: На целевой сервере в файле ~/.ssh/authorized_keys можно ограничить команды, которые разрешено выполнять с этого ключа, используя директиву command=. Это предотвращает несанкционированный доступ в случае компрометации ключа.
Проверка пулов и подготовка целевой стороны
Убедитесь, что структура данных готова к репликации.
# На исходном сервере: просмотр пулов и датасетов
zpool list
zfs list -t filesystem -r pool_name
# На целевом сервере: проверка наличия места и пула
zpool list
df -h
Если целевой пул отсутствует, его необходимо создать. Имя пула может отличаться, но структура датасетов будет воссоздана репликацией.
# Создание целевого пула (пример для зеркалированного пула из двух дисков)
zpool create -f backup_pool mirror /dev/sdb /dev/sdc
Расчет места: Для initial send на целевом пуле должно быть свободно как минимум столько же места, сколько занимают данные на исходном пуле (учитывая сжатие). Проверить можно командой zfs list -o used,compression,logicalused pool/dataset.
Первая полная репликация: создание и отправка начального снапшота
Этот шаг создает полную копию ваших данных на удаленном сервере. Начните с создания снапшота на исходной системе.
# Создание первого снапшота (рекомендуется использовать дату в имени)
zfs snapshot -r tank/data@initial_replica_2026-04-16
Команда `zfs send`: ключевые флаги для начальной передачи
Для первой передачи критически важен флаг -R (или --replicate). Он обеспечивает рекурсивную отправку всех дочерних датасетов указанного снапшота, а также всех свойств ZFS и истории снапшотов. Без него будет отправлен только один датасет.
# Отправка рекурсивного снапшота через SSH
zfs send -Rv tank/data@initial_replica_2026-04-16 | \
ssh -i ~/.ssh/id_ed25519_zfs root@target_host 'zfs receive -Fduv backup_pool/data'
Разберем флаги:
-R: Отправляет рекурсивно всю иерархию датасетов, их свойства и историю снапшотов.-v: Выводит подробную информацию о ходе передачи (verbose).- В команде
receive:-F: Принудительно откатывает целевой датасет к состоянию переданного снапшота, если он уже существует.-d: Использует имя целевого пула (backup_pool) как корневое, воссоздавая структуру датасетов относительно него.-u: Не монтирует полученные файловые системы сразу (полезно для контроля).
Прием данных на целевой сервер: команда `zfs receive`
В приведенном выше примере команда receive выполняется на стороне целевого сервера через SSH. После завершения проверьте успешность:
# На целевом сервере
zfs list -t snapshot -r backup_pool/data
# Вы должны увидеть снапшот 'initial_replica_2026-04-16'
Инкрементальная репликация: экономия времени и трафика
После initial send основная работа переходит к инкрементальным обновлениям. Создайте новый снапшот на source и определите общий снапшот с target.
# Создаем новый снапшот на source
zfs snapshot -r tank/data@daily_2026-04-17
Флаг `-I`: отправка цепочки инкрементальных снапшотов
Флаг -I — самый мощный инструмент для инкрементальной репликации. Он отправляет все инкрементальные снапшоты от самого старого общего снапшота до указанного. Это полезно, если несколько репликаций были пропущены.
# Отправка всех изменений от initial снапшота до daily_2026-04-17
zfs send -RI tank/data@initial_replica_2026-04-16 tank/data@daily_2026-04-17 | \
ssh root@target_host 'zfs receive -Fduv backup_pool/data'
Важно: Флаг -i (строчная i) отправляет инкремент только между двумя конкретными снапшотами. Флаг -I (прописная I) отправляет цепочку от общего предка до целевого снапшота.
Автоматический поиск последнего общего снапшота
Для автоматизации скрипту необходимо самому находить последний общий снапшот. Вот логика и пример для bash:
#!/bin/bash
# ... настройки ...
# Получаем последний снапшот на исходной стороне
LAST_SRC_SNAP=$(zfs list -t snapshot -r -o name -H "$SOURCE_DATASET" | grep "@" | tail -1)
# Получаем последний снапшот на целевой стороне (через SSH)
LAST_DST_SNAP=$(ssh "$TARGET_USER@$TARGET_HOST" "zfs list -t snapshot -r -o name -H \"$TARGET_DATASET\" | grep '@' | tail -1")
# Упрощенное сравнение (в реальном скрипте нужна более сложная логика сопоставления имен)
COMMON_SNAP="$LAST_DST_SNAP" # Упрощение: считаем последний на target общим
Более надежный метод — передавать явное имя последнего удаленного снапшота или использовать инструменты вроде sanoid/syncoid, которые решают эту задачу.
Автоматизация процесса: скрипты и cron для регулярной репликации
Ручное выполнение команд не масштабируется. Приведем готовый bash-скрипт для автоматической инкрементальной репликации.
Готовый bash-скрипт для инкрементальной репликации
#!/bin/bash
set -euo pipefail
# --- Конфигурация ---
SOURCE_HOST="localhost"
SOURCE_DATASET="tank/data"
TARGET_HOST="backup-server.lan"
TARGET_USER="root"
TARGET_DATASET="backup_pool/data"
SSH_KEY="/root/.ssh/id_ed25519_zfs"
SNAPSHOT_PREFIX="auto_"
LOG_FILE="/var/log/zfs_replication.log"
# --- Инициализация ---
TIMESTAMP=$(date '+%Y-%m-%d_%H%M')
SNAPSHOT_NAME="${SNAPSHOT_PREFIX}${TIMESTAMP}"
FULL_SOURCE_SNAP="${SOURCE_DATASET}@${SNAPSHOT_NAME}"
# --- Функция логирования ---
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
# --- Основной процесс ---
log "Начало репликации для ${SOURCE_DATASET}"
# 1. Создание нового снапшота на source
log "Создание снапшота ${FULL_SOURCE_SNAP}"
zfs snapshot -r "$FULL_SOURCE_SNAP" || {
log "ОШИБКА: Не удалось создать снапшот"; exit 1;
}
# 2. Определение последнего общего снапшота (упрощенная версия)
# Получаем последний снапшот на target, исключая те, что уже есть в имени auto_*
LAST_REMOTE_SNAP=$(ssh -i "$SSH_KEY" "${TARGET_USER}@${TARGET_HOST}" \
"zfs list -t snapshot -o name -r -H \"${TARGET_DATASET}\" | grep -v '@auto_' | tail -1")
if [ -z "$LAST_REMOTE_SNAP" ]; then
log "На целевом сервере не найдено снапшотов. Будет выполнен initial send."
SEND_CMD="zfs send -R \"${FULL_SOURCE_SNAP}\""
else
log "Последний общий снапшот (определен эвристически): $LAST_REMOTE_SNAP"
# Извлекаем только имя снапшота после @
COMMON_SNAP_NAME="@${LAST_REMOTE_SNAP##*@}"
SEND_CMD="zfs send -RI \"${SOURCE_DATASET}${COMMON_SNAP_NAME}\" \"${FULL_SOURCE_SNAP}\""
fi
# 3. Выполнение отправки
log "Запуск команды отправки: $SEND_CMD"
if eval "$SEND_CMD" | ssh -i "$SSH_KEY" "${TARGET_USER}@${TARGET_HOST}" "zfs receive -Fduv ${TARGET_DATASET}"; then
log "Репликация успешно завершена."
else
log "ОШИБКА: Репликация не удалась."
exit 1
fi
# 4. Очистка старых локальных снапшотов (например, старше 7 дней)
find /"$SOURCE_DATASET"/.zfs/snapshot -name "${SNAPSHOT_PREFIX}*" -type d -mtime +7 -exec echo "Удаление {}" \; 2>/dev/null || true
# Для реального удаления используйте: zfs destroy ...
log "Процесс репликации завершен."
Настройка cron и добавление логгирования
Добавьте скрипт в планировщик cron для ежедневного выполнения, например, в 2:00 ночи.
# Открыть crontab для редактирования
crontab -e
# Добавить строку (предполагается, что скрипт лежит в /usr/local/bin/zfs-replicate.sh)
0 2 * * * /usr/local/bin/zfs-replicate.sh >> /var/log/zfs_cron.log 2>&1
Скрипт уже включает запись в собственный лог-файл. Для продвинутого мониторинга можно добавить отправку уведомлений в Telegram или Slack при обнаружении ошибки (exit code не 0).
Восстановление данных из реплики: процедура аварийного восстановления
Репликация бессмысленна без проверенного плана восстановления. Рассмотрим два основных сценария: восстановление отдельных файлов и полный failover.
Промоут реплики и импорт пула на новом оборудовании
Если основной сервер уничтожен, необходимо сделать реплику основной.
- Импорт пула на резервном оборудовании: Если целевой пул не импортирован, выполните:
zpool import -f backup_pool - Промоут реплики (если использовалась инкрементальная репликация): Это меняет реплику с read-only на read-write и позволяет создавать от нее новые снапшоты.
zfs promote backup_pool/data - Монтирование и проверка данных: Смонтируйте файловые системы и проверьте целостность критических данных.
zfs mount -afind /backup_pool/data -name "important_database.sql" -type f
Для восстановления в рамках стратегии Disaster Recovery, рассмотрите наше подробное практическое руководство по Disaster Recovery в TrueNAS, где разбираются архитектурные модели и пошаговый план разворота системы.
Тестирование плана восстановления: как не допустить сбоя при реальном сбое
Регулярное тестирование — залог успеха. Не реже раза в квартал:
- Разверните виртуальную машину или используйте изолированное железо.
- Импортируйте на нее пул с репликой (можно использовать клон дисков или файлы).
- Выполните процедуру промоута и монтирования.
- Запустите тестовые приложения или скрипты проверки целостности данных.
- Зафиксируйте время от начала процедуры до полной готовности системы (RTO — Recovery Time Objective).
Этот процесс также описан в нашем руководстве по настройке репликации данных в TrueNAS, где отдельный раздел посвящен проверенным процедурам восстановления.
Продвинутые сценарии и оптимизация: raw send, сеть и производительность
Флаг `-w` (raw send) для репликации зашифрованных данных
Если исходный датасет использует встроенное шифрование ZFS (encryption=on), для его репликации без расшифровки используйте флаг -w (raw send). Это передает зашифрованные блоки данных «как есть».
zfs send -wR tank/encrypted_data@snapshot | ssh target_host 'zfs receive -Fduv backup_pool/encrypted_data'
Критически важное условие: Ключи шифрования (или файл с парольной фразой) должны быть доступны на целевом сервере для последующего доступа к данным. Без ключей данные останутся зашифрованными и недоступными.
Использование mbuffer для защиты от сетевых сбоев
При передаче больших объемов данных по ненадежной сети стандартный pipe может оборваться. Утилита mbuffer добавляет буферизацию и повышает устойчивость.
# Установка (Debian/Ubuntu): apt install mbuffer
# Установка (RHEL/CentOS): yum install mbuffer
zfs send -R tank/data@snapshot | \
mbuffer -s 128k -m 2G -O target_host:9999 &
# На целевой стороне:
mbuffer -s 128k -m 2G -I 9999 | zfs receive -Fduv backup_pool/data
Параметры:-s 128k: размер блока.-m 2G: размер буфера в памяти.
Это особенно полезно для initial send по WAN-каналу.
Типичные проблемы и их решения
- «cannot receive: pool is busy»: Целевой пул или датасет используется (смонтирован, в процессе другого receive). Решение: Убедитесь, что на целевом датасете не запущены процессы, размонтируйте его (
zfs unmount -f) или используйте флаг-uв receive, чтобы не монтировать автоматически. - «destination is out of space»: Не хватает места на целевом пуле. Решение: Проверьте место командой
zpool list -o free. Очистите старые снапшоты на target:zfs list -t snapshot -r pool | grep old_snap | xargs -n1 zfs destroy. - Проблемы с совместимостью версий ZFS: Если на source новее версия OpenZFS, чем на target, некоторые флаги (например,
--raw) могут не поддерживаться. Решение: Обновите ZFS на целевом сервере или используйте более простые флаги. Все команды в этом руководстве актуальны для OpenZFS 2.x, который является основой для TrueNAS CORE/Scale 2026 года. - Сбои SSH соединения при автоматизации: Таймауты или разрывы. Решение: Добавьте в
~/.ssh/configна source параметры для target_host:ServerAliveInterval 60иServerAliveCountMax 3. Используйтеmbufferкак описано выше.
Для дальнейшей оптимизации производительности вашего хранилища, включая тонкую настройку ZFS и сетевых протоколов, рекомендуем ознакомиться с нашим руководством по настройке производительности TrueNAS в 2026.