Установка и настройка KVM в Fedora 30

Подготовка к установке

В данной статье будет кратко написано про установку KVM в Fedora 30 и более детально про последующую настройку сети и взаимодействие гостевых виртуальных машин.

Изучить подробно информацию по работе KVM\QEMU\libvirt можно по различным статьям в рунете или на оф. сайтах. Здесь же вкратце опишу основные моменты.

KVM – Kernel Virtual Machine, open source, является модулем ядра Linux c 2.6.20, разрабатывается Red Hat. Обеспечивает возможность аппаратной виртуализации на базе Intel\AMD.

QEMU – ПО, эмулирующее работу аппаратного оборудования для различных платформ. Может работать и без использования KVM, но обычно используется совместно для достижения большей производительности (QEMU-KVM). При такой связке, KVM, как модуль ядра, выполняет большую часть гостевого кода, продолжая эмулировать остальную часть машины.

Управление KVM происходит благодаря библиотеке libvirt через API, которая включает в себя GUI virt-manager или консольный вариант virsh.

Осталось выполнить несколько команд перед началом.

Для проверки, что CPU (Intel) поддерживает технологию аппаратной виртуализации VT (на выходе должен быть не пустой результат) выполнить:

grep -e 'vmx' /proc/cpuinfo

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

egrep '^flags.*(vmx|svm)' /proc/cpuinfo

Выключить selinux:

setenforce 0

Установка

Установка пакетов QEMU:

dnf install qemu-kvm qemu-img

Установка библиотек (в т.ч. GUI & CLI инструментов управления) для гипервизора и управления:

dnf install virt-manager libvirt libvirt-python libvirt-client 

И обязательные пакеты согласно оф. документации Fedora:

dnf groupinfo virtualization

Group: Virtualization
Group-Id: virtualization
Description: These packages provide a virtualization environment.

Mandatory Packages:
   =virt-install

Default Packages:
   =libvirt-daemon-config-network
   =libvirt-daemon-kvm
   =qemu-kvm
   =virt-manager
   =virt-viewer

Optional Packages:
   guestfs-browser
   libguestfs-tools
   python-libguestfs
   virt-top
dnf install @virtualization

Запуск сервиса libvirt, который управляет виртуализацией (поддерживает не только KVM, но и LXC, OpenVZ, Xen, Vbox, VMWare и пр.) и предоставляет API:

systemctl start libvirtd && systemctl enable libvirtd

Устройство сети

Каждая стандартная установка libvirt обеспечивает возможность подключения к виртуальным машинам на основе NAT. Это так называемая виртуальная сеть по умолчанию. Для проверки, что сеть активна:

virsh net-list --all

Name                 State      Autostart 
-----------------------------------------
default              active     yes

Настройки данной сети в XML:

/usr/share/libvirt/networks/default.xml

libvirt создаёт также мост:

brctl show

bridge name	bridge id		STP enabled	interfaces
virbr0		8000.5254002edac4	yes		virbr0-nic

На хост-машине можно заметить, что создался интерфейс:

virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:2e:da:c4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever

В терминологии libvirt, этот интерфейс называется виртуальным коммутатором(virtual network switch ) для объединения гостевых машин.

NAT

Гостевые машины по умолчанию взаимодействуют с внешним миром через виртуальный сетевой коммутатор, который работает в режиме NAT, используя IP masquerading.

Это означает, что все гостевые машины используют IP-адрес хост-машины для связи с внешним миром. А машины извне (относительно хост-машины) доступа к гостевым не имеют.

Картинка для примера из оф. документации:

Host with a virtual network switch in nat mode and two guests.png

Для работы гостевых виртуальных машин по сети с внешними узлами посредством NAT, libvirt создает правила в iptables в цепочках INPUT, FORWARD, OUTPUT и POSTROUTING + включается форвардинг. По-хорошему, лучше его прописать в sysctl.conf:

net.ipv4.ip_forward = 1

И применить:

sysctl -p

Резюмируя: NAT-forwarding активен по-умолчанию и не требует доп. настройки.

DNS\DHCP

Виртуальному сетевому коммутатору (их может быть > 1) назначается пул адресов, которые будут предоставляться гостям по DHCP. Для этого обычно используется dnsmasq, который автоматом настраивается и запускается для каждого виртуального сетевого коммутатора, который в этом нуждается.

Если dnsmasq уже используется отдельно от libvirt, это может вызвать проблемы, читать тут

Картинка для примера из оф. документации:

Virtual network switch with dnsmasq.jpg

При использовании NAT для гостевых ВМ и необходимости предоставить какой-либо гостевой сервис наружу, т.е. предоставить входящий доступ извне, потребуется пробрасывать порты через iptables хоста:

  • Разрешить трафик в цепочке FORWARD до гостевого узла и порта;
  • Настроить DSTNAT с хост-порта до нужного гостевого узла.
/sbin/iptables -D FORWARD -o virbr0 -d  $GUEST_IP --dport $GUEST_PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT

Routed mode

Помимо NAT, есть ещё режим маршрутизации (т.н. роутинг), посредством которого также можно настроить взаимодействие гостей с внешними узлами.

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

Для того, чтобы знать, куда передавать трафик, виртуальный коммутатор смотрит IP-адреса в каждом пакете.

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

Картинка для примера из оф. документации:

Virtual network switch in routed mode.png

Резюмируя: routed forwarding может затребовать доп. настройки на вышестоящем оборудовании и более сложен в настройке.

Изолированный режим

В данном режиме гости могут общаться только друг с другом и хост-машиной и гарантированно изолированы от внешнего мира.

Картинка для примера из оф. документации:

Virtual network switch in isolated mode.png

Настройка сетевого моста

Как было сказано ранее, NAT forwarding (aka “virtual networks”) доступен по-умолчанию из коробки во всех дистрибутивах и не требует настройки. Поэтому после того, как будет установлена и запущена гостевая машина, будет выход во внешний мир, но не будет обратного доступа напрямую. Такая конфигурация удобна для быстрого развертывания.

Для того, чтобы гость имел доступ до узлов в хост-сети и наоборот, применяется Bridged networking (aka “shared physical device”), при этом никакого NAT уже не будет, т.к. мост работает на 2 уровне OSI.

Сетевой мост – это устройство на канальном уровне, которое пересылает трафик между сетями на основе MAC-адресов и поэтому называется устройством второго уровня. Мост принимает решения о пересылке на основе таблиц MAC-адресов, которые он создает, узнавая, какие хосты подключены к каждой сети.

К сожалению, беспроводные интерфейсы не могут быть подключены к хост-мосту Linux, это нужно иметь ввиду при настройке.

Также, если после попытки использовать интерфейс моста вы обнаружите, что ваше сетевое соединение перестает работать, возможно, вышестоящий маршрутизатор/коммутатор блокирует «неавторизованные коммутаторы» в сети (например, путем обнаружения BPDU-пакетов).

Основная идея моста в том, что нужно будет:

  • создать интерфейс типа мост с именем br0 для хоста, который будет master-интерфейсом;
  • создать slave-интерфейс, в который будет подключен enp1s0 (текущий интерфейс до настройки моста);
  • отключить enp1s0.

С теорией закончили. Здесь для каждых дистрибутивов будут разные настройки. Напоминаю, в данном случае производится настройка относительно Fedora 30 c использованием NetworkManager (NM).

Для начала нужно убедиться, что NM запущен:

systemctl status NetworkManager
● NetworkManager.service - Network Manager
   Loaded: loaded (/usr/lib/systemd/system/NetworkManager.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2019-10-07 11:30:49 MSK; 2 weeks 1 days ago

А теперь непосредственно создание нового соединения типа мост с именем br0:

nmcli con add ifname br0 type bridge con-name br0

Протокол связующего дерева (STP) для отлова петель в сети включен по-умолчанию при создании моста.

И создание slave, в который сразу же подключается интерфейс хост-машины enp1s0, а br0 назначается master`ом:

nmcli con add type bridge-slave ifname enp1s0 master br0

Теперь, если посмотреть список сетевых соединений, можно увидеть, что новый интерфейс br0 создан, но ещё не активен:

$ nmcli con show

NAME                   UUID                                  TYPE             DEVICE
wired-direct           73157bec-12fb-42d0-98c4-f4576742e095  802-3-ethernet   enp1s0
br0                    892869fe-f8ac-4f17-ace9-b8aeeeee61a0  bridge           --
bridge-slave-enp0s25   33ee8c62-48d8-4789-97df-604c479b6860  802-3-ethernet   --

А теперь нужно отключить интерфейс enp1s0 и включить br0:

nmcli con down 73157bec-12fb-42d0-98c4-f4576742e095 && nmcli con up br0

Для вступления изменений в силу, перезагрузить сеть:

systemctl restart NetworkManager.service

Если посмотреть вывод команды ip a, можно увидеть, что IP-адрес теперь назначен новому интерфейсу br0, а enp1s0 уже без IP-адреса. Подразумевается, что использовался DHCP. Для того, чтобы мосту назначать статический адрес, нужно указывать соответствующий флаг при создании моста (manual).

$ nmcli con

NAME                  UUID                                  TYPE            DEVICE
br0                   892869fe-f8ac-4f17-ace9-b8aeeeee61a0  bridge          br0
bridge-slave-enp0s25  33ee8c62-48d8-4789-97df-604c479b6860  802-3-ethernet  enp0s25

Создание сети для libvirt

Итак, хост-машина настроена теперь на выход в сеть через интерфейс сетевого моста br0 (можно посмотреть ip r). Теперь нужно создать сетевой интерфейс в libvirt для гостевых машин:

cat > bridge.xml <<EOF
<network>
    <name>host-bridge</name>
    <forward mode="bridge"/>
    <bridge name="br0"/>
</network>
EOF

Далее нужно добавить новую сеть, запустить и включить автостарт:

virsh net-define bridge.xml && virsh net-start host-bridge && virsh net-autostart host-bridge

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

Источники

Ваш комментарий будет первым

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *