Освободить неиспользуемое пространство в файле-образе qcow2 в kvm/qemu

Мы используем kvm/qemu с qcow2-образами для наших виртуальных машин.

У qcow2 есть эта приятная особенность, когда файл образа выделяет только фактически необходимое пространство для виртуальной машины. но как мне сжать файл образа, если выделенное пространство виртуальной машины становится меньше?

пример:

1.) Я создаю новое изображение в формате qcow2, размером 100 ГБ.

2.) Я использую этот образ для установки Ubuntu. для установки требуется около 10 ГБ, файл образа увеличивается до 10 ГБ. пока ничего неожиданного.

3.) Я заполняю изображение примерно 40 ГБ дополнительных данных. файл изображения увеличивается до 50 ГБ. я в порядке с этим:-)

4.) это то, где это становится странным: я удаляю все данные 40 ГБ на изображении, но размер изображения все еще съедает 50 ГБ.

Вопрос: как освободить эти 40 ГБ данных и уменьшить изображение до необходимых 10 ГБ?

спасибо заранее, Берни

3 ответа

Решение

Изображение не будет автоматически уменьшаться, так как при удалении файлов вы фактически не удаляете данные (вот почему работает undelete). В Qemu есть возможность сжимать изображения qcow2 обратно, но утилита действительно дедуплицирует нули с диска, оставляя всю остальную информацию нетронутой. Таким образом, идея заключается в следующем:

  1. Ноль заполнить диск (dd if=/dev/zero of=/some/file пока не кончится космос)
  2. удалить / некоторые / файл
  3. выключить виртуальную машину
  4. перейдите туда, где хранятся и запускаются образы для виртуальной машины qemu-img convert -O qcow2 original_image.qcow2 deduplicated_image.qcow2
  5. измените настройки виртуальной машины, чтобы использовать новый deduplicated_image.qcow2, проверьте работоспособность виртуальной машины и удалите старый образ

Это, afaik, будет работать только с изображениями qcow2, я не тестировал другие форматы.

Virt-sparsify может сделать все это с меньшими хлопотами с вашей стороны: http://libguestfs.org/virt-sparsify.1.html

Для этого вы можете использовать virt-sparsify. Он автоматически обнуляет и разрежает свободное пространство в большинстве файловых систем, которые он находит в образе исходного диска (поддерживает ext2/3/4, btrfs, NTFS и т. Д.) .

Пошаговые инструкции по конвертации на месте

  1. Выключите виртуальную машину

  2. Сохраните резервную копию

  3. Конвертировать: virt-sparsify --in-place disk.img

Пошаговые инструкции по преобразованию в другой файл (это безопаснее, но требует больше свободного места):

  1. Выключите виртуальную машину

  2. Конвертировать: virt-sparsify disk.img new-file.img

  3. Заменить старый файл новым изображением: mv disk.img disk.img.bak && mv new-file.img disk.img

  4. Если виртуальная машина запускается нормально, вы можете удалить резервную копию: rm disk.img.bak

PS: Вы также можете конвертировать между форматами, используя virt-sparsify:

virt-sparsify disk.raw --convert qcow2 disk.qcow2

В дополнение к принятому ответу (который описывает более распространенный, общий метод сжатия файла qcow2) современная версия (например, RHEL7+) стека libvirt/qemu/qcow2 поддерживает virtio-scsi драйвер, который поддерживает discard='unmap' вариант.

Если виртуальная машина использует virtio-scsi а определение libvirt включает discard='unmap', просто fstrimв гостевой файловой системе освободит назначенное, но неиспользуемое свободное пространство на хосте. Это можно проверить с помощью du -hs <guestdisk> на стороне хозяина (примечание: ls -al <guestdisk>не будет показывать реальный выделенный размер, только логический).

Для даже более новых экземпляров libvirt / qemu (например, RHEL8+) размер гостевого файла можно уменьшить, даже если гостевая ОС не поддерживает обрезку: включив оба discard='unmap' и discard_zeroes='unmap' (и используя virtio-scsi драйвер), записывая последовательный нулевой поток на гостевой стороне (то есть через dd if=/dev/zero of=/zero.img bs=1M count=1024) вызовет обрезку затронутых диапазонов LBA по размеру хоста. Однако обратите внимание, что это может потребовать значительных ресурсов процессора для хоста (который должен был "анализировать" любую гостевую запись в поисках повторяющихся нулей), поэтому его следует включать только в определенных случаях.

Оба метода уменьшат физический выделенный размер (что du -hsпоказывает). Для уменьшения логического размера (какой простой ls -al дает) вам нужно использовать virt-spasify или же qemu-img (как описано в других ответах).

В дополнение к другим ответам о virt-sparsify:

Временная папка

virt-sparsify использует вашу папку /tmp для создания / управления новым образом диска, прежде чем помещать его в папку назначения. Итак, на вашем разделе / ​​должно быть свободное место, даже если файл тома находится в другом разделе.

Если у вас нет свободного места, вы можете установить новую временную папку с помощью --tmp my_tmp_folderвариант. Пример:

mkdir my_tmp_folder
virt-sparsify \
  --tmp my_tmp_folder \
  ubuntu.qcow2 new_ubuntu.qcow2
  • Это не сработает с --in-place;
  • Вы можете удалить папку tmp после завершения процесса.

Подробный

Есть подробный вариант, который поможет вам понять, что происходит. Пример:

virt-sparsify \
  -v \
  ubuntu.qcow2 new_ubuntu.qcow2

Проверить перед удалением

Как было сказано ранее, всегда загружайте виртуальную машину и проверяйте, все ли работает, прежде чем удалять исходный образ диска.

virt-sparsify fileA fileB сделает все это, но на самом деле не уменьшит размер изображения. Для этого нужно добавить --compress,

Измените размер раздела в виртуальной машине до целевого размера, например, измените размер до 50 ГБ для данных 45 ГБ. После этого с базовой машины:

qemu-img convert -f qcow2 -O raw source.qcow2 | dd of=target.raw bs=4M count=12800 status=progress

вероятно будет работать. Возможно, вам потребуется добавить iflag=sync или что-то еще, хотя...

тщательно протестируйте его перед использованием на всем...

Другие вопросы по тегам