Мне лично проще всего думать о KVM (Kernel-based Virtual Machine), как о таком уровне абстракции над технологиями хардверной виртуализации Intel VT-x и AMD-V. Берем машину с процессором, поддерживающим одну из этих технологий, ставим на эту машину Linux, в Linux’е устанавливаем KVM, в результате получаем возможность создавать виртуалки. Так примерно и работают облачные хостинги, например, Amazon Web Services . Наряду с KVM иногда также используется и Xen, но обсуждение этой технологии уже выходит за рамки данного поста. В отличие от технологий контейнерной виртуализации, например, того же Docker , KVM позволяет запускать в качестве гостевой системы любую ОС, но при этом имеет и б о льшие накладные расходы на виртуализацию.
Примечание: Описанные ниже действия были проверены мной на Ubuntu Linux 14.04, но по идее будут во многом справедливы как для других версий Ubuntu, так и других дистрибутивов Linux. Все должно работать как на десктопе, так и на сервере, доступ к которому осуществляется по SSH.
Установка KVM
Проверяем, поддерживается ли Intel VT-x или AMD-V нашим процессором:
Если что-то нагреполось, значит поддерживается, и можно действовать дальше.
Устанавливаем KVM:
sudo apt-get install qemu-kvm libvirt-bin virtinst bridge-utils
Что где принято хранить:
- /var/lib/libvirt/boot/ — ISO-образы для установки гостевых систем;
- /var/lib/libvirt/images/ — образы жестких дисков гостевых систем;
- /var/log/libvirt/ — тут следует искать все логи;
- /etc/libvirt/ — каталог с файлами конфигурации;
Теперь, когда KVM установлен, создадим нашу первую виртуалку.
Создание первой виртуалки
В качестве гостевой системы я выбрал FreeBSD. Качаем ISO-образ системы:
sudo wget http: // ftp.freebsd.org / path / to / some-freebsd-disk.iso
Управление виртуальными машинами в большинстве случаев производится при помощи утилиты virsh:
Перед запуском виртуалки нам понадобится собрать кое-какие дополнительные сведения.
Смотрим список доступных сетей:
Просмотр информации о конкретной сети (с именем default):
Смотрим список доступных оптимизаций для гостевых ОС:
Итак, теперь создаем виртуальную машину с 1 CPU, 1 Гб RAM и 32 Гб места на диске, подключенную к сети default:
—virt-type =kvm
—name freebsd10
—ram 1024
—vcpus = 1
—os-variant =freebsd8
—hvm
—cdrom = / var / lib / libvirt / boot / FreeBSD- 10.2 -RELEASE-amd64-disc1.iso
—network network =default, model =virtio
—graphics vnc
—disk path = / var / lib / libvirt / images / freebsd10.img, size = 32 , bus =virtio
Вы можете увидеть:
installed. Please install the ‘virt-viewer’ package.
Domain installation still in progress. You can reconnect to the console
to complete the installation process.
Это нормально, так и должно быть.
Затем смотрим свойства виртуалки в формате XML:
Тут приводится наиболее полная информация. В том числе есть, к примеру, и MAC-адрес, который понадобятся нам далее. Пока что находим информацию о VNC. В моем случае:
С помощью любимого клиента (я лично пользуюсь Rammina) заходим по VNC , при необходимости используя SSH port forwarding. Попадаем прямо в инстялятор FreeBSD. Дальше все как обычно — Next, Next, Next, получаем установленную систему.
Основные команды
Давайте теперь рассмотрим основные команды для работы с KVM.
Получение списка всех виртуалок:
Получение информации о конкретной виртуалке:
Запустить виртуалку:
Остановить виртуалку:
Жестко прибить виртуалку (несмотря на название, это не удаление):
Ребутнуть виртуалку:
Склонировать виртуалку:
—file / var / lib / libvirt / images / freebsd10-clone.img
Включить/выключить автозапуск:
sudo virsh autostart —disable freebsd10
Запуск virsh в диалоговом режиме (все команды в диалоговом режиме — как описано выше):
Редактирование свойств виртуалки в XML, в том числе здесь можно изменить ограничение на количество памяти и тд:
Важно! Комментарии из отредактированного XML, к сожалению, удаляются.
Когда виртуалка остановлена, диск тоже можно ресайзить:
sudo qemu-img info / var / lib / libvirt / images / freebsd10.img
Важно! Вашей гостевой ОС, скорее всего, не понравится, что диск внезапно стал больше или меньше. В лучшем случае, она загрузится в аварийном режиме с предложением переразбить диск. Скорее всего, вы не должны хотеть так делать. Куда проще может оказаться завести новую виртуалку и смигрировать на нее все данные.
Резервное копирование и восстановление производятся довольно просто. Достаточно сохранить куда-то вывод dumpxml, а также образ диска, а потом восстановить их. На YouTube удалось найти видео с демонстрацией этого процесса, все и вправду несложно.
Настройки сети
Интересный вопрос — как определить, какой IP-адрес получила виртуалка после загрузки? В KVM это делается хитро. Я в итоге написал такой скрипт на Python :
# virt-ip.py script
# (c) 2016 Aleksander Alekseev
# http://remontka.com/
import sys
import re
import os
import subprocess
from xml . etree import ElementTree
def eprint ( str ) :
print ( str , file = sys . stderr )
if len ( sys . argv ) < 2 :
eprint ( «USAGE: » + sys . argv [ 0 ] + » <domain>» )
eprint ( «Example: » + sys . argv [ 0 ] + » freebsd10″ )
sys . exit ( 1 )
if os . geteuid ( ) != 0 :
eprint ( «ERROR: you shold be root» )
eprint ( «Hint: run `sudo » + sys . argv [ 0 ] + » …`» ) ;
sys . exit ( 1 )
if subprocess . call ( «which arping 2>&1 >/dev/null» , shell = True ) != 0 :
eprint ( «ERROR: arping not found» )
eprint ( «Hint: run `sudo apt-get install arping`» )
sys . exit ( 1 )
domain = sys . argv [ 1 ]
if not re . match ( «^[a-zA-Z0-9_-]*$» , domain ) :
eprint ( «ERROR: invalid characters in domain name» )
sys . exit ( 1 )
domout = subprocess . check_output ( «virsh dumpxml » +domain+ » || true» ,
shell = True )
domout = domout. decode ( ‘utf-8’ ) . strip ( )
if domout == «» :
# error message already printed by dumpxml
sys . exit ( 1 )
doc = ElementTree. fromstring ( domout )
# 1. list all network interfaces
# 2. run `arping` on every interface in parallel
# 3. grep replies
cmd = «(ifconfig | cut -d ‘ ‘ -f 1 | grep -E ‘.’ | » +
«xargs -P0 -I IFACE arping -i IFACE -c 1 {} 2>&1 | » +
«grep ‘bytes from’) || true»
for child in doc. iter ( ) :
if child. tag == «mac» :
macaddr = child. attrib [ «address» ]
macout = subprocess . check_output ( cmd . format ( macaddr ) ,
shell = True )
print ( macout. decode ( «utf-8» ) )
Скрипт работает как с default сетью, так и с bridged сетью, настройку которой мы рассмотрим далее. Однако на практике куда удобнее настроить KVM так, чтобы он всегда назначал гостевым системам одни и те же IP-адреса. Для этого правим настройки сети:
… примерно таким образом:
<range start = ‘192.168.122.2’ end = ‘192.168.122.254’ />
<!— добавляем вот эту строчку: —>
<host mac = ’52:54:00:59:96:00′ name = ‘freebsd10’ ip = ‘192.168.122.184’ />
</dhcp >
После внесения этих правок необходимо выполнить команды :
sudo virsh net-start default
sudo service libvirt-bin restart
Теперь перезагружаем несколько раз гостевую систему и убеждаемся, что она всегда получает адрес 192.168.122.184.
По умолчанию виртуальные машины могут ходить в интернет, а также к ним можно приконнектится из хост-системы. В общем и целом все выглядит так, словно гостевые системы находятся за NAT. На практике же часто бывает куда удобнее иметь bridged сеть. Как она настраивается на хост-системе ранее мы уже рассматривали в заметках Туториал по контейнеризации при помощи LXC и Контейнерная виртуализация при помощи OpenVZ .
После окончания настройки правим конфиг гостевой системы. Находим в нем что-то вроде:
<source network = ‘default’ />
<!— остальное не важно —>
</interface >
… и заменяем на что-то вроде:
<source bridge = ‘br0’ />
<!— прочее оставляем как есть —>
</interface >
Перезагружаем гостевую систему и проверяем, что она получила IP по DHCP от роутера. Если же вы хотите, чтобы гостевая система имела статический IP-адрес, это настраивается как обычно внутри самой гостевой системы.
Программа virt-manager
Вас также может заинтересовать программа virt-manager:
sudo usermod -a -G libvirtd USERNAME
Так выглядит ее главное окно:
Как видите, virt-manager представляет собой не только GUI для виртуалок, запущенных локально. С его помощью можно управлять виртуальными машинами, работающими и на других хостах, а также смотреть на красивые графички в реальном времени. Я лично нахожу особенно удобным в virt-manager то, что не нужно искать по конфигам, на каком порту крутится VNC конкретной гостевой системы. Просто находишь виртуалку в списке, делаешь двойной клик, и получаешь доступ к монитору.
Еще при помощи virt-manager очень удобно делать вещи, которые иначе потребовали бы трудоемкого редактирования XML-файлов и в некоторых случаях выполнения дополнительных команд. Например, переименование виртуальных машин, настройку CPU affinity и подобные вещи. Кстати, использование CPU affinity существенно снижает эффект шумных соседей и влияние виртуальных машин на хост-систему. По возможности используйте его всегда.
Если вы решите использовать KVM в качестве замены VirtualBox, примите во внимание, что хардверную виртуализацию они между собой поделить не смогут. Чтобы KVM заработал у вас на десктопе, вам не только придется остановить все виртуалки в VirtualBox и Vagrant , но и перезагрузить систему. Я лично нахожу KVM намного удобнее VirtualBox, как минимум, потому что он не требует выполнять команду sudo / sbin / rcvboxdrv setup
после каждого обновления ядра, адекватно работает c Unity , и вообще позволяет спрятать все окошки.
Заключение
По традиции, немного ссылок по теме:
В целом, KVM произвел на меня исключительно положительное впечатление. Теперь я не понимаю, зачем все это время я мучился с Vagrant и VirtualBox, когда все уже есть в KVM и сделано куда лучше. Ну, почти. Кое-какие косяки все же имеются. Так, например, в htop гостевой системы вы можете видеть, что утилизируете CPU на 30%, хотя на хост-системе вы утилизируете все 100%. Однако мой опыт работы с виртуальными машинами свидетельствует о том, что такого рода проблемы и прочие шумные соседи возникают всегда, и еще один минорный баг в общем-то не делает в этом плане все сильно хуже.
А используете ли вы KVM и если да, то для чего?
Дополнение: Также вас могут заинтересовать статьи Мой первый опыт использования Proxmox VE и Управление VirtualBox из консоли с помощью vboxmanage .