- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF137:libvirt
Материал из Linuxformat.
- Сети в libvirt
Содержание |
libvirt: В виртуальной паутине
- Дмитрий Михирев вызвался разобраться в настройках сетей libvirt. На его удивление, там всё оказалось довольно просто.
В LXF132 Грэм Моррисон рассказал много интересного про работу с виртуальной машиной KVM. Прочитавшие его статью наверняка убедились, что в её использовании нет ничего сложного: даже не особо подготовленный пользователь может создать и настроить «виртуалку» с помощью virt-manager и установить на неё любую ОС. Вопрос настройки сетевого соединения для виртуальной машины, однако, остался незатронутым, а ведь потребность в этом возникает очень часто. Попробуем восполнить данное упущение.
Добавим виртуальности
Итак, что же нам понадобится? Разумеется, это сам модуль kvm, QEMU, набор утилит libvirt и графическая оболочка virt-manager. Я буду использовать Mandriva, в которой kvm входит в стандартную комплектацию ядра. Остаётся доустановить пакеты qemu, libvirt-utils, virt-manager, а также, для экспериментов с сетью, bridge-utils. Это делается при помощи команды
su -c “urpmi qemu libvirt-utils virt-manager bridge-utils”
В других дистрибутивах названия пакетов, конечно, могут отличаться, но набор потребуется такой же.
Теперь осталось только запустить демон libvirtd командой
su -c “service libvirtd start”
и можно приступить к настройке сети. Для начала просто посмотрим, что нам предлагается по умолчанию. Для этого запустим virt-manager и откроем пункт меню Правка > Параметры хоста. Здесь на вкладке Виртуальные сети можно увидеть одну-единственную сеть default 192.168.122.0/24, которой соответствует интерфейс virbr0. Маршрутизация в ней осуществляется при посредстве трансляции сетевых адресов (Network Address Translation, NAT), а адреса виртуальным машинам выдаются автоматически по DHCP. Такая конфигурация подходит для большинства случаев – пока у вас не появятся особые запросы.
В некоторых случаях в гостевых системах возникают проблемы с получением настроек по DHCP: например, у меня не сработала автоматическая установка соединения при загрузке с дистрибутивного диска Ubuntu 10.04. В таком случае выручает dhclient – достаточно лишь выполнить в гостевой системе команду
sudo dhclient eth0
и проблема будет решена.
Если виртуальная машина используется не для тестирования новых дистрибутивов, а для более серьезных целей, нередко возникает необходимость сделать гостевую систему видимой из внешней сети. Для примера рассмотрим ситуацию, когда на ней работает web-сервер. Здесь есть два варианта настройки: «проброс» TCP-порта 80 через NAT или отказ от NAT вообще.
Адреса и маски
Если вы не знакомы с основами маршрутизации и вас пугают слова вроде «маска подсети» – не нервничайте, в этом нет ничего сложного. Фактически, задавая IP-адрес и маску, вы указываете своей системе, какие IP-адреса ей надлежит искать на том или ином сетевом интерфейсе. IPv4-адрес состоит из 4 байт, то есть 32 бит. Начала адресов, скрывающихся за тем или иным интерфейсом, обычно одинаковы: например, при настройке виртуальной сети по умолчанию интерфейсу virbr0 соответствуют адреса вида 192.168.122.xxx, где изменяется только последний байт. Первые три байта, то есть 24 бита, неизменны, что и означает число 24 в записи 192.168.122.0/24.
Другой способ сказать то же самое – указать IP-адрес интерфейса и маску, состоящую также из 4 байт, в которой неизменным битам соответствуют единицы, а произвольным – нули. Таким образом, IP-адрес интерфейса 192.168.122.1 и маска подсети 255.255.255.0 означают те же настройки, что и предыдущая запись (адрес подсети получается из адреса интерфейса путём обнуле ния всех изменяемых битов).
Есть ещё один нюанс, о котором, впрочем, virt-manager сам напомнит вам при настройке интерфейса. Если только вам не выделены внешние статические IP-адреса, при настройке следует использовать адреса из трёх специально зарезервированных частных диапазонов: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16. Разумеется, если ваш провайдер вместо внешних IP-адресов раздаёт пользователям адреса, начинающиеся на 10, то для построения своей сети тот же диапазон использовать не стоит.
Проброс порта
В первом случае нужно назначить гостевой ОС статический IP-адрес, для чего неплохо бы сначала исключить его из диапазона, отведённого для DHCP (по умолчанию он покрывает все доступные адреса). Для этого изменим параметр «Окончание DHCP» с 192.168.122.254 на 192.168.122.159. Таким образом, адреса с 192.168.122.160 по 192.168.122.254 можно использовать в качестве статических, не опасаясь конфликтов.
После настройки гостевой ОС на использование IP-адреса – скажем, 192.168.122.160 – вам останется только задать правила маршрутизации. Для этого можно воспользоваться графическими утилитами, входящими в дистрибутив, но мы приведём универсальное решение с применением iptables:
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j DNAT --to 192.168.122.160:80 iptables -A INPUT -p tcp -m state --state NEW --dport 80 -i eth0 -j ACCEPT
Первая команда здесь задаёт переадресацию входящих TCP-соединений на 80‑й порт на адрес гостевой системы, а вторая разрешает приём этих соединений из внешней сети. Разумеется, если в Интернет «смотрит» не eth0, а другой интерфейс, надо внести в команды соответствующие поправки.
Не надо нам NAT’а
Так ли нам нужен NAT? Лично у меня уже есть один в маршрутизаторе, и я не вижу резона чрезмерно усложнять архитектуру сети. А при наличии в ней нескольких серверов, подключение к которым осуществляется по одному и тому же порту, возникает необходимость раздать им всем «белые» IP-адреса. Такая возможность предусмотрена в libvirt, и она так же легко настраивается через virt-manager.
Для этого нужно добавить новую виртуальную сеть (кнопочка с зелёным плюсом притаилась в нижней части окна настроек). Адресное пространство в данном случае следует выбирать таким образом, чтобы не нарушилась маршрутизация в пределах всей подсети. Например, мой маршрутизатор настроен на локальную сеть 192.168.1.0/24 (то есть с маской подсети 255.255.255.0). В данном случае мне проще всего изменить в его настройках маску подсети для LAN на 255.255.0.0, тем самым существенно расширив диапазон доступных в локальной сети адресов. В настройках новой виртуальной сети тогда можно оставить значение по умолчанию – 192.168.100.0/24.
Настройки DHCP тоже можно не трогать: по умолчанию половина доступного диапазона адресов резервируется под статическое использование, а другая – для DHCP. Ну и, наконец, самое главное: надо указать, что виртуальная сеть должна быть подключена к физической, и выбрать режим «Маршрутизируемая». Когда виртуальная сеть будет готова, подключение к ней можно будет выбрать при создании новой виртуальной машины.
Можно и подключить к сети уже существующую машину; для этого в окне последней (вкладка «Подробности») нужно добавить новый сетевой интерфейс, указав в качестве хост-устройства [host device] маршрутизируемую сеть. Если один или несколько виртуальных сетевых интерфейсов уже были подключены к машине ранее, их можно удалить.
Без virt-manager
Virt-manager, безусловно, удобен, но иногда приходится настраивать сеть и в отсутствие графической среды. С libvirt это не так уж сложно: для этих целей служит программа virsh, предоставляющая для настройки текстовый интерфейс командной оболочки.
Основное затруднение заключается в том, что конфигурационный файл сети придётся писать в формате XML. По счастью, он не такой уж большой, чтобы наделать в нём ошибок. Чтобы разобраться, что к чему, взглянем на файл с настройками по умолчанию:
<network> <name>default</name> <uuid>271151ec-efa7-4cfd-99e8-ce7d4d4f848d</uuid> <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>
Первое: все настройки должны быть заключены в тэг <network>. Имя сети – обязательный элемент, он заключается в тэг <name>. В имени можно использовать только буквы латиницы и цифры. Важно, чтобы оно не совпадало с именем уже существующей сети. Идентификатор сети в тэге <uuid> вручную указывать не нужно – он будет создан при добавлении сети автоматически.
Тэг <bridge> содержит описание интерфейса сетевого моста; в большинстве случаев достаточно задать его имя. Рекомендуется начинать имя интерфейса с префикса vir; при этом нужно следить, чтобы оно не дублировало имя уже существующего. Имя virbr0 зарезервировано для виртуальной сети по умолчанию, поэтому при написании конфигурации новых сетей его использовать нельзя.
Тэг <forward> означает, что виртуальная сеть должна быть соединена с физической. Для него можно задать атрибуты mode, принимающий значения «nat» или «route» (для сети с NAT или маршрутизируемой, соответственно), и dev, значение которого задаёт физический сетевой интерфейс. Так, чтобы настроить маршрутизируемую сеть через интерфейс eth0, надо будет написать
<forward mode=”route” dev=”eth0” />
Если виртуальную сеть с физической соединять не надо, тэг <forward> следует опустить.
Ну и, наконец, самое главное – тэг <ip>. Атрибут address задаёт IPv4‑адрес сетевого интерфейса; для виртуальных машин он будет адресом шлюза. Атрибут netmask, как несложно догадаться, задаёт маску подсети; значение “255.255.255.0” в большинстве случаев будет оптимальным. Заключённый в тэг <ip> тэг <dhcp> служит для описания настроек DHCP-сервера. Параметрами тэга <range> задаётся диапазон IP-адресов. Сюда можно также добавить один или несколько тэгов <host>, которые избавят нас от необходимости настраивать статические IP-адреса для виртуальных машин. Например, тэг
<host mac=”52:54:00:13:ee:56” name=”www.home” ip=”192.168.122.1” />
зарезервирует IP-адрес 192.168.122.1 и имя хоста www.home для виртуальной машины с MAC-адресом 52:54:00:13:ee:56. Узнать MAC-адрес можно, просмотрев конфигурационный файл виртуальной машины с помощью команды
virsh dumpxml example | less
Здесь example – это имя машины.
С учётом всего изложенного, конфигурационный файл сети, соответствующий второму из описанных в предыдущем разделе вариантов настройки, будет выглядеть так:
<network> <name>network1</name> <forward mode='route' /> <bridge name='virbr1' /> <ip address='192.168.100.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.100.128' end='192.168.100.254' /> </dhcp> </ip> </network>
Этот файл надо сохранить в любом каталоге, после чего от имени root дать команду
virsh net-create network1.xml
где network1.xml – имя файла. Чтобы сеть запускалась автоматически, нужно выполнить команду
virsh net-autostart network1
Здесь network1 – это имя сети, указанное нами в тэге <name>.
Чтобы отключить автоматический запуск сети default, нужно использовать ту же команду с ключом --disable:
virsh net-autostart default --disable
Хорошо, а как же быть, если возникает необходимость внести исправления в настройки сети? Virsh поможет и здесь: команда virsh net-edit network1 откроет конфигурационный файл в редакторе Vim. Если вы плохо знакомы с ним, можно использовать другой, задав его через переменную окружения $VISUAL. Например, команда
VISUAL=”nano” virsh net-edit network1
откроет файл в редакторе Nano.
Строим мост
Рассмотрим ещё один вариант настройки сети, который подойдёт, если виртуальной машине требуется широкий канал, под который имеется отдельная сетевая карта. Собственно, очевидным решением кажется предоставить гостевой системе прямой доступ к устройству, но это возможно только на сравнительно новом оборудовании с поддержкой IOMMU. Более универсальное решение – настроить мост, отдав физический интерфейс в полное распоряжение виртуальной машины. К сожалению, дело это не такое простое, а главное – в разных дистрибутивах настройку придётся выполнять по-разному. Кроме того, вряд ли получится настроить мост на беспроводной интерфейс.
В Fedora, а также дистрибутивах, производных от Red Hat, включая Mandriva, настройка производится следующим образом. Первым делом отредактируем файл /etc/sysconfig/network-scripts/ifcfg-eth0 (в случае настройки физического интерфейса eth0), приведя его к следующему виду:
DEVICE=eth0 HWADDR=00:1E:8C:47:D2:53 ONBOOT=yes BRIDGE=br0 NM_CONTROLLED=no
Параметр DEVICE должен соответствовать имени интерфейса, HWADDR – его MAC-адресу. Узнать MAC-адрес можно с помощью команды
ifconfig eth0
Параметр BRIDGE=br0 указывает, что интерфейс должен быть связан с мостом br0, который мы создадим чуть позже. Наконец, строка NM_CONTROLLED=no означает, что интерфейс не должен управляться NetworkManager, который не поддерживает соединения мостом. В моём случае с Mandriva последний параметр, возможно, и лишний, поскольку NetworkManager в системе отсутствует, но хуже от него точно не будет.
Далее необходимо создать в каталоге /etc/sysconfig/network-scripts новый файл ifcfg-br0 со следующим содержимым:
DEVICE=br0 TYPE=Bridge BOOTPROTO=dhcp ONBOOT=yes DELAY=0 NM_CONTROLLED=no
Обратите внимание, что в строке TYPE=Bridge слово «Bridge» должно начинаться с заглавной буквы! Если вместо использования DHCP необходимо назначить статический IP-адрес, то параметру BOOTPROTO надлежит присвоить значение
BOOTPROTO=static
и задать параметры сети, например
IPADDR=192.168.1.128 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 DNS1=192.168.1.1
После этого надо перезапустить сервис network:
service network restart
Не помешает также отключить брандмауэр на соединениях типа «мост» (возможно, это уже сделано по умолчанию). Проверьте наличие в файле /etc/sysctl.conf следующих строк:
net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 net.bridge.bridge-nf-call-arptables = 0
Если они отсутствуют, то добавьте их. Затем применим изменения:
sysctl -p /etc/sysctl.conf
Для Debian, Ubuntu и других базирующихся на Debian дистрибутивов настройка несколько отличается. Первым делом потребуется отключить NetworkManager, выполнив команды
sudo /etc/dbus-1/event.d/26NetworkManagerDispatcher stop sudo /etc/dbus-1/event.d/25NetworkManager stop
Затем нужно запретить его запуск в дальнейшем. Это делается следующим образом:
sudo echo “exit” > /etc/default/NetworkManager sudo echo “exit” > /etc/default/NetworkManagerDispatcher
После этого потребуется исправить файл /etc/network/interfaces. Сначала найдите там строки вроде
allow-hotplug eth0 iface eth0 inet static
и отредактируйте их и следующие за ними, приведя к такому виду:
auto br0 iface br0 inet static bridge_ports eth0 bridge_stp on bridge_maxwait 0 bridge_fd 0
Настройки статического IP или DHCP следует оставить без изменений. После сохранения файла остаётся поднять соединение командой
sudo ifup br0
Далее, как и в предыдущем случае, нужно отключить брандмауэр для мостовых соединений, добавив в файл /etc/sysctl.conf строки
net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 net.bridge.bridge-nf-call-arptables = 0
и выполнив команду
sudo sysctl -p /etc/sysctl.conf
Пустим машины
Надеемся, вышеприведённое описание настроек сетевого моста помогло справиться с этой задачей большинству читателей. Пользователям дистрибутивов, не родственных Red Hat или Debian, придётся поискать решение самостоятельно. В некоторых случаях оно предельно простое: например в openSUSE мост добавляется при помощи YaST, в разделе Сетевые устройства > Сетевые настройки. На худой конец, всегда можно создать временный мост, «живущий» до перезагрузки системы, непосредственным вызовом команд из пакета bridge-utils. Все подробности можно найти в документации к пакету.
Когда с созданием моста будет покончено, останется только подключить его к виртуальной машине. Делается это точно так же, как и подключение виртуального сетевого интерфейса. В окне виртуальной машины, на вкладке «Подробности», нужно добавить сетевой интерфейс, в качестве host device выбрав мост br0.
Если графический интерфейс по той или иной причине недоступен, нужно будет внести исправления в конфигурационный файл виртуальной машины. Для этого в случае машины с названием example нужно выполнить от имени root команду
virsh edit example
после чего добавить внутри тэга <devices> примерно такие строки:
<interface type='bridge'> <source bridge='br0' /> <target dev='vnet7' /> <mac address=”00:11:22:33:44:55” /> </interface>
Атрибут dev в тэге <target> должен указывать название виртуального сетевого интерфейса, которое бы не дублировало название уже существующего. С тэгом <mac>, думаю, всё понятно: атрибут address имеет значение, определяющее MAC-адрес этого интерфейса.
Заключение
Как видно, в плане работы в сети виртуальная машина мало чем отличается от реальной. Единственное различие заключается в том, что соединение осуществляется через мост – виртуальный или «настоящий». Благодаря этому виртуальные машины на базе KVM можно использовать и для самых разных экспериментов с построением сетей, и для запуска на них рабочих серверов, никак не связанных с основной системой. А с libvirt настройка KVM становится совсем несложной – неважно, работаете вы из графического окружения или из консоли.