Настройка дисковой подсистемы Qemu KVM для увеличения быстродействия в Ubuntu по сравнению с Hyper-V

gxubi1ucfhq7jujnimizriacaqa.png

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

Однако проведённое им тестирование показало, что дисковая система KVM прилично отставала от показателей, которые у него были под Hyper-V. Он хотел раскочегарить qemu на своих Ubuntu серверах, чтобы избежать закупок дорогих серверных лицензий Windows.

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

Для тестирования использовался SSD Samsung 970 Pro 1TB. Заказчик проверял результаты работы в CrystalDiskMark, поэтому далее в статье все графики из него.


Начнём с того, что в Ubuntu (16.04 LTS и 18.04) до сих пор используется qemu версии 2.11. Поэтому некоторые плюшки самых последних qemu в этой статье не рассмотрены.

1. Используем LVM-тома, а не файлы для хранения дисков виртуальных машин.


Логика такая. Файл с виртуальным диском хранится в файловой системе Linux, внутри самого файла находится NTFS. Каждая файловая система потребляет ресурсы при дисковых операциях. Поэтому чем меньше глубина матрёшки, тем быстрее ввод/вывод.

Слой LVM потребляет значительно меньше процессорных ресурсов, чем файловая система. Одна из причин этого то, что блоки в нём значительно больше, чем типичный блок файловой системы (4КБ). Чем больше блок (extent) на физическом устройстве LVM, тем более быстро происходит IO и тем меньше фрагментация.

А ведь даже для SSD случайный ввод/вывод значительно более медленнее, чем последовательный.

LVM довольно удобно использовать для хостинга виртуальных машин. Тем более, что virt-manager (libvirt) умеет из коробки создавать логические тома под диски виртуальных машин.

Поэтому при создании Volume Group мы укажем очень большую величину extent: 256MB.

Привлекательной выглядит также возможность создать thin volumes («тонкие» тома), но если учесть, что тонкий том — это дополнительный слой абстракции, то, очевидно, что он будет ухудшать производительность IO. К тому же в libvirt нет элегантного пути автоматического создания дисков для виртуальных машин в «тонком» пуле.

Read ahead на логическом томе стоит отключить, так как он расходует IO без выигрыша, так как теперь никто не занимается дефрагментацией дисков в Windows на SSD.

# Инициализируем физический раздел SSD для группы томов (volume group)
pvcreate /dev/nvme1n1p1

# Создаёт группу том win с размером блока (extent) 256МБ.
vgcreate -s 256M win_pool /dev/nvme1n1p1

# Создаём логический том vm1. Подойдёт для диска C
lvcreate -n vm1 -L 100G -c 4m

# Отключаем упреждающее кеширование при чтении (read ahead)
lvchange -r none /dev/win_pool/vm1

1.1. Thin volume как диск и/или настройки логических томов для снимков


Если вы хотите использовать thin pool, в котором будете создавать тонкие тома, то имеет смысл установить размер чанка у пула в 4МБ, что значительно больше размера по-умолчанию в 64КБ.
Что повлечёт более быструю работу этого слоя абстракции.

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

lvcreate -c 4m ....


Или в lvm.conf или подобном файле (например lvmlocal.conf):

thin_pool_chunk_size = 4096


Вы можете сами определить оптимальный размер чанка выполнив тестирование следующей командой, подобрав величину --blocksize:

fio --name=randwrite --filename=/dev/nvme0n1p9 --size=10G --ioengine=libaio --iodepth=1 --buffered=0 --direct=1 --rw=randwrite --blocksize=4m


2. Увеличение количества логических процессоров, выделяемых на каждую виртуальную машину KVM, улучшает дисковую производительность.


Понятно, что вряд ли кто будет выделять на виртуалку 10 процессоров, но было интересно посмотреть на крайний случай.

Тут уже зависит от числа свободных процессоров. На мой взгляд больше 4-х выделять нецелесообразно. При числе потоков равному 8 мы получили максимальную производительность случайного чтения и записи. Это специфика CrystalDiskMark 6.0.2, в котором второй тест проводит 8-ю потоками.

Из чего можно сделать вывод, что хорошо иметь по одному логическому процессору на каждую задачу, активно использующую IO.

3. Используем огромные страницы оперативной памяти, чтобы избежать снижения производительности из-за фрагментации RAM.


Этот пакет может пригодиться, когда нам понадобиться различная информацию о hugepages в процессе эксплуатации.

apt install hugepages


Правим /etc/default/grub:

GRUB_CMDLINE_LINUX="default_hugepagesz=1GB hugepagesz=1G hugepages=64"

