Мой рецепт для стабильной и быстрой работы виртуальных машин с Windows под KVM. Проверено на Windows 7, 2008, 2008 R2, 2012, 2012 R2 и 2016.
1. Никаких virtio-устройств и соответствующих им драйверов. В общем случае с ними нет проблем, но у меня бывало,что зависающая несколько раз в год машина вдруг переставала так себя вести после перевода ее на то оборудование, драйвера для которого уже есть в комплекте Windows.
Моя любимая конфигурация на сегодняшний день выглядит так:
- SCSI-адаптер lsisas1068
- сетевая карта e1000
- memballoon model=’none’
На самом деле с e1000 один раз проблема была, но это был единичный и трудноуловимый глюк линуксового ядра, который проявился только при десятигигабитной сетевой карте на хосте. Во всех остальных случаях, e1000 достаточно быстра, а ее родной windows-драйвер очень стабилен.
2. Простой и понятный процессор. Скорости это не добавит, но в некоторых случаях может выручить. В частности, когда Windows 2016 только-только пошла в массы, подмена процессора на Core2 Duo существенно повышала ее стабильность на KVM. И не мешало даже то, что Core2 Duo оказался четырехядерным с поддержкой гипертрейдинга:
<cpu mode='custom' match='exact'> <model fallback='allow'>core2duo</model> <topology sockets='1' cores='4' threads='2'/> </cpu>
3. Убедить винду в том, что она запущена на hyper-v. Для этого достаточно добавить в конфиг виртуальной машины:
<features> ... <hyperv> <relaxed state='on'/> <vapic state='on'/> <spinlocks state=’on’ retries='8191'/> </hyperv> ... </features> <clock offset='localtime'> <timer name='hypervclock' present='yes'/> </clock>
И сразу волшебным образом падает Load Average…
4. Дать быстрый диск.
- На текущий момент быстро и дешево – это ZFS, средствами которой собран raid10 с ssd кешем.
- Образы виртуальных машин хранить не в файлах, а в zvol.
- Я уже писал, что предпочитаю эмулировать SCSI-адаптер lsisas1068. Он значительно быстрее IDE, лишь чуть медленнее virtio-scsi, но очень и очень стабилен.
Как приятный бонус, эта связка позволяет включить поддержку trim и при удалении файлов windows будет возвращать дисковое пространство.
5. Включить поддержку huge pages. Сам я с секундомером не стоял, но очевидцы уверяют, что huge pages даёт профит в ~7%.
Бонус:
Пример конфига виртуальной машины, у которой всё хорошо и жизнь удалась.
<domain type='kvm'> <name>vm2016</name> <uuid>f3ebdeca-ac86-4a6c-9246-91cb02e164ce</uuid> <memory unit='KiB'>16777216</memory> <currentMemory unit='KiB'>16777216</currentMemory> <memoryBacking> <hugepages/> </memoryBacking> <vcpu placement='static'>8</vcpu> <os> <type arch='x86_64' machine='pc-i440fx-2.8'>hvm</type> <bootmenu enable='yes' timeout='3000'/> </os> <features> <acpi/> <apic/> <pae/> <hyperv> <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='8191'/> </hyperv> </features> <cpu mode='custom' match='exact'> <model fallback='allow'>core2duo</model> <topology sockets='1' cores='4' threads='2'/> </cpu> <clock offset='localtime'> <timer name='hypervclock' present='yes'/> </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> <emulator>/usr/bin/kvm</emulator> <disk type='block' device='disk'> <driver name='qemu' type='raw' discard='unmap'/> <source dev='/dev/zvol/zfs/virt/zvol/vm2016'/> <target dev='sda' bus='scsi'/> <boot order='1'/> <address type='drive' controller='0' bus='0' target='0' unit='0'/> </disk> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='/virt/iso/Windows2016.iso'/> <target dev='hdb' bus='ide'/> <readonly/> <address type='drive' controller='0' bus='0' target='0' unit='1'/> </disk> <controller type='ide' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> </controller> <controller type='usb' index='0' model='piix3-uhci'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> <controller type='pci' index='0' model='pci-root'/> <controller type='scsi' index='0' model='lsisas1068'> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </controller> <interface type='bridge'> <mac address='aa:bb:cc:00:11:22'/> <source bridge='br0'/> <model type='e1000'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target type='serial' port='0'/> </console> <input type='tablet' bus='usb'> <address type='usb' bus='0' port='1'/> </input> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <graphics type='vnc' port='-1' autoport='yes'> <listen type='address'/> </graphics> <video> <model type='vga' vram='16384' heads='1' primary='yes'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </video> <memballoon model='none'/> </devices> </domain>