QEMU (Quick Emulator) – это программа с открытым исходным кодом, которая позволяет выполнять запуск виртуальных машин и эмулировать различные аппаратные архитектуры на одном физическом сервере. Таким образом можно запускать операционные системы и программы, предназначенные для одной архитектуры, на оборудовании с другой архитектурой.
В Linux QEMU часто используется в связке с KVM для обеспечения высокой производительности виртуальных машин. Важным компонентом в работе виртуальной инфраструктуры при этом является QEMU Guest Agent (qemu-ga) – служебная программа-демон, устанавливаемая внутри гостевой ОС виртуальной машины для обеспечения связи с хостом (гипервизором QEMU/KVM).
В этой статье мы разберем особенности использования QEMU.
Для начала – несколько слов о виртуализации.
Виртуализация – одна из ключевых технологий современной облачной инфраструктуры, позволяющая запускать несколько виртуальных машин на одном физическом сервере изолированно друг от друга. Но при подобном подходе возникает вопрос, как сохранить работу множества виртуальных машин при необходимости обслуживания физического сервера.
Для данной задачи был предусмотрен процесс миграции виртуальной машины между гипервизорами – в этом случае виртуальная машина как бы ставится на паузу, создается снимок VM, который передается на целевую машину по сети, после чего выполнение инструкций продолжается уже на новом гипервизоре. При этом сам процесс переключения происходит почти мгновенно.
Но есть ли ограничения для этого процесса? Что будет, если процессоры гипервизоров отличаются? В данной статье мы немного обсудим данные вопросы.
Уровни архитектуры x86-64
Прежде чем перейти к обсуждению миграций, стоит упомянуть про саму архитектуру x86-64.
Архитектура x86-64 существует уже больше 20 лет и за это время набор инструкций в ней расширялся, подобно исходной архитектуре i386 к моменту выхода Pentium Pro – за это время появились MMX, SSE, SSE2, NX и DEP.
Каждый уровень микроархитектуры соответствует базовому набору инструкций процессора. Первоначальный набор x86-64, дебютировавший в виде Athlon 64 от AMD в сентябре 2003 года, известен как x86-64-v1. Любой код, собранный под первый уровень, может запускаться на любом процессоре x86-64.
Второй уровень, x86-64-v2, соответствует Intel Nehalem (2009) и AMD Bulldozer (2010) и выше. В нем добавились векторные инструкции SSE3 и SSE4, а также инструкция POPCNT, требуемая в RHEL 9 и Windows 11.
Также стоит упомянуть неофициальный уровень 2.5, также известный как x86-64-v2-aes. Его важность обусловлена наличием инструкций AES, позволяющих значительно ускорить обработку TLS, а также шифрования AES, значительно повышающего производительность веб-серверов, которые обрабатывают TLS/HTTPS-трафик. Данный уровень соответствует поколению Sandy Bridge от Intel.
Третий уровень, x86-64-v3, соотносится с Intel Haswell и AMD Excavator и добавляет набор инструкций AVX2, предоставляющий 256-битные регистры для выполнения операций SIMD, ускоряя обработку данных, представленных в виде больших массивов, – матриц, векторов и т. д.
И наконец, последний на данный момент уровень x86-64-v4 соответствует процессорам, поддерживающим AVX512. Данный набор инструкций привносит инструкции SIMD для более широких 512-битных регистров.
Типы процессора в QEMU
QEMU позволяет “виртуализовать” определенные типы процессора – можно выставить как определенный тип процессора, так и общие типы, соответствующие уровням, описанным выше. Кроме того, вы можете выбрать тип "host", который передаст виртуальной машине ядро гипервизора со всеми поддерживаемыми им инструкциями. Помимо набора инструкций, также передается информация об ошибках безопасности – и всё это влияет как на производительность, так и на безопасность виртуальной машины.
Многие гипервизоры позволяют выполнять live-миграцию виртуальной машины между хостами. Гипервизор создает снапшот состояния VM, включая кэш, регистры, стек, указатель стека и программный счетчик процессора, после чего передает его другому гипервизору, который воссоздает машину на другом хосте. Звучит сложно, но сам процесс происходит очень быстро после того, как оперативная память машины передана и синхронизирована.
При live-миграции виртуальной машины может возникнуть ситуация, когда процессоры хостов отличаются – это могут быть разные производители, разные архитектуры или даже разные степпинги одной архитектуры. Всё это вносит изменения в набор инструкций между процессорами гипервизора.
Проблема может возникнуть, когда миграция происходит между системами с неодинаковыми архитектурой и степпингом процессора. Виртуальный процессор в VM может иметь регистры и программный счетчик с инструкциями, которые не существуют в реальном железе гипервизора. Что произойдет в таком случае? Процессор гипервизора выбросит исключение, столкнувшись с подобной инструкцией, поскольку не знает, как ее обработать. В лучшем случае гипервизор обработает данное исключение, что приведет к остановке виртуальной машины.
Влияние на безопасность и производительность
Как же решить проблему с живыми миграциями? Первый вариант – осуществлять живую миграцию только между хостами с одинаковыми процессорами. Данный вариант позволяет выжать максимальную производительность, но для миграции потребуется сервер с идентичным процессором. QEMU также дает нам второй вариант – передачу базового набора инструкций гипервизора виртуальной машине. Подобный подход снижает требования к миграции, достаточно, чтобы оба гипервизора поддерживали выбранный набор инструкций. Но у всего есть цена:
- Производительность – например, если запускаемая программа может использовать набор инструкций AVX2, а виртуальный процессор его не включает, ПО в виртуальной машине не сможет использовать эти инструкции даже если физический процессор гипервизора их поддерживает.
- Безопасность – помимо набора инструкций, у процессора есть информация о возможных уязвимостях (обычно это затрагивает спекулятивное исполнение, например, spectrev1 и spectrev2). Некоторые из них специфичны для определенной архитектуры или бренда. Если выбрать некий общий тип процессора, например, на основе уровня архитектуры x86-64, передаваемый список уязвимостей может быть неполным.
Оба подхода имеют право на существование, однако мы придерживаемся первого подхода с сохранением возможности живой миграции за счет унифицированных линеек серверных платформ. При этом миграция между линейками также возможна, хоть для этого и требуется остановка виртуальной машины.
Заключение
Современные компании всё чаще используют системы виртуализации, а рынок отечественного ПО виртуализации ИТ-инфраструктуры, по прогнозам, к 2030 году превысит 50 млрд руб.
В данной статье мы остановились на виртуализации с практической точки зрения – кратко обсудили уровни архитектуры x86-64, какие типы процессора позволяют установить и выполнить настройку QEMU и как тот или иной тип влияет на производительность и безопасность.
Если возникнут вопросы, напишите нам, пожалуйста, тикет из панели управления аккаунта (раздел “Помощь и поддержка”), а если вы захотите обсудить эту статью или наши облачные продукты с коллегами по цеху и сотрудниками Beget – ждем вас в нашем сообществе в Telegram.