Как временно расширить ZFS-пул с помощью zvol из другого пула
Иногда ZFS-пул оказывается заполнен почти полностью, но переносить данные на другой файловый раздел неудобно или слишком долго.
Было два независимых пула:
zpool list
NAME SIZE ALLOC FREE FRAG CAP HEALTH
db 11.7T 8.99T 2.71T 18% 76% ONLINE
limon 79.5G 77.0G 2.46G 90% 96% ONLINEПул limon закончился, а в пуле db оставалось несколько терабайт свободного пространства.
Требовалось временно дать пулу limon около 10 ГБ, очистить логи и затем вернуть конфигурацию в исходное состояние.
Почему нельзя просто передать свободное место?
Свободное пространство принадлежит конкретному ZFS-пулу. Датасет одного пула не может непосредственно использовать место из другого пула.
Топология исходного пула
Пул limon состоял из одного раздела:
zpool status limon
pool: limon
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
limon ONLINE 0 0 0
sdd1 ONLINE 0 0 0Для последующего удаления временного vdev необходимо проверить поддержку функции device_removal:
zpool get feature@device_removal limonВ моём случае функция была включена:
NAME PROPERTY VALUE SOURCE
limon feature@device_removal enabled localТакже необходимо определить фактическое значение ashift существующего vdev.
Команда:
zpool get ashift limonможет показать:
limon ashift 0 defaultЗначение 0 означает автоматический выбор для новых устройств и не показывает фактический ashift уже существующего vdev.
Реальное значение можно получить через zdb:
zdb -C limon | grep -E 'path|ashift'Результат:
path: '/dev/sdd1'
phys_path: 'acpi-VMBUS:01-vmbus-3d4511ba2bac43a19298b9d3bddf7b27-lun-2'
ashift: 12Таким образом, временный vdev тоже нужно добавлять с ashift=12.
Важное предупреждение
Описанный способ создаёт зависимость одного ZFS-пула от другого.
Пока временный zvol входит в пул limon:
- пул db нельзя экспортировать;
- zvol нельзя удалить;
- сервер нельзя загружать без доступного пула db;
- потеря пула db может привести к потере всего пула limon
Это аварийная временная мера, а не постоянная архитектура хранения.
Создание временного zvol
Чтобы не повторять изменяемые значения в командах, зададим переменные:
POOL_SOURCE="db"
POOL_TARGET="limon"
ZVOL_NAME="limon-temp-vdev"
ZVOL_SIZE="10G"
ZVOL_DATASET="${POOL_SOURCE}/${ZVOL_NAME}"
ZVOL_DEVICE="/dev/zvol/${ZVOL_DATASET}"
ASHIFT="12"
VOLBLOCKSIZE="16K"Создаём обычный, неразреженный zvol:
zfs create -V "${ZVOL_SIZE}" -b "${VOLBLOCKSIZE}" -o compression=off "${ZVOL_DATASET}"Проверяем созданный zvol:
zfs get volsize,volblocksize,refreservation,compression "${ZVOL_DATASET}"Проверяем наличие блочного устройства:
udevadm settle
ls -l "${ZVOL_DEVICE}"
blockdev --getsize64 "${ZVOL_DEVICE}"У обычного zvol параметр refreservation должен быть примерно равен его размеру. Это гарантирует, что необходимые 10 ГБ действительно зарезервированы в пуле db.
Проверка добавления без изменения пула
Сначала выполняем пробный запуск:
zpool add -n -o ashift="${ASHIFT}" "${POOL_TARGET}" "${ZVOL_DEVICE}"В предполагаемой конфигурации исходный диск и временный zvol должны находиться на одном уровне:
limon
sdd1
/dev/zvol/db/limon-temp-vdevДобавление временного пространства
Если пробная проверка не показывает ошибок, добавляем zvol:
zpool add -o ashift="${ASHIFT}" "${POOL_TARGET}" "${ZVOL_DEVICE}"После этого проверяем состояние:
zpool status -P "${POOL_TARGET}"zpool list "${POOL_TARGET}"
zfs list "${POOL_TARGET}"Дополнительно проверяем ashift обоих vdev:
zdb -C "${POOL_TARGET}" | grep -E 'path|ashift'Оба top-level vdev должны иметь ashift=12. Разный ashift может помешать последующему удалению временного устройства.
После добавления zvol пул limon получит немного меньше 10 ГБ полезного пространства из-за внутренних накладных расходов ZFS.
Удаление временного vdev
Сначала проверяем возможность удаления:
zpool remove -n "${POOL_TARGET}" "${ZVOL_DEVICE}"Параметр -n не выполняет полноценную симуляцию переноса данных. Он используется для оценки параметров операции, включая необходимый объём памяти для таблиц перенаправления.
Если ошибок нет, запускаем удаление с ожиданием завершения:
zpool remove -w "${POOL_TARGET}" "${ZVOL_DEVICE}"Во время удаления ZFS переносит блоки с временного zvol обратно на исходный диск sdd1.
За процессом можно наблюдать в другом терминале:
watch -n 5 "zpool status ${POOL_TARGET}; zpool list ${POOL_TARGET}"До полного завершения операции нельзя:
- уничтожать zvol;
- экспортировать пул db;
- отключать устройство;
- перезагружать систему без необходимости.
После успешного удаления проверяем, что в пуле остался только исходный vdev:
zpool status -P "${POOL_TARGET}"В конфигурации должен снова отображаться только sdd1.
Удаление временного zvol
Только после успешного завершения zpool remove можно уничтожить zvol:
zfs destroy "${ZVOL_DATASET}"Финальная проверка:
zpool status "${POOL_TARGET}"
zpool list "${POOL_TARGET}"
zfs list "${POOL_SOURCE}" "${POOL_TARGET}"