В данном случае было выделено 64ГБ памяти для всех виртуальных машин в виде hugepages. В вашем случае может быть меньше/больше.

Применяем эти настройки для GRUB, чтобы при следующей загрузке системы они стали активны:

grub-mkconfig -o /boot/grub/grub.cfg

Редактируем конфиг виртуальной машины:

virsh edit vm_name


Добавляем:


  

4. Добавляем в каждую виртуальную машину выделенный поток для обслуживания IO.

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

1


iothread='1'/>




4.1. Для ускорения случайной записи используем кеширование writeback.

Для ускорения случайной записи на диск, но с увеличением риска потери данных, можно использовать cache=writeback в предыдущем пункте. Можно использовать только если есть большая уверенность в качестве и резервировании питания и при наличии бакапов.

5. Настройки дисковой подсистемы в В Virt Manager.


Disk bus: VirtIO
Storage format: raw
Cache mode: writeback
IO mode: threads


5.1. Настройка дисковой подсистемы через конфигурационный файл.


Qemu 2.11 (который сейчас используется в Ubuntu) поддерживает для типа дисковых виртуальных устройств: virtio-blk и virtio-scsi. Когда в Virt Manager указывается Disk bus: VirtIO — это означает использование устройства virtio-blk.

Во всех случаях по скорости лучше virtio-blk. Использовать virtio-scsi имеет смысл в экзотических случаях, например, когда нужно подключать сотни дисков к виртуальной машине.

6. В процессе инсталляции Windows устанавливаем драйвер VirtIO.


Иначе диск не будет доступен для ОС. Для этого используем образ с драйверами, который предварительно подключаем к виртуальной машине.

7. Результаты после применения всех твиков.


На самом деле твик 4.1 не был применён, так как я не был уверен в надёжности питания у клиента.
Нужно понимать, что эти результаты грешат некой условностью, так как при каждом запуске CrystalDiskMark значения немного отличаются.
Мы видим, что удалось существенно ускорить работу дисковой подсистемы в qemu (kvm) при одном и том же числе ядер. Запись была ускорена в среднем на 58%, а чтение на 25%.

Основные элементы успеха: использование LVM-томов вместо файлов qcow2, отдельный поток ввода/вывода и hugepages.

Замеченные ошибки направляйте в личку. Повышаю за это карму.

P.S. vhost-user-blk и vhost-user-nvme


В ходе экспериментов были также и скомпилированы Qemu 2.12 и 3-й версии. Тестировалась опция vhost-user-blk для диска.

В итоге она работала хуже, чем virtio-blk.


Для использования vhost-user-nvme нужно было патчить qemu, этот вариант усложнял автоматическое обновление серверов в продакшене, поэтому не был протестирован.

P.P. S. SPDK


Intel разработала этот фреймворк для достижения выдающих показателей производительности у дисковых систем в виртуальных машинах, которые должны работать на процессорах Intel.

Чтобы заставить spdk хорошо работать идут на массу ухищрений — выделяют ему отдельные ядра, размещают ядра spdk и виртуальной машины в одном сокете. Загружают виртуальную машину в непрерывный кусок памяти. Если такие меры применять к обычному virtio-blk, то он тоже будет быстрее работать.

SPDK способен работать в 3-х режимах: vhost-user-scsi, vhost-user-blk и vhost-user-nvme. Второй режим доступен только в qemu от 2.12, который ещё не доступен в ubuntu. Режим vhost-user-nvme вообще мегаэкспериментальный — для него нужно патчить qemu. На текущий момент работает только эмуляция scsi и она медленная.

Есть ещё одно серьёзное ограничение для режима vhost-user-scsi — диск spdk не может быть загрузочным.

Make sure bootindex=2 Qemu option is given to vhost-user-scsi-pci device.


Рекорды ставятся, когда они с помощью своего драйвера разделяют SSD на несколько устройств и прокидывают их как vhost-user-nvme. Подход с прокидыванием железа нам не подходил.

Сложилось впечатление, что нормально использовать SPDK можно только с их реализацией логических дисков (которая совершенно отличается от стандартных lvm). Это такой самопальный велосипед со своими снимками и клонированием. Команды все отличаются от LVM.

Сложность в настройке SPDK, поддержке и переносимости виртуальных машин, а также привязанность к процессорам Intel отвернула от его использования.

Благодарности


За изображение спасибо TripletConcept. Его лучше смотреть в полном размере в отдельном окне.
За разрешение поделиться рабочими материалами — st_neon


Вы можете заказать виртуальную машину с SSD у RUVDS по купону ниже.

1ba550d25e8846ce8805de564da6aa63.png

Замеченные ошибки направляйте в личку. Повышаю за это карму.

© Habrahabr.ru