MAATRIX / Блог / LVM: снапшоты, расширение и как не потерять данные

LVM: снапшоты, расширение и как не потерять данные

MAATRIX

Диск на сервере закончился в неудобный момент, а пересоздавать раздел с нуля и переносить данные — то ещё удовольствие. Или вы решили сделать консистентный бэкап базы данных «на живую» и создали снапшот — а через сутки обнаружили, что он развалился и откатиться уже нельзя. Оба случая закрывает LVM, если понимать, как он устроен на самом деле, а не только помнить набор команд.

Что такое LVM и зачем нужен этот слой абстракции

LVM (Logical Volume Manager) — менеджер логических томов в Linux, который встаёт между физическими дисками и файловой системой. Без LVM раздел жёстко привязан к границам на диске: если /dev/sda1 занял место от начала до какой-то отметки, расширить его без переразбивки диска (в лучшем случае) или переустановки (в худшем) сложно и рискованно.

LVM вводит три уровня:

  • Physical Volume (PV) — физический диск или раздел, помеченный как доступный для LVM (pvcreate /dev/sdb).
  • Volume Group (VG) — пул из одного или нескольких PV, объединённых в общее пространство (vgcreate vg_data /dev/sdb). Можно добавлять новые диски в VG на лету.
  • Logical Volume (LV) — «виртуальный раздел», который нарезается из VG (lvcreate -L 50G -n lv_web vg_data) и на котором создаётся файловая система.

Ключевая выгода: LV не привязан жёстко к физическим границам диска. Можно добавить новый физический диск в VG, а потом «дорастить» существующий LV за счёт этого пространства — без остановки сервиса и без пересборки таблицы разделов. Это особенно удобно на арендованном сервере или VPS, где диск часто нельзя просто физически заменить на больший — зато можно подключить дополнительный том и расширить VG.

Обратная сторона гибкости — LVM добавляет ещё один слой между железом и файловой системой, а значит ещё одно место, где можно ошибиться в команде и получить неожиданный результат. Ниже — две самые практичные операции: расширение тома и снапшоты, и что в них может пойти не так.

Расширение логического тома: пошагово

Типичная задача — на сервере кончается место, диск заранее был отдан LVM с запасом (или в VG есть непроинициализированное пространство), и нужно добавить места к существующему разделу без даунтайма.

Порядок действий:

  1. Проверить свободное место в volume group:
vgs
# VG      #PV #LV #SN Attr   VSize   VFree
# vg_data   1   2   0 wz--n- 200.00g  50.00g

Если VFree показывает 0, а физический диск на самом деле больше, нужно сначала расширить сам раздел под PV (например, через growpart, если это облачный/VPS-диск), а затем — сам PV:

growpart /dev/sda 3
pvresize /dev/sda3
  1. Расширить логический том за счёт свободного места в VG:
lvextend -L +20G /dev/vg_data/lv_web

Здесь +20G значит «добавить 20 ГБ к текущему размеру». Можно и указать абсолютный размер (-L 70G) вместо относительного прироста, либо отдать всё свободное место сразу:

lvextend -l +100%FREE /dev/vg_data/lv_web

На этом шаге сам логический том уже стал больше, но файловая система внутри него — ещё нет. Это частая ошибка: lvextend отработал без ошибок, df при этом продолжает показывать старый размер, и человек думает, что что-то не сработало.

  1. Расширить файловую систему поверх увеличенного тома. Команда зависит от типа ФС:

Для ext4:

resize2fs /dev/vg_data/lv_web

Для XFS (важно: XFS можно только расширять, уменьшить её штатными средствами нельзя):

xfs_growfs /mount/point

Обратите внимание: resize2fs принимает путь к устройству, а xfs_growfs — путь к точке монтирования, а не к устройству. Это частая причина ошибки «no such file or directory» при копировании команды из чужого мануала без адаптации.

Можно сделать оба шага (lvextend + resize) одной командой с флагом -r:

lvextend -r -L +20G /dev/vg_data/lv_web

