Назад | Перейти на главную страницу

Как «реально» уменьшить размер образов виртуальных машин KVM?

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

Все, что я нашел, это обнулить свободное пространство виртуальной машины, дефрагментировать виртуальный диск (из Windows), а затем запустить qemu-img convert -c ... (-c флаг для сжатия).

У меня есть виртуальная машина Windows 7 с размером виртуального диска 100 ГБ. Первоначально этот VDD занимал 40 ГБ в хранилище хоста. После обнуления VDD съедает на хосте реальные 100 ГБ. И qemu-img -c ... создает 91 ГБ, что совсем не то, что я ожидал.

На современном веб-сайте мы можем загрузить виртуальные машины W7 размером менее 10 ГБ, как это возможно? Есть ли способ «по-настоящему» сжать образы ВМ?


Благодаря @dyasny я провел небольшой тест с virt-sparsity. Я очистил виртуальный диск W7, отключил гибернацию, поэтому VDD потребляет только 20 ГБ. Снова деградировал диск и снова запустил sdelete -z. Бег virt-sparsity с --compress flag дает виртуальный диск объемом 80 ГБ. Это далеко не то, на что я надеялся.


EDIT-2016-02-16: «Обновление» этого вопроса, поскольку обсуждаемый здесь метод сжатия виртуальной машины очень эффективен, но имеет серьезный недостаток: он удаляет все снимки виртуальной машины. Если кто-то знает, как сжать виртуальную машину при сохранении снимков, поделитесь!

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

Это просто, но неправильное выполнение может привести к потере данных и волос.

Вот шаги для KVM с гостевым компьютером Windows Server 2012 размером 100 ГБ, который мы хотим уменьшить до 35 ГБ, используя формат QCOW2.

ВАЖНЫЙ: Этот метод включает нет модификации виртуальной машины определение. Вместо этого требуется только манипуляции с образами дисков.

Предположения для гостя:

  • Гость - это Windows Server 2012
  • Образ диска 100 ГБ в формате QCOW2
  • Две перегородки:
    • 350 МБ загрузки
    • 99,6 ГБ C: диск с 20 ГБ используемого пространства
  • Мы хотим уменьшить C: с 99,6 ГБ до 34 ГБ

Предположения для Хоста:

  • Сервер Ubuntu 16 LTS
  • KVM (libvirt)
  • Диск 250 ГБ
  • Виртуальные образы, расположенные в / var / lib / libvirt / images

ШАГ 1: Подготовка Windows Guest, усадка основного раздела C:

На этом шаге мы просто уменьшим наши разделы Windows прямо из Windows. Образ диска, полученный в конце этого шага, будет суммой загрузочного раздела, диска C: (уменьшенного) и оставшегося неиспользуемого пространства, которое мы удалим (не копируя его на новый диск).

  1. Войдите в гостевую систему Windows
  2. Откройте служебную программу «Управление компьютером», используя функцию поиска в меню «Пуск», чтобы найти ее.
  3. Слева нажмите «Хранилище-> Управление дисками». Скриншот Storage Disk Management
  4. На новом экране щелкните правой кнопкой мыши раздел C :, выберите «Сжать том…», что должно занять некоторое время, прежде чем появится диалоговое окно. Потерпи.
  5. Когда появится диалоговое окно «Сжать C:», введите объем пространства в поле «Объем пространства для сжатия», чтобы значение «Общий размер после сжатия в МБ» приблизилось к желаемым 35 ГБ. Затем нажмите «Сжать».

    НОТА: Вы можете получить сообщение об ошибке, если новое пространство слишком мало. В этом случае вам следует постепенно уменьшать «Объем пространства для сжатия» на 1 ГБ, пока ошибка не исчезнет и не произойдет сжатие. На практике нам нравится оставлять 10 ГБ свободного места.

    Предположим, вам удалось уменьшить раздел C: до 34 ГБ.

  6. После этого выключите виртуальную машину, открыв командную строку и набрав: shutdown /s /t 0

  7. Ваш гость Windows готов.

ШАГ 2: Уменьшение размера диска на хосте ВМ

На самом деле процедура не является сжатием, но вместо этого мы собираемся создать новый диск (окончательного размера), на котором мы скопируем два раздела с исходного диска и пропустим перенос неиспользуемого пространства.

