НАЗНАЧЕНИЕ
Уменьшение размера виртуального диска (.qcow2) виртуальной машины KVM/QEMU без переустановки гостевой ОС и без потери данных — когда реальный объём используемых данных внутри гостя значительно меньше выделенного виртуального размера диска, и нужно освободить место на хранилище хоста.
ПРИМЕНЕНИЕ
Применяется, когда при создании ВМ диску было выделено с большим запасом больше места, чем реально требуется, и нужно вернуть неиспользуемый объём хосту без даунтайма всей инфраструктуры (только конкретной ВМ на время операции).
Актуально прежде всего для Linux-гостей с файловой системой ext4 без LVM. Для NTFS (Windows) и для LVM-разметки процесс частично отличается — см. раздел «Типовые ошибки».
УСЛОВИЕ
- Sudo-доступ на хосте KVM;
- Установлен пакет guestfs-tools (даёт virt-resize, guestfish, virt-filesystems, qemu-img);
- На хранилище хоста достаточно свободного места, чтобы одновременно держать старый (текущий) и новый (уменьшенный) файлы образа до момента, пока новый не будет проверен и подтверждён рабочим;
- У ВМ нет активных снапшотов (снапшоты усложняют процесс — их нужно предварительно консолидировать/удалить);
- Заранее известен реальный объём используемых данных внутри гостя (df -h / «Этот компьютер») — если он близок к текущему размеру диска (например, занято 80%+), сжатие может не иметь смысла (см. «Типовые ошибки», п.4);
- Наличие бэкапа виртуального диска (на крайний случай).
ШАГИ
- Собрать информацию о диске и разметке. На хосте:
sudo qemu-img info -U /путь/к/disk.qcow2
sudo virsh domblklist <имя_ВМ> --details
Внутри гостя:
lsblk -f
df -h
Зафиксировать: реальный virtual size диска, реально используемый объём данных, разметку (разделы/LVM), точку монтирования.
- Установить guestfs-tools на хосте (если ещё не установлен):
sudo apt update && sudo apt install guestfs-tools
-
Определить целевой размер нового диска — с запасом.
-
Выполнить fstrim внутри гостя (не обязательно, но полезно перед началом):
sudo fstrim -av
- Выключить ВМ и дождаться полной остановки:
sudo virsh shutdown <имя_ВМ>
sudo virsh domstate <имя_ВМ> # должно показать "выключен"
- Убедиться, что на хосте достаточно свободного места для операции:
df -h /путь/к/хранилищу
- Предварительно уменьшить саму файловую систему (именно этот шаг чаще всего пропускают, см. «Типовые ошибки», п.1):
sudo guestfish --rw -a /путь/к/disk.qcow2 run : e2fsck-f /dev/sda2 : resize2fs-size /dev/sda2 <целевой_размер_ФС>G
Целевой размер ФС должен быть заметно меньше, чем итоговый размер нового раздела (запас на служебные структуры и будущий рост).
Важно: внутри guestfish/virt-resize разделы именуются /dev/sdaN независимо от того, как они называются внутри самого гостя (/dev/vdaN).
- Создать новый пустой образ нужного итогового размера:
sudo qemu-img create -f qcow2 /путь/к/disk-new.qcow2 <размер>G
- Выполнить перенос с ужатием раздела:
sudo virt-resize --shrink /dev/sda2 /путь/к/disk.qcow2 /путь/к/disk-new.qcow2
Дождаться сообщения «Resize operation completed with no errors».
- Подменить путь к диску в конфигурации ВМ:
sudo virsh edit <имя_ВМ>
Заменить <source file='...disk.qcow2'/> на <source file='...disk-new.qcow2'/>.
- Запустить ВМ и проверить:
sudo virsh start <имя_ВМ>
Внутри гостя — df -h, lsblk: размер раздела должен соответствовать новому, объём используемых данных — без изменений.
- Обязательно выполнить полную перезагрузку гостя (не ограничиваться тем, что ВМ «продолжила работать» после virsh start) — это единственная надёжная проверка полного холодного цикла загрузки:
sudo reboot
После — переподключиться, проверить uptime, df -h, lsblk ещё раз.
- Проверить логи на реальные ошибки (не ложные срабатывания по ключевым словам):
sudo journalctl -p err -b
-
Проверить работоспособность всех сервисов, которые крутятся на ВМ.
-
Только после уверенности в стабильной работе (можно выдержать паузу для подстраховки) — удалить старый файл образа и проверить освобождение места:
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 актуальна и здесь.