Флаг -r сам определит тип файловой системы и вызовет нужную утилиту расширения. Это удобно и снижает риск забыть второй шаг, но при нестандартных ФС (например, ZFS поверх LVM, что само по себе не лучшая идея) лучше делать шаги раздельно и проверять вывод каждого.

Важная деталь: lvextendresize2fs на смонтированной ext4) можно выполнять на активном, смонтированном разделе — сервис останавливать не нужно. Это одно из главных практических преимуществ LVM: место добавляется «на лету». Уменьшение тома — отдельная и куда более опасная операция (нужно сначала уменьшить ФС, потом том, и в обратном порядке), здесь её разбирать не будем: если сомневаетесь — не уменьшайте, лучше выделить новый том нужного размера и перенести данные.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Снапшоты LVM: как это устроено внутри

Снапшот LVM — это моментальный «слепок» состояния тома на момент создания, который позволяет либо откатиться назад, либо снять консистентную копию данных (например, для бэкапа базы данных без остановки СУБД). Создаётся он так:

lvcreate -L 5G -s -n lv_web_snap /dev/vg_data/lv_web

Здесь -s — флаг снапшота, а -L 5G — это ключевой параметр, из-за которого и возникает весь дальнейший риск: это заранее заданный, фиксированный размер места, выделенного под хранение изменений, а не размер самого снапшота как «полной копии» тома.

Механика классического LVM-снапшота (COW, copy-on-write) устроена так: снапшот сам по себе не копирует данные тома. Вместо этого при любой записи на исходный том LVM сначала сохраняет старую версию изменяемого блока в отдельную область — ту самую, зарезервированную флагом -L. Снапшот логически «состоит» из исходного тома плюс этой области с сохранёнными старыми блоками. Чем больше данных меняется на исходном томе после создания снапшота, тем больше заполняется эта резервная область.

Критический риск: переполнение и безвозвратная порча снапшота

Вот здесь и кроется проблема, которую часто упускают: область под изменения имеет жёсткий, заранее заданный лимит. Если объём реальных изменений на исходном томе с момента создания снапшота превышает выделенный размер (те самые 5G в примере выше), происходит следующее: снапшот автоматически и безвозвратно переходит в невалидное состояние (в выводе lvs это отображается как атрибут d — disabled/invalid). Восстановиться из такого снапшота или откатиться к нему уже нельзя — он просто помечается недействительным и сохранённые для отката блоки становятся бесполезны.

Это принципиально отличается от того, как работают снапшоты в ZFS или Btrfs. Там снапшот — часть нативной модели copy-on-write самой файловой системы: место под изменения не резервируется заранее фиксированным куском, а расходуется динамически из общего свободного пространства пула. Пока в пуле есть свободное место вообще, снапшот не «портится» из-за собственного переполнения — он просто продолжает занимать больше места по мере накопления изменений. Разбор этой механики есть в статье про снапшоты ZFS и пул/датасет и в сравнении снапшотов ZFS с полноценным бэкапом — там же видно, почему снапшот и бэкап — не одно и то же ни в LVM, ни в ZFS.

Итого: классический LVM-снапшот — это не «безопасная копия на всякий случай», а конструкция с конечным и заранее известным запасом прочности. Создать его и забыть — рабочая стратегия только для очень короткого окна (минуты, максимум часы) с предсказуемо низкой нагрузкой на запись. Для чего угодно длиннее — нужен явный расчёт и мониторинг.

Сколько места закладывать на практике

Универсального числа нет — объём изменений зависит от интенсивности записи на исходный том. Но есть рабочий подход:

  • Оцените объём записи на том за предполагаемое время жизни снапшота. Для базы данных под нагрузкой это может быть заметная доля от объёма самого тома даже за несколько часов — здесь ориентируйтесь на собственную статистику iostat/логи СУБД, а не на общие цифры из интернета.
  • Берите запас с большим множителем от этой оценки, а не впритык. Для снапшота, который вы планируете держать дольше короткого окна (классический случай — снять консистентный дамп базы данных, который выполняется не пять минут, а час-два), закладывайте кратно больше, чем «средняя» оценка изменений — лучше отдать лишний десяток гигабайт под снапшот, чем потерять возможность отката в середине бэкапа.
  • Учитывайте, что размер снапшота (-L) можно расширить и после создания командой lvextend, если он начинает заполняться — но для этого нужно вовремя заметить проблему, а не узнать о ней постфактум.

