Глава 3. Построение сетей KVM при помощи libvirt
Содержание
В этой главе мы намерены рассмотреть такие вопросы:
-
Мост Linux
-
Open vSwitch
-
Настройка сетевой среды пересылки NAT
-
Настройка сетевой среды с мостом
-
Настройка сквозной сетевой среды PCIe
-
Манипулирование интерфесами сетевой среды
В libvirt мы можем определять различные типы сетевых сред для наших гостевых KVM при помощи уже известного нам
синтаксиса определений XML и инструментов пространства пользователя virsh
и virt-install
. В этой главе мы намерены развернуть три типа сетевых сред,
изучить соответствующий сетевой формат XML и рассмотреть примеры того как определять виртуальные интерфейсы для
своих экземпляров KVM и как ими манипулировать.
Чтобы иметь возможность подключать виртуальные машины к ОС своего хоста или друг к другу, мы собираемся воспользоваться имеющимся мостом Linux и демонами Open vSwitch (OVS), инструментами пространства пользователя и модулями ядра. Обе технологии построения программного моста великолепны при создании Software-defined Networking (SDN, программно определяемой сетевой среды) различной сложности неким согласованным и простым в обращении образом. И мост Linux, и OVS, оба действуют как мост/ коммутатор, к которым могут подключаться имеющиеся у наших гостевых KVM виртуальные интерфейсы.
Имея это в виду, давайте начнём узнавать подробности программных мостов в Linux.
Мост Linux является неким программно определяемым устройством 2 уровня, который предоставляет необходимую функциональность какого- то физического устройства моста. Он способен переправлять кадры между гостевыми KVM, ОС своего хоста и виртуальными машинами, запущенными на прочих серверах или в иных сетевых средах. Мост Linux состоит из двух компонентов - инструмента администрирования пространства пользователя, который мы намерены применять в данном рецепте и какого- то модуля ядра, который и выполняет всю работу по соединению воедино множества сегментов Ethernet. Каждый создаваемый нами программный мост может иметь некое число подключённых к нему портов, где и происходит переадресация сетевого обмена в обоих направлениях. При создании экземпляров KVM мы можем подключать их виртуальные интерфейсы, которые ассоциированы с таким мостом, что аналогично вставке какого- то сетевого кабеля от некой NIC сервера в устройство моста/ коммутатора. Выступая в роли устройства 2 уровня, имеющийся мост Linux работает с MAC адресами и выполняет сопровождение некоторой структуры ядра по отслеживанию портов и ассоциированных MAC адресов в виде некоей таблицы Content Addressable Memory (CAM, ассоциативной памяти).
В данном рецепте мы намерены создать некий новый мост Linux и воспользоваться утилитой
brctl
для манипуляций с ним.
В данном рецепте нам потребуется следующее:
-
Современное ядро Linux с включёнными возможностями
802.1d Ethernet
.Для проверки того скомпилировано ли ваше ядро с такой функциональностью или выставлены ли модули ядра, исполните такие команды:
root@kvm:~# cat /boot/config-`uname -r` | grep -i bridg # PC-card bridges CONFIG_BRIDGE_NETFILTER=y CONFIG_NF_TABLES_BRIDGE=m CONFIG_BRIDGE_NF_EBTABLES=m CONFIG_BRIDGE_EBT_BROUTE=m CONFIG_BRIDGE_EBT_T_FILTER=m CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_802_3=m CONFIG_BRIDGE_EBT_AMONG=m CONFIG_BRIDGE_EBT_ARP=m CONFIG_BRIDGE_EBT_IP=m CONFIG_BRIDGE_EBT_IP6=m CONFIG_BRIDGE_EBT_LIMIT=m CONFIG_BRIDGE_EBT_MARK=m CONFIG_BRIDGE_EBT_PKTTYPE=m CONFIG_BRIDGE_EBT_STP=m CONFIG_BRIDGE_EBT_VLAN=m CONFIG_BRIDGE_EBT_ARPREPLY=m CONFIG_BRIDGE_EBT_DNAT=m CONFIG_BRIDGE_EBT_MARK_T=m CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_LOG=m # CONFIG_BRIDGE_EBT_ULOG is not set CONFIG_BRIDGE_EBT_NFLOG=m CONFIG_BRIDGE=m CONFIG_BRIDGE_IGMP_SNOOPING=y CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_SSB_B43_PCI_BRIDGE=y CONFIG_DVB_DDBRIDGE=m CONFIG_EDAC_SBRIDGE=m # VME Bridge Drivers root@kvm:~#
-
Собственно модуль ядра
bridge
.Для проверки того что этот модуль загружен и для получения дополнительной информации о его версии и свойствах исполните такие команды:
root@kvm:~# lsmod | grep bridge bridge 110925 0 stp 12976 2 garp,bridge llc 14552 3 stp,garp,bridge root@kvm:~# root@kvm:~# modinfo bridge filename: /lib/modules/3.13.0-107-generic/kernel/net/bridge/bridge.ko alias: rtnl-link-bridge version: 2.3 license: GPL srcversion: 49D4B615F0B11CA696D8623 depends: stp,llc intree: Y vermagic: 3.13.0-107-generic SMP mod_unload modversions signer: Magrathea: Glacier signing key sig_key: E1:07:B2:8D:F0:77:39:2F:D6:2D:FD:D7:92:BF:3B:1D:BD:57:0C:D8 sig_hashalgo: sha512 root@kvm:~#
-
Пакет
bridge-utils
, который предоставляет необходимые инструменты для создания моста Linux и манипуляции им. -
Возможность создания новых гостей KVM при помощи libvirt или соответствующих утилит QEMU или некого имеющегося экземпляра KVM из наших предыдущих глав.
Чтобы создавать, перечислять и манипулировать новым мостом, выполните следующие шаги:
-
Установите необходимый пакет моста Linux, если его ещё нет:
root@kvm:~# apt install bridge-utils
-
Постройте новый экземпляр KVM при помощи сырого образа из нашего рецепта Главы 1 Установка пользовательской ОС в образ при помощи debootstrap если вы не читаете эту книгу от корки до корки:
root@kvm:~# virt-install --name kvm1 --ram 1024 --disk path=/tmp/debian.img,format=raw --graphics vnc,listen=146.20.141.158 --noautoconsole --hvm --import Starting install... Creating domain... | 0 B 00:00 Domain creation completed. You can restart your domain by running: virsh --connect qemu:///system start kvm1 root@kvm:~#
-
Перечислите все доступные устройства мостов:
root@kvm:~# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.fe5400559bd6 yes vnet0 root@kvm:~#
-
Выключите свой виртуальный мост, удалите его и убедитесь в его удалении:
root@kvm:~# ifconfig virbr0 down root@kvm:~# brctl delbr virbr0 root@kvm:~# brctl show bridge name bridge id STP enabled interfaces root@kvm:~#
-
Создайте некий новый мост и поднимите его:
root@kvm:~# brctl addbr virbr0 root@kvm:~# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.000000000000 no root@kvm:~# ifconfig virbr0 up root@kvm:~#
-
Назначьте мосту некий IP адрес:
root@kvm:~# ip addr add 192.168.122.1 dev virbr0 root@kvm:~# ip addr show virbr0 39: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default link/ether 32:7d:3f:80:d7:c6 brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/32 scope global virbr0 valid_lft forever preferred_lft forever inet6 fe80::307d:3fff:fe80:d7c6/64 scope link valid_lft forever preferred_lft forever root@kvm:~#
-
Перечислите все сетевые интерфейсы ОС своего хоста:
root@kvm:~# ip a s | grep vnet 38: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500 root@kvm:~#
-
Добавьте имеющийся виртуальный интерфейс
vnet0
в свой мост:root@kvm:~# brctl addif virbr0 vnet0 root@kvm:~# brctl show virbr0 bridge name bridge id STP enabled interfaces virbr0 8000.fe5400559bd6 no vnet0 root@kvm:~#
-
Включите в своём мосте Spanning Tree Protocol (STP, протокол связующего дерева):
root@kvm:~# brctl stp virbr0 on root@kvm:~# brctl showstp virbr0 virbr0 bridge id 8000.fe5400559bd6 designated root 8000.fe5400559bd6 root port 0 path cost 0 max age 20.00 bridge max age 20.00 hello time 2.00 bridge hello time 2.00 forward delay 15.00 bridge forward delay 15.00 ageing time 300.00 hello timer 0.26 tcn timer 0.00 topology change timer 0.00 gc timer 90.89 flags vnet0 (1) port id 8001 state forwarding designated root 8000.fe5400559bd6 path cost 100 designated bridge 8000.fe5400559bd6 message age timer 0.00 designated port 8001 forward delay timer 0.00 designated cost 0 hold timer 0.00 flags root@kvm:~#
-
Из экземпляра KVM поднимите интерфейс, запросите IP- адрес и проверьте подключение к ОС его хоста:
root@debian:~# ifconfig eth0 up root@debian:~# dhclient eth0 root@debian:~# ip a s eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:55:9b:d6 brd ff:ff:ff:ff:ff:ff inet 192.168.122.92/24 brd 192.168.122.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe55:9bd6/64 scope link valid_lft forever preferred_lft forever root@debian:~# root@debian:~# ping 192.168.122.1 -c 3 PING 192.168.122.1 (192.168.122.1) 56(84) bytes of data. 64 bytes from 192.168.122.1: icmp_seq=1 ttl=64 time=0.276 ms 64 bytes from 192.168.122.1: icmp_seq=2 ttl=64 time=0.226 ms 64 bytes from 192.168.122.1: icmp_seq=3 ttl=64 time=0.259 ms --- 192.168.122.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.226/0.253/0.276/0.027 ms root@debian:~#
После того как мы впервые установили свой демон libvirt
несколько моментов
произошло в автоматическом режиме:
-
Был создан некий новый мост Linux с теми названием и IP адресом, которые определены в файле настройки
/etc/libvirt/qemu/networks/default.xml
-
Была запущена служба
dnsmasq
с какой- то конфигурацией, определённой в файле/var/lib/libvirt/dnsmasq/default.conf
Давайте изучим установленные по умолчанию настройки моста libvirt
:
root@kvm:~# cat /etc/libvirt/qemu/networks/default.xml
<network>
<name>default</name>
<bridge name="virbr0"/>
<forward/>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.122.2" end="192.168.122.254"/>
</dhcp>
</ip>
</network>
root@kvm:~#
Именно эту сетевую среду по умолчанию создал для нас libvirt, определив соответствующие название моста, адрес IP и тот диапазон IP, который используется запущенным сервером DHCP. Позднее в этой главе мы намерены обсудить более подробно сетевую среду libvirt; тем не менее мы показали её здесь чтобы помочь вам понять откуда появились все наши адреса IP и само название моста.
Мы можем обнаружить, что в ОС нашего хоста исполняется некий сервер DHCP и просмотреть его файл настройки с помощью такой команды:
root@kvm:~# pgrep -lfa dnsmasq
38983 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf
root@kvm:~# cat /var/lib/libvirt/dnsmasq/default.conf
##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
##OVERWRITTEN AND LOST. Changes to this configuration should be made using:
## virsh net-edit default
## or other application using the libvirt API.
##
## dnsmasq conf file created by libvirt
strict-order
user=libvirt-dnsmasq
pid-file=/var/run/libvirt/network/default.pid
except-interface=lo
bind-dynamic
interface=virbr0
dhcp-range=192.168.122.2,192.168.122.254
dhcp-no-override
dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases
dhcp-lease-max=253
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
root@kvm:~#
В приведённом выше файле настроек отметим как устанавливается соответствие диапазона IP адресов для имеющейся службы DHCP и самого названия нашего виртуального моста, которые настроены в файле сетевой среды libvirt установок по умолчанию, который мы рассматривали выше.
Имея всё это в виду, давайте пройдём по всем выполненным нами ранее шагам.
На шаге 1 мы установили инструментарий пространства пользователя brctl
, который
мы будем применять для создания, настройки и инспектирования конфигурации своего моста Linux в своём ядре Linux.
На шаге 2 мы предоставили некий новый экземпляр KVM при помощи некого индивидуального сырого образа, содержащего необходимую гостевую ОС. Это шаг не требуется если вы выполняли все рецепты в наших предыдущих главах.
На шаге 3 мы вызвали свою утилиту bridge
для перечисления всех доступных
устройств моста. Из полученного вывода мы можем обнаружить что в настоящий момент у нас имеется один мост с названием
virbr0
, который был автоматически создан libvirt. Отметим, что в колонке
интерфейса мы можем видеть интерфейс vnet0
. Именно эта виртуальная NIC выставляется
в ОС нащего хоста при запуске нами соответствующего экземпляра KVM. Это означает, что наша виртуальная машина подключена
к мосту своего хоста.
На шаге 4 мы вначале отключаем имеющийся мост для его удаления, а затем снова применяем команду
brctl
для унчтожения этого моста и проверки того что он более не присутствует
в ОС нашего хоста.
На шаге 5 мы повторно создаём необходимый мост и опять поднимаем его. Мы делаем это чтобы показать шаги, необходимые при создании какого- то нового моста.
На шаге 6 мы повторно назначаем тот же самый IP адрес своему мосту и просматриваем его.
На шагах 7 и 8 мы перечисляем все виртуальные интерфейсы в ОС своего хоста. Поскольку у нас имеется в настоящий момент
только одна гостевая KVM, которая исполняется в нашем сервере, мы видим всего один виртуальный интерфейс, то есть
vnet0
. Затем мы переходим к добавлению/ подключению своего виртуального NIC
к созданному мосту.
На шаге 9 мы включаем STP в своём мосте. STP является неким протоколом 2 уровня, который помогает нам предотвращать зацикливания в сетевой среде в случае когда у нас имеются избыточные сетевые пути. Это в особенности полезно при сетевых топологиях более крупного масштаба и более сложных, когда множество мостов соединяются друг с другом.
Наконец, на шаге 10 мы подключаемся к своей гостевой KVM при помощи консоли, перечисляем настройки её сетевых интерфейсов
и убеждаемся что мы способны выполнить пинг к имеющемуся в ОС её хоста мосту. Для этого нам требуется поднять этот сетевой
интерфейс внутри своего гостя с помощью ifconfig eth0 up
, затем получить некий
IP адрес при помощи команды dhclient eth0
от того сервера
dnsmasq
, который запущен на нашем хосте.
Существует ещё ряд полезных команд, которые могут применяться для имеющегося моста Linux.
Мы уже знаем что некий мост выполняет переадресацию кадров на основе тех MAC адресов, которые содержатся внутри него. Для изучения имеющейся таблицы MAC адресов, известных нашему мосту, исполните такую команду:
root@kvm:~# brctl showmacs virbr0
port no mac addr is local? ageing timer
1 52:54:00:55:9b:d6 no 268.02
1 fe:54:00:55:9b:d6 yes 0.00
root@kvm:~#
В своём предыдущем выводе мы можем обнаружить что наш мост записал в свой порт два только два MAC адреса. Самая первая запись является нелокальным адресом и относится к тому сетевому интерфейсу, который находится внутри экземпляров KVM. Мы можем подтвердить это подключившись к своей гостевой KVM следующим образом:
root@kvm:~# virsh console kvm1
Connected to domain kvm1
Escape character is ^]
root@debian:~# ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:55:9b:d6 brd ff:ff:ff:ff:ff:ff
inet6 fe80::5054:ff:fe55:9bd6/64 scope link
valid_lft forever preferred_lft forever
root@debian:~#
Второй MAC адрес является адресом самого нашего моста и его MAC адрес имеющегося виртуального интерфейса, относящегося к имеющейся виртуальной машине, который выставляется ОС его хоста. Чтобы убедиться в этом исполните такую команду:
root@kvm:~# ifconfig | grep "fe:54:00:55:9b:d6"
virbr0 Link encap:Ethernet HWaddr fe:54:00:55:9b:d6
vnet0 Link encap:Ethernet HWaddr fe:54:00:55:9b:d6
root@kvm:~#
Когда наш мост видит некий кадр в одном из своих портов, он записывает значение времени, затем после того как на протяжении установленного промежутка времени он не наблюдает тот же самый MAC адрес снова, он удалит эту запись из своей таблицы CAM. Мы можем устанавливать в секундах этот временной предел до того как истечёт срок действия записи MAC адреса выполняя такую команду:
root@kvm:~# brctl setageing virbr0 600
root@kvm:~#
Команда brctl
хорошо документирована; чтобы перечислить все доступные субкоманды,
запустите её без параметров:
root@kvm:~# brctl
Usage: brctl [commands]
commands:
addbr <bridge> add bridge
delbr <bridge> delete bridge
addif <bridge> <device> add interface to bridge
delif <bridge> <device> delete interface from bridge
hairpin <bridge> <port> {on|off} turn hairpin on/off
setageing <bridge> <time> set ageing time
setbridgeprio <bridge> <prio> set bridge priority
setfd <bridge> <time> set bridge forward delay
sethello <bridge> <time> set hello time
setmaxage <bridge> <time> set max message age
setpathcost <bridge> <port> <cost> set path cost
setportprio <bridge> <port> <prio> set port priority
show [ <bridge> ] show a list of bridges
showmacs <bridge> show a list of mac addrs
showstp <bridge> show bridge stp info
stp <bridge> {on|off} turn stp on/off
root@kvm:~#
Большинство дистрибутивов Linux пакуют в свой состав обсуждаемую утилиту brctl
и именно её мы и применяем в данном рецепте. Однако, чтобы воспользоваться самой последней версией или если
пакет не доступен в вашем дистрибутиве, мы можем построить эту утилиту из исходного кда клонировав её проект с
git
, а затем выполнив настройку и скомпилировав её:
root@kvm:~# cd /usr/src/
root@kvm:/usr/src# apt-get update && apt-get install build-essential automake pkg-config git
root@kvm:/usr/src# git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/bridge-utils.git
Cloning into 'bridge-utils'...
remote: Counting objects: 654, done.
remote: Total 654 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (654/654), 131.72 KiB | 198.00 KiB/s, done.
Resolving deltas: 100% (425/425), done.
Checking connectivity... done.
root@kvm:/usr/src# cd bridge-utils/
root@kvm:/usr/src/bridge-utils# autoconf
root@kvm:/usr/src/bridge-utils# ./configure && make && make install
root@kvm:/usr/src/bridge-utils# brctl --version
bridge-utils, 1.5
root@kvm:/usr/src/bridge-utils#
В своём предыдущем выводе мы можем наблюдать что вначале мы клонировали имеющийся для проекта
bridge-utils
репозиторий git
,
а потом скомпилировали полученный исходный код.
В хосте RedHat/CentOS этот процесс аналогичный:
[root@centos ~]# cd /usr/src/
[root@centos src]#
[root@centos src]# yum groupinstall "Development tools"
[root@centos src]# git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/bridge-utils.git
Cloning into 'bridge-utils'...
remote: Counting objects: 654, done.
remote: Total 654 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (654/654), 131.72 KiB | 198.00 KiB/s, done.
Resolving deltas: 100% (425/425), done.
Checking connectivity... done.
[root@centos src]# cd bridge-utils
[root@centos bridge-utils]# autoconf
[root@centos bridge-utils]# ./configure && make && make install
[root@centos bridge-utils]# brctl --version
bridge-utils, 1.5
[root@centos bridge-utils]#
OVS является другим программно определяемым устройством моста/ коммутатора, который может применяться для создания различных виртуальных сетевых топологий и подключать к ним экземпляры KVM. OVS может использоваться вместо моста Linux и предоставляет расширенный набор свойств, включающих в свой состав политики маршрутизации, ACL (Access Control Lists, списки контролья доступа) политики QoS (Quality of Service, качества обслуживания), отслеживание сетевого обмена, управление потоком, выставление тегов VLAN, туннелирование GRE и многое другое.
В данном рецепте мы намереваемся установить, настроить и применить мост OVS для подключения некоего экземпляра KVM к ОС его хоста аналогично тому как мы это делали в своём предыдущем рецепте с помощью моста Linux.
Для работы с этим рецептом нам понадобятся гарантии следующего:
-
Мост Linux удалён, в случае его наличия, а OVS установлен
-
У нас имеется запущенным по крайней мере один экземпляр KVM
Для создания некого нового моста OVS и подключения имеющегося виртуального интерфейса некой гостевой KVM следуйте таким шагам:
-
Если он имеется, удалите существующий мост Linux:
root@kvm:~# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.fe5400559bd6 yes vnet0 root@kvm:~# ifconfig virbr0 down root@kvm:~# brctl delbr virbr0 root@kvm:~# brctl show bridge name bridge id STP enabled interfaces root@kvm:~#
Совет В некоторых дистрибутивах Linux помогает выгрузка соответствующего модуля ядра для моста KVM перед использованием OVS. Чтобы сделать это выполните
root@kvm:/usr/src# modprobe -r bridge
. -
Установите необходимый пакет OVS в Ubuntu:
root@kvm:~# apt-get install openvswitch-switch ... Setting up openvswitch-common (2.0.2-0ubuntu0.14.04.3) ... Setting up openvswitch-switch (2.0.2-0ubuntu0.14.04.3) ... openvswitch-switch start/running ... root@kvm:~#
-
Убедитесь что соответствующие процессы OVS исполняются:
root@kvm:~# pgrep -lfa switch 22255 ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/run/openvswitch/db.sock --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert --no-chdir --log-file=/var/log/openvswitch/ovsdb-server.log --pidfile=/var/run/openvswitch/ovsdb-server.pid --detach --monitor 22264 ovs-vswitchd: monitoring pid 22265 (healthy) 22265 ovs-vswitchd unix:/var/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall --no-chdir --log-file=/var/log/openvswitch/ovs-vswitchd.log --pidfile=/var/run/openvswitch/ovs-vswitchd.pid --detach --monitor root@kvm:~#
-
Проверьте загрузку необходимого модуля ядра OVS:
root@kvm:~# lsmod | grep switch openvswitch 70989 0 gre 13796 1 openvswitch vxlan 37611 1 openvswitch libcrc32c 12644 1 openvswitch root@kvm:~#
-
Перечислите все доступные коммутаторы OVS:
root@kvm:~# ovs-vsctl show e5164e3e-7897-4717-b766-eae1918077b0 ovs_version: "2.0.2" root@kvm:~#
-
Создайте некий новый коммутатор OVS:
root@kvm:~# ovs-vsctl add-br virbr1 root@kvm:~# ovs-vsctl show e5164e3e-7897-4717-b766-eae1918077b0 Bridge "virbr1" Port "virbr1" Interface "virbr1" type: internal ovs_version: "2.0.2" root@kvm:~#
-
Добавьте имеющийся интерфейс исполняемого экземпляра KVM в созданный коммутатор OVS:
root@kvm:~# ovs-vsctl add-port virbr1 vnet0 root@kvm:~# ovs-vsctl show e5164e3e-7897-4717-b766-eae1918077b0 Bridge "virbr1" Port "virbr1" Interface "virbr1" type: internal Port "vnet0" Interface "vnet0" ovs_version: "2.0.2" root@kvm:~#
-
Настройте IP адрес самого коммутатора OVS:
root@kvm:~# ip addr add 192.168.122.1/24 dev virbr1 root@kvm:~# ip addr show virbr1 41: virbr1: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default link/ether b2:52:e0:73:89:4e brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 scope global virbr1 valid_lft forever preferred_lft forever inet6 fe80::b0a8:c2ff:fed4:bb3f/64 scope link valid_lft forever preferred_lft forever root@kvm:~#
-
Настройте некий IP адрес внутри своей гостевой KVM и проверьте связь с ОС её хоста (если ваш образ не имеет настроенного доступа к консоли, подключитесь к нему при помощи VNC:
root@debian:~# ifconfig eth0 up && ip addr add 192.168.122.210/24 dev eth0 root@debian:~# ip addr show eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:55:9b:d6 brd ff:ff:ff:ff:ff:ff inet 192.168.122.210/24 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe55:9bd6/64 scope link valid_lft forever preferred_lft forever root@debian:~# ping 192.168.122.1 PING 192.168.122.1 (192.168.122.1) 56(84) bytes of data. 64 bytes from 192.168.122.1: icmp_seq=1 ttl=64 time=0.711 ms 64 bytes from 192.168.122.1: icmp_seq=2 ttl=64 time=0.394 ms 64 bytes from 192.168.122.1: icmp_seq=3 ttl=64 time=0.243 ms ^C --- 192.168.122.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2001ms rtt min/avg/max/mdev = 0.243/0.449/0.711/0.195 ms root@debian:~#
Для упрощения нашей установки и во избежание конфликтов будет благоразумно вначале удалить имеющийся мост Linux, прежде чем создавать некий новый OVS. На 1 шаге мы удаляем имеющийся мост и опционально выгружаем его модуль ядра.
На шаге 2 мы устанавливаем пакет OVS, который также запускает основной необходимый демон OVS
ovs-vswitchd
, который отвечает за создание необходимых мостов/ коммутаторов и
их изменение в ОС данного хоста.
На шаге 4 мы проверяем что модуль ядра OVS загружен, а на шаге 5 мы перечисляем все доступные коммутаторы OVS в данном хосте.
На шагах 6 и 7 мы создаём некий новый коммутатор OVS и добавляем имеющийся виртуальный интерфейс KVM в этот коммутатор.
Тот процесс сервера ovsdb
, который также был запущен после установки основного
пакета, и который мы видели на шаге 3, является неким механизмом базы данных, который применяет
RPC
(Remote Procedure Calls) JSON для взаимодействия со своим
основным демоном OVS. Данный процесс сервера ovsdb
запоминает информацию, например,
относительно потоков, портов и QoS
своего коммутатора, чтобы упоминуть хотя бы
некоторую из возможной. Вы можете опрашивать эту базу данных исполняя такую команду:
root@kvm:~# ovsdb-client list-dbs
Open_vSwitch
root@kvm:~# ovsdb-client list-tables
Table
-------------------------
Port
Manager
Bridge
Interface
SSL
IPFIX
Open_vSwitch
Queue
NetFlow
Mirror
QoS
Controller
Flow_Table
sFlow
Flow_Sample_Collector_Set
root@kvm:~# ovsdb-client dump Open_vSwitch
...
Port table
_uuid bond_downdelay bond_fake_iface bond_mode bond_updelay external_ids fake_bridge interfaces lacp mac name other_config qos statistics status tag trunks vlan_mode
------------------------------------ -------------- --------------- --------- ------------ ------------ ----------- -------------------------------------- ---- --- -------- ------------ --- ---------- ------ --- ------ ---------
9b4b743d-66b2-4779-9dd8-404b3aa55e18 0 false [] 0 {} false [e7ed4e2b-a73c-46c7-adeb-a203be56587c] [] [] "virbr1" {} [] {} {} [] [] []
f2a033aa-9072-4be3-808e-6e0fce67ce7b 0 false [] 0 {} false [86a10eed-698f-4ccc-b3b7-dd20c13e3ee3] [] [] "vnet0" {} [] {} {} [] [] []
...
root@kvm:~#
Отметим, что в нашем предыдущем выводе теперь отображены эти новые коммутатор
virbr1
и порт vnet0
когда мы опрашиваем имеющуюся базу данных OVS.
На шагах 8 и 9 мы назначаем IP адреса созданному коммутатору OVS и имеющейся гостевой KVM и проверяем что мы способны достигать полученный мост хоста изнутри своей виртуальной машины.
OVS является достаточно сложным программно определяемым коммутатором; в этом рецепте мы только чиркнули по его поверхности. В следующих нескольких рецептах мы можем применять как мост Linux, так и OVS с основными изменениями в настройках, на которые мы будем указывать по ходу действия.
Для удаления имеющегося виртуального интерфейса KVM из соответствующего коммутатора OVS выполните такую команду:
root@kvm:~# ovs-vsctl del-port virbr1 vnet0
root@kvm:~#
Чтобы полностью удалить имеющийся коммутатор OVS исполните такую команду:
root@kvm:~# ovs-vsctl del-br virbr1 && ovs-vsctl show
e5164e3e-7897-4717-b766-eae1918077b0
ovs_version: "2.0.2"
root@kvm:~#
Замечание | |
---|---|
Для получения дополнительных сведений относительно OVS посетите, пожалуйста веб сайт проекта. |
После своего запуска, libvirt
создаёт некую сетевую среду по умолчанию в
своём файле настроек /etc/libvirt/qemu/networks/default.xml
. При построении
какой- то новой KVM без определения каких бы то ни было новых сетевых параметров, она будет использовать такие
настройки по умолчанию для взаимодействия с ОС своего хоста и прочими гостями, а также с сетевыми средами. Устанавливаемая
по умолчанию сетевая среда libvirt
применяет метод
NAT
(Network Address Translation, трансляции сетевых адресов).
NAT предоставляет соответствие одного IP адреса другому, изменяя имеющийся IP адрес в самом заголовке данной IP дейтаграммы
пакета. Это в особенности полезно когда наш хост предоставляет один IP адрес, позволяющий множеству гостей в одном и том
же хосте применять этот адрес для установления исходящих соединений. Адреса таких виртуальных машин по существу
транслируются чтобы проявляться как IP адрес этой машины хоста.
Сетевая среда переадресации по умолчанию определяет и настраивает некий мост Linux для подключения к нему имеющихся гостей. В данном рецепте мы собираемся создать некую новую сеть NAT и подключить к ней свою гостевую KVM.
В данном рецепте нам понадобится следующее:
-
Некий хост Linux с установленным
libvirt
и его запущенным демоном. -
Установленные в ОС рассматриваемого хоста пакеты
iptables
иiproute2
. Если вы устанавливалиlibvirt
из некого пакета, имеются шансы что этиiptables
иiproute2
уже установлены, как зависимости самого пакетаlibvirt
. Если же вы строилиlibvirt
из исходного кода, вам может потребоваться установить их вручную. -
Исполняемые экземпляры KVM.
Для настройки некоей новой сетевой среды NAT и подключения к ней какого- то экземпляра KVM выполните следующее:
-
Перечислите все доступные сети:
root@kvm:~# virsh net-list --all Name State Autostart Persistent ---------------------------------------------------------- default active yes yes root@kvm:~#
-
Выдайте дамп имеющихся установок вашей сети по умолчанию:
root@kvm:~# virsh net-dumpxml default <network connections='1'> <name>default</name> <uuid>2ab5d22c-5928-4304-920e-bc43b8731bcf</uuid> <forward mode='nat'> <nat> <port start='1024' end='65535'/> </nat> </forward> <bridge name='virbr0' stp='on' delay='0'/> <ip address='192.168.122.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.122.2' end='192.168.122.254'/> </dhcp> </ip> </network> root@kvm:~#
-
Сравните это с файлом определения XML для сети по умолчанию:
root@kvm:~# cat /etc/libvirt/qemu/networks/default.xml <network> <name>default</name> <bridge name="virbr0"/> <forward/> <ip address="192.168.122.1" netmask="255.255.255.0"> <dhcp> <range start="192.168.122.2" end="192.168.122.254"/> </dhcp> </ip> </network> root@kvm:~#
-
Перечислите все запущенные в вашем хосте экземпляры:
root@kvm:~# virsh list --all Id Name State ---------------------------------------------------- 3 kvm1 running root@kvm:~#
-
Убедитесь что ваши экземпляры KVM подключены к установленному по умолчанию мосту Linux:
root@kvm:~# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.fe5400559bd6 yes vnet0 root@kvm:~#
-
Создайте некое новое определение сети NAT:
root@kvm:~# cat nat_net.xml <network> <name>nat_net</name> <bridge name="virbr1"/> <forward/> <ip address="10.10.10.1" netmask="255.255.255.0"> <dhcp> <range start="10.10.10.2" end="10.10.10.254"/> </dhcp> </ip> </network> root@kvm:~#
-
Определите эту новую сетевую среду:
root@kvm:~# virsh net-define nat_net.xml Network nat_net defined from nat_net.xml root@kvm:~# virsh net-list --all Name State Autostart Persistent ---------------------------------------------------------- default active yes yes nat_net inactive no yes root@kvm:~#
-
Запустите эту новую сетевую среду и установите её автоматический старт:
root@kvm:~# virsh net-start nat_net Network nat_net started root@kvm:~# virsh net-autostart nat_net Network nat_net marked as autostarted root@kvm:~# virsh net-list Name State Autostart Persistent ---------------------------------------------------------- default active yes yes nat_net active yes yes root@kvm:~#
-
Получите дополнительные сведения относительно этой новой сети:
root@kvm:~# virsh net-info nat_net Name: nat_net UUID: fba2ca2b-8ca7-4dbb-beee-14799ee04bc3 Active: yes Persistent: yes Autostart: yes Bridge: virbr1 root@kvm:~#
-
Измените соответствующее определение своего экземпляра
kvm1
и измените название сетевой среды его источника:root@kvm:~# virsh edit kvm1 ... <interface type='network'> ... <source network='nat_net'/> ... </interface> ... Domain kvm1 XML configuration edited. root@kvm:~#
-
Перезупустите эту гостевую KVM:
root@kvm:~# virsh destroy kvm1 Domain kvm1 destroyed root@kvm:~# virsh start kvm1 Domain kvm1 started root@kvm:~#
-
Перечислите все программно определённые мосты своего хоста:
root@kvm:~# brctl show bridge name bridge id STP enabled interfaces virbr0 8000.000000000000 yes virbr1 8000.525400ba8e2c yes virbr1-nic vnet0 root@kvm:~#
-
Подключитесь к своим экземплярам KVM и проверьте установленные IP адреса их нтерфейсов
eth0
и убедитесь в наличии подключения к мосту их хоста (если ваш образ не настроен для доступа через консоль, воспользуйтесь вместо него каким- то клиентом VNC):root@kvm:~# virsh console kvm1 Connected to domain kvm1 Escape character is ^] Debian GNU/Linux 8 debian ttyS0 debian login: root Password: ... root@debian:~# ip a s eth0 | grep inet inet 10.10.10.92/24 brd 10.10.10.255 scope global eth0 inet6 fe80::5054:ff:fe55:9bd6/64 scope link root@debian:~# ifconfig eth0 up && dhclient eth0 root@debian:~# ping 10.10.10.1 -c 3 PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data. 64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=0.313 ms 64 bytes from 10.10.10.1: icmp_seq=2 ttl=64 time=0.136 ms 64 bytes from 10.10.10.1: icmp_seq=3 ttl=64 time=0.253 ms --- 10.10.10.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2000ms rtt min/avg/max/mdev = 0.136/0.234/0.313/0.073 ms root@debian:~#
-
В ОС своего хоста опросите какие службы DHCP запущены:
root@kvm:~# pgrep -lfa dnsmasq 38983 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf 40098 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/nat_net.conf root@kvm:~#
-
Проверьте установленный IP для интерфейса своего нового моста:
root@kvm:~# ip a s virbr1 43: virbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 52:54:00:ba:8e:2c brd ff:ff:ff:ff:ff:ff inet 10.10.10.1/24 brd 10.10.10.255 scope global virbr1 valid_lft forever preferred_lft forever root@kvm:~#
-
Выведите список правил
iptables
для имеющейся таблицы NAT:root@kvm:~# iptables -L -n -t nat Chain PREROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination RETURN all -- 10.10.10.0/24 224.0.0.0/24 RETURN all -- 10.10.10.0/24 255.255.255.255 MASQUERADE tcp -- 10.10.10.0/24 !10.10.10.0/24 masq ports: 1024-65535 MASQUERADE udp -- 10.10.10.0/24 !10.10.10.0/24 masq ports: 1024-65535 MASQUERADE all -- 10.10.10.0/24 !10.10.10.0/24 RETURN all -- 192.168.122.0/24 224.0.0.0/24 RETURN all -- 192.168.122.0/24 255.255.255.255 MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24 RETURN all -- 192.168.122.0/24 224.0.0.0/24 RETURN all -- 192.168.122.0/24 255.255.255.255 MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24 root@kvm:~#
Мы начали на шаге 1 с перечисления всех доступных сетевых сред в ОС своего хоста. Как мы можем видеть из получаемого
вывода своей команды virsh
, имеется запущенной только одна сетевая среда,
установленная по умолчанию.
На шаге 2 мы изучаем имеющиеся настройки в этой установленной по умолчанию сетевой среды. Его определение XML использует следующие атрибуты:
-
Атрибут
<network>
является корневым элементом, указывающим libvirt что мы определяем некую сетевую среду. -
Элемент
<name>
определяет само название этой сете вой среды и требует его уникальности. -
Атрибут
<uuid>
предоставляет некий глобальный уникальный идентификатор для нашей виртуальной сетевой среды и, если он опущен, он выработается автоматически. -
Элемент
<forward>
и его атрибут режима определяют ту сеть, с которой соединяется весь стек сети хоста при помощи NAT. Если этот элемент опущен, libvirt создаст некую изолированную сеть. -
Субэлемент
<nat>
далее определяет соответствующий диапазон<port>
, который будет применяться когда данный хост выполняет NAT. -
Элемент
<bridge>
определяет создаваемый мост, его название и параметры STP. -
Атрибут
<ip>
определяет необходимый диапазон IP для существующего сервера DHCP под назначение адресов всем гостевым ВМ.
На шаге 3 мы просматриваем файл настроек для установленной сети по умолчанию относительно перечисленного. Обратите внимание, что некоторые атрибуты пропущены. Libvirt автоматически вырабатывает определённые атрибуты и назначает значения по умолчанию так где это необходимо.
На шагах 4 и 5 мы проверяем что у нас имеется запущенный экземпляр, подключённый к установленному по умолчанию мосту Linux.
На шаге 6 мы создаём некое новое определение сетевой среды при помощи сети по умолчанию в качестве шаблона. Мы изменяем её название и определяем новый диапазон IP.
Имея готовым новый файл определения сетевой среды на шагах 7 и 8 мы определяем такую новую сеть, запускаем её и убеждаемся
что она автоматически запускается при запуске самого демона libvirt
в случае
перезагрузки сервера.
После получения на шаге 9 дополнительной информации относительно вновь созданной сетевой среды мы продолжаем на шаге 10
изменять имеющееся определение XML соответствующей гостевой KVM. Чтобы сделать эту ВМ частью нашей новой сети всё что требуется,
это обновить её элемент <source network>
.
После перезапуска этой гостевой KVM на шаге 11 мы продолжаем на шаге 12 выводом списка всех доступных программно
определяемых мостов в ОС своего хоста. Обратите внимание, что теперь у нас существует два моста, причём новый мост имеет
подключёнными к нему виртуальные интерфейсы vnet0
с виртуальных машин.
Затем мы подключаемся к запущенной гостевой KVM и убеждаемся что её сетевой интерфейс eth0 получил некий IP адрес от
своего сервера DHCP запущенного в этом хосте и что этот IP является частью того диапазона адресов, который мы настроили
ранее. Мы также проверяем соединение при помощи команды ping
.
Вернувшись в ОС своего хоста, на шагах 14 и 15 мы проверяем что службы DHCP запущены. Относительно вывода команды
pgrep
, обратите внимание что теперь у нас имеются два запущенных процесса
dnsmasq
: по одному для каждой из определённых сетей.
Переадресация NAT достигается установкой правил iptables, который мы можем видеть на шаге 18. Всякий раз когда мы определяем и запускаем некую новую сеть NAT, libvirt создаёт все необходимые правила в iptables. Из полученного на шаге 18 вывода мы можем видеть наличие двух наборов правил NAT, по одному для каждой запущенной сети NAT.
Полностью снарядив себя мостами мы можем подключать свои гостевые KVM напрямую к сетевой среде своего хоста без использования NAT. Однако такая установка требует некоего IP адреса, который является частью подсети самого хоста, причём для каждой виртуальной машины. Если у вас нет возможности выделять настолько много IP адресов, рассмотрите применение сети NAT, как это описано в выданном ранее рецепте Настройка переадресации NAT сетевой среды. При таком режиме построения сетевой среды ваши виртуальнве машины всё ещё используют для связи имеющийся мост ОС своего хоста; однако этот мост поглощает все физические интерфейсы, которые вы намерены применять для своих гостей.
В этом рецепте нам потребуется следующее:
-
Некий сервер с по крайней мере двумя физическими интерфейсами
-
Возможность предоставлять и запускать экземпляры KVM с помощью libvirt
-
Запущенный экземпляр KVM
Для определения некоторой новой сетевой среды с мостом и подключения к ней гостей выполните следующие шаги:
-
Отключите тот интерфейс, который мы намерены использовать для моста:
root@kvm:~# ifdown eth1 root@kvm:~#
-
Измените файл сетевых настроек в своём хосте и замените его блок
eth1
следующим, если ваш хост это ОС с Debian/ Ubuntu:root@kvm:~# vim /etc/network/interfaces ... auto virbr2 iface virbr2 inet static address 192.168.1.2 netmask 255.255.255.0 network 192.168.1.0 broadcast 192.168.1.255 gateway 192.168.1.1 bridge_ports eth1 bridge_stp on bridge_maxwait 0 ... root@kvm:~#
-
Если вы применяете дистрибутивы RedHat/CentOS, вместо этого замените следующие два файла:
oot@kvm:~# cat /etc/sysconfig/ifcfg-eth1 DEVICE=eth1 NAME=eth1 NM_CONTROLLED=yes ONBOOT=yes TYPE=Ethernet BRIDGE=virbr2 root@kvm:~# cat /etc/sysconfig/ifcfg-bridge_net DEVICE=virbr2 NAME=virbr2 NM_CONTROLLED=yes ONBOOT=yes TYPE=Bridge STP=on IPADDR=192.168.1.2 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 root@kvm:~#
-
Поднимите свой новый интерфейс:
root@kvm:~# ifup virbr2 root@kvm:~#
-
Отключите отправку пакетов в
iptables
, которые появляются из ваших гостевых ВМ:root@kvm:~# sysctl -w net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-iptables = 0 root@kvm:~# sysctl -w net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-iptables = 0 root@kvm:~# sysctl -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-arptables = 0 root@kvm:~#
-
Перечислите все мосты в своём хосте:
root@kvm:~# # brctl show bridge name bridge id STP enabled interfaces virbr0 8000.000000000000 yes virbr2 8000.000a0ac60210 yes eth1 root@kvm:~#
-
Измените определение XML для своего экземпляра KVM:
root@kvm:~# virsh edit kvm1 ... <interface type='bridge'> <source bridge='virbr2'/> </interface> ... Domain kvm1 XML configuration edited. root@kvm:~#
-
Перезапустите этот экземпляр KVM:
root@kvm:~# virsh destroy kvm1 Domain kvm1 destroyed root@kvm:~# virsh start kvm1 Domain kvm1 started root@kvm:~#
Для настройки сетевой среды с мостом на шагах 1 и 2 мы вначале выключаем некий физический интерфейс
(в данном примере eth1
), чтобы поглотить его (сделать его некоторой
частью того нового моста, который мы намерены создать). Затем мы создаём некую сетевую конфигурацию, определяем
новый необходимый мост и тот физический интерфейс, который мы намерены сделать частью этого моста. Это на самом деле
устанавливает соответствие той подсети что мы настраиваем в данном физическом интерфейсе данному мосту. Если ваш
сервер имеет только один сетевой интерфейс, вы всё ещё можете поглотить его. Однако вам потребуется некий
дополнительный способ подключения к этому серверу, так как после того как вы отключите свой основной интерфейс,
вы потеряете связь и устранение неисправностей может стать невозможным через какое- то подключение SSH.
После того как этот новый мост настроен, мы запускаем его на шаге 3.
На шаге 4 мы указываем своему ядру не применять правила iptable ни к какому обмену, появляющемуся у наших виртуальных гостей подключаемых к этому мосту Linux, поскольку мы не применяем никаких правил NAT.
После запуска своего нового интерфейса мы теперь на шаге 5 можем видеть свой мост и поглощённый им физический интерфейс, который мы подключили к нему.
На шаге 6 мы изменяем имеющееся определение XML своего экземпляра kvm1
, в
котором мы задаём необходимый тип сетевой среды который мы желаем применять; для данного рецепта это сеть с мостом
(bridge
). Если вы вспомните рецепт
Настройка переадресации NAT сетевой среды, мы использовали тип
сети (network
) вместо сети с мостом и мы определяли некое название сети
libvirt
вместо самого названия моста.
Наконец, после перезапуска своего экземпляра KVM на шаге 7, наша гостевая ОС должна теперь иметь возможность достигать прочие экземпляры, которые являются частью той же самой подсети без использования NAT.
Обсуждаемый нами гипервизор KVM поддерживает прямое подключение устройств PCI из ОС своего хоста в его виртуальные машины. Мы можем применять эту функциональность для подключения сетевого интерфейса напрямую в имеющуюся гостевую ОС без необходимости применения NAT или программно определяемого моста.
В данном рецепте мы намерены подключить некую NIC (Network Interface Card), которая поддерживает SR-IOV (Single Root I/O Virtualization, виртуализацию ввода/ вывода с единым корнем) из своего хоста в соответствующего гостя KVM. SR-IOV представляет собой спецификацию, которая позволяет устройству PCIe (Peripheral Component Interconnect Express) выступать в виде множества физических устройств {Прим. пер.: виртуальных функций}, которые могут совместно применяться многими виртуальными машинами в одном и том же хосте, выполняя проброс на уровне самого супервизора, тем самым достигая естественной сетевой скорости. Поставщики облачных решений, такие как Amazon AWS выставляют эту функциональность для своих вычислительных экземпляров EC2 через вызовы API.
Для полного исполнения данного рецепта нам потребуется следующее:
-
Некий физический хост с NIC, которая поддерживает SR-IOV
-
Коммутатор с возможностями
802.1Qbh
, подключаемый к этому физическому серверу -
ЦПУ с расширениями либо Intel VT-d, либо AMD IOMMU
-
Хост Linux с установленным
libvirt
готовый к предоставлению экземпляров KVM
Для настройки сетевой среды со сквозным PCIe проделайте следующие шаги:
-
Выведите список всех устройств ОС своего хоста:
root@kvm:~# virsh nodedev-list --tree computer | +- net_lo_00_00_00_00_00_00 +- net_ovs_system_0a_c6_62_34_19_b4 +- net_virbr1_nic_52_54_00_ba_8e_2c +- net_vnet0_fe_54_00_55_9b_d6 ... | +- pci_0000_00_03_0 | | | +- pci_0000_03_00_0 | | | | | +- net_eth0_58_20_b1_00_b8_61 | | | +- pci_0000_03_00_1 | | | +- net_eth1_58_20_b1_00_b8_61 | ... root@kvm:~#
-
Перечислите все адаптеры PCI
Ethernet
:root@kvm:~# lspci | grep Ethernet 03:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01) 03:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01) root@kvm:~#
-
Получите дополнительные сведения относительно той NIC, которую использует устройство
eth1
:root@kvm:~# virsh nodedev-dumpxml pci_0000_03_00_1 <device> <name>pci_0000_03_00_1</name> <path>/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.1</path> <parent>pci_0000_00_03_0</parent> <driver> <name>ixgbe</name> </driver> <capability type='pci'> <domain>0</domain> <bus>3</bus> <slot>0</slot> <function>1</function> <product id='0x10fb'>82599ES 10-Gigabit SFI/SFP+ Network Connection</product> <vendor id='0x8086'>Intel Corporation</vendor> </capability> </device> root@kvm:~#
-
Преобразуйте домен, шину, слот и значения функций в шестнадцатеричные числа:
root@kvm:~# printf %x 0 0 root@kvm:~# printf %x 3 3 root@kvm:~# printf %x 0 0 root@kvm:~# printf %x 1 1 root@kvm:~#
-
Создайте некий новый файл определения сетевой среды
libvirt
:root@kvm:~# cat passthrough_net.xml <network> <name>passthrough_net</name> <forward mode='hostdev' managed='yes'> <pf dev='eth1'/> </forward> </network> root@kvm:~#
-
Определите, запустите и включите автоматический старт своей новой сетевой среды
libvirt
:root@kvm:~# virsh net-define passthrough_net.xml Network passthrough_net defined from passthrough_net.xml root@kvm:~# virsh net-start passthrough_net Network passthrough_nett started root@kvm:~# virsh net-autostart passthrough_net Network passthrough_net marked as autostarted root@kvm:~# virsh net-list Name State Autostart Persistent ---------------------------------------------------------- default active yes yes passthrough_net active yes yes root@kvm:~#
-
Измените XML определение своей гостевой KVM:
root@kvm:~# virsh edit kvm1 ... <devices> ... <interface type='hostdev' managed='yes'> <source> <address type='pci' domain='0x0' bus='0x00' slot='0x07' function='0x0'/> </source> <virtualport type='802.1Qbh' /> </interface> <interface type='network'> <source network='passthrough_net'> </interface> ... </devices> ... Domain kvm1 XML configuration edited. root@kvm:~#
-
Перезапустите этот экземпляр KVM:
root@kvm:~# virsh destroy kvm1 Domain kvm1 destroyed root@kvm:~# virsh start kvm1 Domain kvm1 started root@kvm:~#
-
Выведите перечень VF (Virtual Functions), предоставляемых NIC SR-IOV:
root@kvm:~# virsh net-dumpxml passthrough_net <network connections='1'> <name>passthrough_net</name> <uuid>a4233231-d353-a112-3422-3451ac78623a</uuid> <forward mode='hostdev' managed='yes'> <pf dev='eth1'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x1'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x3'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x5'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x7'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x1'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x3'/> <address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x5'/> </forward> </network> root@kvm:~#
Чтобы напрямую подключать NIC PCIe от ОС своего хоста в его гостевые ВМ нам вначале необходимо получить некую
информацию об аппаратных средствах этого устройства, такую как домен, шина, слот и идентификаторы функций. На шаге 1
мы собираем информацию обо всех доступных устройствах в сервере своего хоста. Нас интересуют сетевой интерфейс,
применяемый для eth1; более того мы выписываем из полученного вывода уникальную идентификацию PCI -
в данном случае pci_0000_03_00_1
.
Чтобы убедится что это на самом деле NIC, который мы бы хотели выставить своему гостю, мы перечисляем все устройства
PCI на шаге 2. Из этого вывода мы можем обнаружить, что идентификатор его PCI тот же самый,
03:00.1
.
Применяя PCI ID с шага 1 на шаге 3 мы продолжим собирать дополнительную информацию относительно NIC.
Обратите внимание, что 0000_03_00_1 ID
разбивается далее на идентификатор домена,
идентификатор шины, идентификатор слота и идентификатор функции, как это показано в соответствующих атрибутах XML.
Мы намерены воспользоваться ими на шаге 7; однако вначале нам необходимо преобразовать их в шестнадцатеричные числа,
что мы и делаем на шаге 4.
На шагах 5 и 6 мы определяем некую новую сетевую среду libvirt
для своих
гостей и включаем автоматический сатр в случае перезапуска сервера своего хоста. Если вы выполняли прочие рецепты из
этой главы, вы уже должны быть знакомы с большинством атрибутов в таком файле XML определений для той сети, которую мы
только что создали. Режим hostdev
определённый в атрибуте
<forward>
является именно тем, что инструктирует
libvirt
что наша новая сетевая среда намерена применять проброс PCI.
Соответствующий параметр managed=yes
, как это определено в нашем атрибуте
<forward>
сообщает libvirt
вначале отключить это устройство PCI от хоста перед передачей его соответствующему гостю и повторно подключать его в этот
хост после останова такого гостя. Наконец, субэлемент <pf>
определяет
тот физический интерфейс, который будет виртуализован и представлен соответствующему гостю.
Замечание | |
---|---|
Для получения дополнительных сведений относительно доступных атрибутов XML, обращайтесь, пожалуйста, к http://libvirt.org/formatdomain.html. |
На щаге 7 мы изменяем определение XML своего экземпляра KVM, определяя тот ID PCI, который мы получили на шаге 3 и определяем некий интерфейс, который будет применять новую сквозную сетевую среду PCIe, которую мы создали на шагах 5 и 6.
На шаге 8 мы перезапускаем свой экземпляр KVM и наконец проверяем что наше физическое устройство PCI NIC теперь является частью новой сквозной сетевой среды, определённой нами ранее. Обратите внимание на наличие множества устройств с типом PCI. Это происходит потому, что данное проброшенное устройство PCIe, которое мы будем применять, поддерживает SR-IOV. Все гостевые KVM, которые будут пользоваться этой сетевой средой теперь будут способны напрямую применять NIC своего хоста назначая одно из перечисленных виртуальных устройств PCie.
Libvirt предоставляет удобный способ управления сетевыми интерфейсами в имеющемся хосте через уже знакомый нам синтаксис
определений XML. Мы можем применять команду virsh
для определения, предоставления и
удаления мостов Linux, а также получать дополнительную информацию относительно имеющихся сетевых интерфейсов, как мы это
уже наблюдали в данной главе.
В данном рецепте мы намерены определить некий новый мост Linux, создать его и наконец удалить его с помощью
virsh
. Если вы вспомните наши более ранние рецепты, мы можем манипулировать
имеющимся мостом Linux через такие утилиты как brctl
. Для libvirt, однако, у нас
имеется некий способ контроля этого программным путём через написание соответствующего файла определения и использование
соответствующих компоновок API, которые мы рассмотрим в Главе 7,
Применение Python для построения экземпляров KVM и управления ими.
Для данного рецепта нам потребуются:
-
Установленный в нашем хосте пакет
libvirt
-
Некий хост Linux с установленным модулем ядра для моста
Для создания нового интерфейса моста при помощи libvirt выполните такие команды:
-
Создайте некий новый файл настройки интерфейса моста:
root@kvm:~# cat test_bridge.xml <interface type='bridge' name='test_bridge'> <start mode="onboot"/> <protocol family='ipv4'> <ip address='192.168.1.100' prefix='24'/> </protocol> <bridge> <interface type='ethernet' name='vnet0'> <mac address='fe:54:00:55:9b:d6'/> </interface> </bridge> </interface> root@kvm:~#
-
Перечислите все известные libvirt интерфейсы:
root@kvm:~# virsh iface-list --all Name State MAC Address --------------------------------------------------- bond0 active 58:20:b1:00:b8:61 bond0.129 active bc:76:4e:20:10:6b bond0.229 active bc:76:4e:20:17:7e eth0 active 58:20:b1:00:b8:61 eth1 active 58:20:b1:00:b8:61 lo active 00:00:00:00:00:00 test_bridge inactive root@kvm:~#
-
Запустите полученный новый интерфейс моста:
root@kvm:~# virsh iface-start test_bridge Interface test_bridge started root@kvm:~# virsh iface-list --all | grep test_bridge test_bridge active 4a:1e:48:e1:e7:de root@kvm:~#
-
Перечислите все устройства моста в этом хосте:
root@kvm:~# brctl show bridge name bridge id STP enabled interfaces test_bridge 8000.000000000000 no virbr0 8000.000000000000 yes virbr1 8000.525400ba8e2c yes virbr1-nic vnet0 root@kvm:~#
-
Проверьте все активные сетевые настройки своего нового моста:
root@kvm:~# ip a s test_bridge 46: test_bridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default link/ether 4a:1e:48:e1:e7:de brd ff:ff:ff:ff:ff:ff inet 192.168.1.100/24 brd 192.168.1.255 scope global test_bridge valid_lft forever preferred_lft forever inet6 fe80::481e:48ff:fee1:e7de/64 scope link valid_lft forever preferred_lft forever root@kvm:~#
-
Определите этот новый интерфейс:
root@kvm:~# virsh iface-define test_bridge.xml Interface test_bridge defined from test_bridge.xml root@kvm:~#
-
Получите значение MAC адреса моста:
root@kvm:~# virsh iface-mac test_bridge 4a:1e:48:e1:e7:de root@kvm:~#
-
Получите название созданного моста предоставив его MAC адрес:
root@kvm:~# virsh iface-name 4a:1e:48:e1:e7:de test_bridge root@kvm:~#
-
Удалите созданный интерфейс следующим образом:
root@kvm:~# virsh iface-destroy test_bridge Interface test_bridge destroyed root@kvm:~# virsh iface-list --all | grep test_bridge test_bridge inactive root@kvm:~# virsh iface-undefine test_bridge Interface test_bridge undefined root@kvm:~# virsh iface-list --all | grep test_bridge root@kvm:~#
На шаге 1 мы записываем необходимое определение XML для своего нового сетевого интерфейса. Мы определяем мост по значению типа, некого IP адреса для его интерфейса и необязательного какого- то MAC адреса.
На шагах 2 и 3 мы определяем этот новый мост и выводим его в списке. Определение такого интерфейса не делает автоматически его активным, поэтому на шаге 4 мы активируем его.
Как показано на шаге 5, активация этого моста создаёт его реальный интерфейс в этом хосте.
На шаге 6 мы убеждаемся что назначенные адреса IP и MAC действительно те, которые мы определили на шаге 1.
На шагах 7 и 8 мы получаем и название и MAC адрес при помощи утилиты virsh
,
а, наконец, на шаге 9 мы удаляем созданный интерфейс bridge
.