Цель состоит в том, чтобы создать диск, общий размер которого = загрузочный раздел + раздел C :. У нас также останется крошечный остаток места (если ваша математика не была идеальной), о которой не стоит беспокоиться, потому что мы разберемся на последнем шаге.

  1. Войдите на хост Linux
  2. переключиться на суперпользователя: sudo su
  3. перейдите туда, где хранятся виртуальные образы: cd /var/lib/libvirt/images
  4. перечислить файлы: ls -l
  5. Найдите свое гостевое изображение (множество руководств по этому поводу в другом месте). Предположим, наш гостевой образ Windows называется windows.qcow2
  6. делаем бэкап:

    mkdir backup
    cp windows.qcow2 backup/windows.qcow2.bak
    

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

  7. установите пакеты guestfs, которые могут отсутствовать:

    apt-get install libguestfs-tools
    
  8. Хорошо, давайте дважды проверим наш диск с Windows, исследуя изображение Windows с помощью virt-filesystems:

    virt-filesystems --long --parts --blkdevs -h -a windows.qcow2
    

    который выводит это:

    Name       Type       MBR  Size  Parent 
    /dev/sda1  partition  07   350M  /dev/sda
    /dev/sda2  partition  07   34G   /dev/sda
    /dev/sda   device     -    100G  -
    

    Обратите внимание, что у нас есть /dev/sda1 это наш загрузочный раздел Windows размером 350 МБ, /dev/sda2 который является нашим разделом C: размером 34 ГБ и что общий образ диска /dev/sda/ составляет 100 G, оставляя нам много места для обрезки.

    Итак, вот важный шаг: посчитайте: 34 G + 350M умещается в 35 G, поэтому мы собираемся создать образ размером 35 ГБ. У нас неизбежно останется немного свободного места - если ваша математика не идеальна - но не беспокойтесь об этом, мы разберемся с этим ниже.

  9. давайте создадим новый виртуальный диск QCOW2, который мы называем newdisk.qcow2 общим размером 35 ГБ:

    qemu-img create -f qcow2 -o preallocation=metadata newdisk.qcow2 35G
    

    который выводит:

    Formatting 'newdisk.qcow2', fmt=qcow2 size=37580963840 encryption=off cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16`
    
  10. Давайте изменим размер диска, скопировав старый диск на новый. Это то, что абсолютно круто. Большинство других руководств показывают ужасно сложные вещи. Это просто делается с помощью этой команды, после чего вы должны пойти выпить еще кофе - это, вероятно, займет некоторое время:

    virt-resize windows.qcow2 newdisk.qcow2`
    

    который выводит это:

    [   0.0] Examining windows.qcow2
    100% ?¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦? --:--
    **********
    Summary of changes:
    /dev/sda1: This partition will be left alone.
    /dev/sda2: This partition will be left alone.
    There is a surplus of 439.8M.  An extra partition will be created for the surplus.
    **********
    [   8.8] Setting up initial partition table on newdisk.qcow2
    [   9.9] Copying /dev/sda1
    100% ?¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦? 00:00
    [  15.1] Copying /dev/sda2
    100% ?¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦? 00:00
    Resize operation completed with no errors.  Before deleting the old disk, carefully check that the resized disk boots and works correctly.
    

    Обратите внимание на то, что инструмент обнаружил избыток места ... вспомните комментарии о Math ... Итак, вы можете отменить это и воссоздать диск или просто продолжить, как мы делаем здесь, и развернуть sda2 раздел, как это сделано на ШАГЕ 3.

  11. Когда-то сделали. Осматриваем получившееся изображение:

    virt-filesystems --long --parts --blkdevs -h -a newdisk.qcow2
    

    который выводит это:

    Name       Type       MBR  Size  Parent
    /dev/sda1  partition  07   350M  /dev/sda
    /dev/sda2  partition  07   34G   /dev/sda
    /dev/sda3  partition  83  439.8M   /dev/sda
    /dev/sda   device     -    35G  -
    

    Обратите внимание, как тип /dev/sda3 имеет тип linux для оставшегося места. Оставшееся место - это нормально, если вы не правильно подсчитали. Мы разберемся с этим дополнительным разделом для гостевой Windows ниже. Прямо сейчас просто игнорируйте это.

  12. Поменяйте местами образы дисков:

    mv windows.qcow2 backup/
    mv newdisk.qcow2 windows.qcow2
    
  13. Запустите свою виртуальную машину.

ШАГ 3: Завершение работы с диском в Window Guest

На этом шаге мы подтверждаем, что Windows загружается нормально, и собираемся расширить наш раздел C до дополнительного места.

  1. Войти в гостевой Windows

  2. Откройте служебную программу «Управление компьютером», используя функцию поиска в меню «Пуск», чтобы найти ее.

  3. Слева нажмите «Хранилище-> Управление дисками».

  4. Вы должны увидеть 3 раздела: загрузочный, C: и небольшой раздел размером 439 МБ (крайний правый). Снимок экрана управления компьютером, показывающий 3 раздела

  5. Удалите раздел Linux, щелкнув правой кнопкой мыши -> удалить том. (нажмите "Да" на любой запрос)

  6. Щелкните правой кнопкой мыши раздел C: и нажмите «Расширить», затем «Далее» и «ОК» в диалоговых окнах. Он должен предлагать только расширение на размер последнего раздела. После этого вы изменили размер C: и остались только два раздела.

  7. Это оно. Ваш гость Windows теперь использует только 35 ГБ или около того. Помните, что фактический образ диска может быть больше (он может быть ближе к 38 ГБ) из-за всех накладных расходов и т. Д.

Убедитесь, что все работает нормально, и удалите резервные копии изображений или переместите их в автономный режим в хранилище.

Наконец-то мне удалось по-настоящему сжать пространство виртуальной машины. Вначале виртуальная машина W7 занимала 107 ГБ в хранилище хоста. Размер виртуального жесткого диска составляет 100 ГБ, и в настоящее время виртуальная машина использует только 18 ГБ своей виртуальной памяти.

Вот что я сделал:

  1. Очистите виртуальный диск (удалите файлы temps и т. Д.)
  2. Дефрагментация с помощью программного обеспечения UltraDefrag с открытым исходным кодом с «полной оптимизацией»
  3. Бегать sdelete -c c:
  4. Бегать sdelete -z c:
  5. Бегать qemu-img convert -c -f qcow2 w7-64.qcow2 -O qcow2 w7-64-compressed.qcow2

Таким образом, файл qcow2 был уменьшен с 107 ГБ до ... 7 ГБ!

Когда ты бежишь qemu-img -c, вы сжимаете изображение, что, хотя и сокращает пространство, может серьезно снизить производительность. Если вы хотите дедуплицировать нули на диске, вам нужно запустить qemu-img convert, как будто вы пытаетесь преобразовать изображение из одного формата в другой (даже если форматы src и dst одинаковы).

Этот процесс запишет новое преобразованное изображение без нулей, эффективно дедуплицируя обнуленное пространство на диске.

Другой вариант - просто использовать virt-sparsify конечно.

Метод, который работал у меня для виртуальной машины Windows на KVM, выглядит следующим образом.

В гостевой ОС Windows:

  1. При необходимости выполните дефрагментацию.
  2. sdelete -z c: (sdelete -z для виртуальных машин. Он не увеличивает фактический размер образа QCOW2 на диске и обнуляет пустое пространство. sdelete -c с другой стороны, не требуется, и это увеличит размер образа QCOW2 на диске)

На хосте Linux:

  1. qemu-img convert -O qcow2 -c inputVM.img outputVM.img (обратите внимание, что это не сохраняет снимки и принимает текущее состояние)

Вам просто нужно «дырокол» или «разрежить» пустое пространство. Для этого вам нужно, чтобы пространство содержало только нули и дыры. «Пустое пространство» файловой системы просто нераспределено, но может содержать старые ненужные данные, а не нули. Итак, первый шаг - обнулить его. Для этого есть инструменты, но вот простой минимальный способ сделать это ...

  1. Загрузите vm.
  2. Создайте файл, содержащий только 0 в каждой файловой системе, и удалите его. Здесь я предполагаю, что / tmp доступен для записи и находится в rootfs. (в Windows вы можете выполнить ту же команду в cygwin или использовать другой инструмент.)

    dd if=/dev/zero of=/tmp/zeros bs=1M
    rm /tmp/zeros
    

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

  3. Остановите виртуальную машину.

  4. Пробейте отверстия. Есть несколько способов сделать это ... вот быстрый способ, используя скрипт python. Сначала остановите виртуальную машину, а затем запустите сценарий на дисковых файлах. Если это файл qcow2 или другой формат, он должен работать так же, но может быть что-то я забываю или просто способ попроще.

И имейте в виду, что дыра не выделяется, поэтому файл не находится в одном месте; файловая система может стать фрагментированной, что снизит производительность. Это никоим образом не должно быть заметно в типичных файловых системах Linux / UNIX, если только у вас не было очень мало места при записи файлов, но просто помните о возможности. Рекомендуется оставлять не менее 10% свободного места, чтобы избежать фрагментации.

Кроме того, есть инструменты, которые делают и другие вещи ... например, обнуление только ненулевого пустого пространства (чтобы они не увеличивались до того, как вы пробили дыры), обнуление свопа тоже, выполнение этого в режиме онлайн (возможно, требуется поддержка гипервизора), и т. д. Я попробовал эти способы и обнаружил, что все они ужасно ненадежны, иногда едва уменьшая 5% по сравнению с ручным обнулением, так что я даже не буду утруждать себя перечислением инструментов; другие могут перечислить свои фавориты.

В Xenial и Bionic утилита virt-sparsify из пакета libguestfs-инструменты должно сработать. Обратите внимание, что:

  • Вам НЕ нужно запускать такой инструмент, как sdelete заранее внутри гостя (но не повредит)
  • Вы можете использовать --in-place чтобы освободить место без копирования файла (полезно, если размер образа диска уже превышает размер оставшегося свободного места на диске!)
  • Инструмент поддерживает изображения в формате qcow2 и raw.

Вы можете отключить восстановление системы или удалить все существующие теневые копии тома на диске виртуальной машины. Одно это может занять много места и будет отображаться скрытым для файловой системы. Затем запустите sdelete и обнулите свободное место после перезагрузки виртуальной машины.