Практический пример: если исходный том 100 ГБ и на нём работает база данных с активной записью, для двухчасового окна снятия бэкапа лучше закладывать не «на глазок» 5-10%, а по факту наблюдаемой нагрузки — если логи СУБД показывают условные 15-20 ГБ изменений в час, разумный запас на два часа с хорошим коэффициентом безопасности — далеко за пределы голого расчёта «изменения × время». Точную цифру для своей нагрузки нужно смотреть по факту, а не ориентироваться на чужие цифры — они будут другими на другом сервере с другим профилем нагрузки.

Тема связана с более общим вопросом о запасе диска вообще — см. сколько дискового пространства закладывать с запасом: для снапшотов правило то же самое, просто последствия нехватки места жёстче, чем обычное «диск заполнился на 100%».

Мониторинг заполнения снапшота в реальном времени

Создать снапшот с запасом — необходимое, но не достаточное условие. Нужно следить за его заполнением, пока он существует, а не проверять постфактум. Команда lvs с полем Data% показывает, насколько заполнен снапшот прямо сейчас:

lvs -o lv_name,lv_size,data_percent,snap_percent
#   LV            LSize  Data%  Snap%
#   lv_web        70.00g
#   lv_web_snap    5.00g          62.40

Snap% (или Data% в зависимости от версии lvs) для снапшота — это процент заполнения выделенной под него области. Когда это значение приближается к 80-90%, пора действовать — либо расширить снапшот, либо ускорить операцию, ради которой он был создан (например, доснять бэкап и удалить снапшот раньше).

Расширить существующий снапшот, пока он ещё не переполнился, можно так же, как и обычный том:

lvextend -L +5G /dev/vg_data/lv_web_snap

Для автоматического контроля в проде разумно повесить простую проверку по cron или в систему мониторинга — например, скрипт, который парсит вывод lvs --noheadings -o snap_percent и шлёт алерт при превышении порога (скажем, 75%). Ручная проверка раз в сутки для снапшота, который живёт часы, — это уже постфактум: к моменту, когда вы посмотрите, он может быть уже мёртв.

И главное практическое правило: не создавайте снапшот «на всякий случай» надолго. Если задача — консистентный бэкап, снимайте его, копируйте данные и сразу удаляйте снапшот (lvremove). Чем дольше он существует, тем больше накапливается изменений и тем выше риск упереться в лимит, даже если изначально запас казался щедрым.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли уменьшить размер выделенной под снапшот области после создания?

Штатно уменьшить область снапшота нельзя — только расширить (lvextend). Если запас оказался избыточным, проще удалить снапшот и при необходимости создать новый меньшего размера.

Что произойдёт с исходным томом, если снапшот переполнится и станет invalid?

Ничего — исходный том продолжает работать в обычном режиме. Испорченным становится только снапшот: он теряет пригодность для отката, а не сам рабочий том.

Нужно ли размонтировать файловую систему перед lvextend?

Нет, расширение тома и файловой системы (ext4 через resize2fs, XFS через xfs_growfs) штатно выполняется на активном смонтированном разделе без остановки сервиса.

Чем LVM thin-provisioning отличается от классического снапшота, описанного здесь?

LVM thin pools используют динамическое выделение места, ближе по духу к ZFS/Btrfs, и не имеют того же жёсткого фиксированного лимита на снапшот — но это отдельная тема со своими нюансами и граблями, здесь речь про классические (thick) снапшоты, которые в проде встречаются чаще.

Как понять, что снапшот уже испорчен?

Команда lvs покажет атрибут d в столбце атрибутов у такого тома, а попытка примонтировать или откатиться (lvconvert --merge) завершится ошибкой.

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →