Перейти к основному содержимому

ALIMUSAEV — IT и 1С

C:\> type \instructions\linux\umenshit-razmer-virtualnogo-diska-vm-kvm-qemu.md

Уменьшить размер виртуального диска ВМ KVM+QEMU

НАЗНАЧЕНИЕ

Уменьшение размера виртуального диска (.qcow2) виртуальной машины KVM/QEMU без переустановки гостевой ОС и без потери данных — когда реальный объём используемых данных внутри гостя значительно меньше выделенного виртуального размера диска, и нужно освободить место на хранилище хоста.

ПРИМЕНЕНИЕ

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

Актуально прежде всего для Linux-гостей с файловой системой ext4 без LVM. Для NTFS (Windows) и для LVM-разметки процесс частично отличается — см. раздел «Типовые ошибки».

УСЛОВИЕ

  • Sudo-доступ на хосте KVM;
  • Установлен пакет guestfs-tools (даёт virt-resize, guestfish, virt-filesystems, qemu-img);
  • На хранилище хоста достаточно свободного места, чтобы одновременно держать старый (текущий) и новый (уменьшенный) файлы образа до момента, пока новый не будет проверен и подтверждён рабочим;
  • У ВМ нет активных снапшотов (снапшоты усложняют процесс — их нужно предварительно консолидировать/удалить);
  • Заранее известен реальный объём используемых данных внутри гостя (df -h / «Этот компьютер») — если он близок к текущему размеру диска (например, занято 80%+), сжатие может не иметь смысла (см. «Типовые ошибки», п.4);
  • Наличие бэкапа виртуального диска (на крайний случай).

ШАГИ

  1. Собрать информацию о диске и разметке. На хосте:
   sudo qemu-img info -U /путь/к/disk.qcow2
   sudo virsh domblklist <имя_ВМ> --details

Внутри гостя:

   lsblk -f
   df -h

Зафиксировать: реальный virtual size диска, реально используемый объём данных, разметку (разделы/LVM), точку монтирования.

  1. Установить guestfs-tools на хосте (если ещё не установлен):
   sudo apt update && sudo apt install guestfs-tools
  1. Определить целевой размер нового диска — с запасом.

  2. Выполнить fstrim внутри гостя (не обязательно, но полезно перед началом):

   sudo fstrim -av
  1. Выключить ВМ и дождаться полной остановки:
   sudo virsh shutdown <имя_ВМ>
   sudo virsh domstate <имя_ВМ>   # должно показать "выключен"
  1. Убедиться, что на хосте достаточно свободного места для операции:
   df -h /путь/к/хранилищу
  1. Предварительно уменьшить саму файловую систему (именно этот шаг чаще всего пропускают, см. «Типовые ошибки», п.1):
   sudo guestfish --rw -a /путь/к/disk.qcow2 run : e2fsck-f /dev/sda2 : resize2fs-size /dev/sda2 <целевой_размер_ФС>G

Целевой размер ФС должен быть заметно меньше, чем итоговый размер нового раздела (запас на служебные структуры и будущий рост).

Важно: внутри guestfish/virt-resize разделы именуются /dev/sdaN независимо от того, как они называются внутри самого гостя (/dev/vdaN).

  1. Создать новый пустой образ нужного итогового размера:
   sudo qemu-img create -f qcow2 /путь/к/disk-new.qcow2 <размер>G
  1. Выполнить перенос с ужатием раздела:
   sudo virt-resize --shrink /dev/sda2 /путь/к/disk.qcow2 /путь/к/disk-new.qcow2

Дождаться сообщения «Resize operation completed with no errors».

  1. Подменить путь к диску в конфигурации ВМ:
    sudo virsh edit <имя_ВМ>

Заменить <source file='...disk.qcow2'/> на <source file='...disk-new.qcow2'/>.

  1. Запустить ВМ и проверить:
    sudo virsh start <имя_ВМ>

Внутри гостя — df -h, lsblk: размер раздела должен соответствовать новому, объём используемых данных — без изменений.

  1. Обязательно выполнить полную перезагрузку гостя (не ограничиваться тем, что ВМ «продолжила работать» после virsh start) — это единственная надёжная проверка полного холодного цикла загрузки:
    sudo reboot

После — переподключиться, проверить uptime, df -h, lsblk ещё раз.

  1. Проверить логи на реальные ошибки (не ложные срабатывания по ключевым словам):
    sudo journalctl -p err -b
  1. Проверить работоспособность всех сервисов, которые крутятся на ВМ.

  2. Только после уверенности в стабильной работе (можно выдержать паузу для подстраховки) — удалить старый файл образа и проверить освобождение места:

    sudo rm /путь/к/disk.qcow2
    df -h /путь/к/хранилищу

РЕЗУЛЬТАТ

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

ТИПОВЫЕ ОШИБКИ

❌ Проблема: virt-resize завершается ошибкой This partition contains a ext4 filesystem which will be damaged by shrinking it below X bytes, причём X аномально большое (близко к текущему полному размеру раздела) — даже после e2fsck и проверки через vfs-minimum-size, которая показывает вменяемый малый минимум. → В результате новый диск не создаётся (это безопасно: оригинал при этом не повреждается, virt-resize открывает исходник только на чтение).

✅ Решение: virt-resize никогда сам не уменьшает файловую систему — он ожидает, что содержимое (ФС) уже уменьшено заранее пользователем. Нужно обязательно выполнить явный шаг resize2fs-size через guestfish (Шаг 7) до запуска virt-resize, указав целевой размер ФС явно. Проверка через resize2fs -P / vfs-minimum-size показывает только теоретический минимум, а не то, что ФС реально уменьшена.


❌ Проблема: Команда e2fsck-f через guestfish завершается без какого-либо вывода — создаётся впечатление, что ничего не произошло.

✅ Решение: Это нормально. guestfish использует «тихий» preen-режим (-p): при отсутствии ошибок или их автоматическом устранении вывод минимален или отсутствует. Для подтверждения, что операция прошла, можно дополнительно прогнать guestfish —ro -a disk.qcow2 run : vfs-minimum-size /dev/sda2 — должен вернуться разумный минимальный размер, близкий к реально используемым данным.


❌ Проблема: На хранилище хоста недостаточно места, чтобы держать одновременно старый (большой) и новый (уменьшенный) образы.

✅ Решение: Заранее проверить df -h на целевом разделе. Учитывать, что qemu-img create для qcow2 (sparse) в момент создания занимает минимум места, но по мере копирования вырастает примерно до объёма реальных данных + overhead. Если места объективно не хватает — провести операцию во временном месте (другой раздел/диск с достаточным запасом), затем перенести готовый файл на постоянное место.


❌ Проблема: Реальный объём используемых данных близок к виртуальному размеру диска (занято 80–90%+).

✅ Решение: В этом случае сжатие даст минимальный выигрыш, а трудозатраты и риски (особенно для NTFS/Windows-гостей) не оправданы. Проверять df -h (Linux) или «Этот компьютер» (Windows) внутри гостя до начала работ и оценивать целесообразность заранее.


❌ Проблема: Файловая система внутри гостя — NTFS (Windows), а не ext4.

✅ Решение: Шаг 7 выполняется иначе — уменьшение тома делается изнутри самой Windows: «Управление дисками» → правой кнопкой по разделу → «Сжать том» (Shrink Volume), до желаемого размера. Выключать ВМ и продолжать с шага 8 нужно только после этого. virt-resize поддерживает NTFS через встроенный ntfsresize, но так же требует предварительного уменьшения содержимого пользователем — сама логика «виновника» ошибки из п.1 актуальна и здесь.