Содержание статьи
Представь, что у тебя есть готовая инфраструктура с гипервизорами и виртуалками внутри. Задача: предоставить определенной группе виртуальных машин IP-адрес в одном широковещательном домене, другой группе — в другом, а самому гипервизору — в третьем. То есть разместить их в различных сетях.
Такая ситуация может возникнуть по разным причинам. Приведу несколько примеров.
- Обязанности в организации строго разделены. Есть администратор доменной сети (AD), есть администратор других серверов, предоставляющих различные сетевые сервисы организации (DNS-сервер, mail-сервер, веб-сервер, сервер баз данных и другие). Администратор сервера AD хочет, чтобы его виртуальный сервер был в одной сети с клиентами, при этом безопасник настаивает, чтобы сам гипервизор находился в отдельной сети серверов (отдельный широковещательный домен).
- Ты предоставляешь доступ извне к виртуальной машине. Как обеспечить такой доступ и закрыть доступ к любому другому узлу?
Самый простой способ реализовать такую схему — это включить один сетевой интерфейс в одну сеть, другой в другую и настроить мосты соответствующим образом. Нельзя сказать, что такой подход на 100% правильный или неправильный, но он вполне рабочий. И значит, имеет право на жизнь. А как быть тем, у кого всего один сетевой интерфейс? В любом случае наиболее правильный метод, если есть коммутатор второго уровня (L2), — это разделить сеть на логические сегменты. Проще говоря, построить сеть на VLAN’ах.
Что нужно знать о VLAN
VLAN — это виртуальные сети, которые существуют на втором уровне модели OSI и реализуются с помощью коммутаторов второго уровня. Не вдаваясь в подробности, можно сказать, что это группа портов коммутатора, разделенная на логические сегменты сети. Каждый такой сегмент имеет свой маркер (тег PVID). Каждая группа портов VLAN’а знает о своей принадлежности к определенной группе благодаря этим тегам.
Существует два типа портов: access и trunk. В access подключаются конечные сетевые устройства, в trunk подключаются только другие trunk-порты. Если с компьютера пакет попадает на access-порт, то он помечается тегом (PVID), и далее коммутатор отправляет этот пакет только на порты точно с такими же VLAN ID или на trunk-порт. При отправке кадра конечному узлу тег снимается, так что они понятия не имеют о том, что находятся в каком-либо VLAN’е.
Когда пакет попадает на trunk-порт, он передается как есть, тег не снимается. Таким образом, внутри trunk-порта передаются пакеты с несколькими тегами (PVID).
Стоит заметить, что access-порт можно настроить так, чтобы тег на выходе не снимался, тогда для принятия пакета конечный клиент должен знать, в какой VLAN он подключен. Не все сетевые карты и/или ОС поддерживают работу с VLAN по умолчанию. Как правило, это зависит от драйвера сетевой карты.
Приступаем к настройке
Напоминаю, что в одной из предыдущих статей мы рассматривали построение виртуализации на базе Ubuntu/Debian и KVM. Поэтому исходить будем из того, что система установлена и настроена, есть два физических интерфейса, один подключен к виртуальному мосту и есть виртуальные машины, которые им пользуются. Второй интерфейс не сконфигурирован.
Теперь вернемся к нашим VLAN’ам. Чтобы наша идея работала, нам нужно подключить первый физический интерфейс нашей машины к trunk-порту коммутатора, но при этом заблаговременно разделить (а точнее, протегировать) трафик виртуалок по разным VLAN’ам.
Самый простой и примитивный вариант это сделать — создавать виртуальные сетевые карты, каждую настраивать на определенный VLAN и для каждой виртуальной карты поднять отдельный виртуальный сетевой мост, через который и подключать нужную виртуальную машину. Способ рабочий, правда есть несколько недостатков:
- Очень некрасивый вывод ifconfig.
- Нет возможности на лету добавить или удалить VLAN. Иначе говоря, для каждого нового VLAN’а нужно добавлять виртуальный интерфейс. Подключать его в VLAN, включать в мост. Останавливать виртуальную машину и подключать сеть через этот мост.
- Занимает много времени.
Но если у нас виртуальные машины, почему бы не воспользоваться виртуальным коммутатором второго уровня, в который и воткнуть все виртуальные проводки? Это решение гораздо лучше, позволяет более гибко настроить систему. Ну и использовать такой коммутатор, как самый обычный!
Гугление привело к трем наиболее популярным решениям. Одно входит в состав Hyper-V, который платный и не умеет OpenFlow. Второе: MikroTik, с помощью которого можно не только создать виртуальный коммутатор, но и перенести его конфигурацию на железный. Отпугивает только, что он базируется на полноценной операционной системе — RouterOS. А это уже совсем не то. И наконец, встречай — Open vSwitch.
Open vSwitch
Open vSwitch — программный многоуровневый коммутатор с открытым исходным текстом, предназначенный для работы с гипервизорами. Работает в Linux начиная с версии 2.6.15. Основные возможности коммутатора:
- учет трафика, в том числе проходящего между виртуальными машинами с использованием SPAN/RSPAN, sFlow и Netflow;
- поддержка VLAN (IEEE 802.1q);
- привязка к конкретным физическим интерфейсам и балансировка нагрузки по исходящим MAC-адресам;
- работа на уровне ядра, совместимость с программным мостом Linux Bridge;
- поддерживает OpenFlow для управления логикой коммутации;
- с меньшей производительностью, чем в режиме на уровне ядра, Open vSwitch может работать как обычное приложение.
Open vSwitch используется в составе Xen Server, Xen Cloud Platform, KVM, VirtualBox, QEMU, ProxMox (начиная с 2.3).
В качестве наглядного примера будем виртуализировать сервер Kerio 9.1.4. Итак, чтобы понимать, как сейчас все устроено до переделки. Железный сервер Kerio — второй сервер виртуализации, в котором работает несколько сетевых сервисов организации: клиентские сети net1, net2, net3 и net4, серверная сеть net5. Каждый сегмент сети подключен в отдельный сетевой интерфейс «железного» Kerio.
![Схема, которую будем реализовывать](https://xakep.ru/wp-content/uploads/2017/09/136643/2.png)
Напоминаю: исходим из того, что сервер виртуализации уже установлен и настроен. Также установлен пакет bridge-utils и настроен сетевой мост br0. В системе присутствуют некоторые виртуальные машины, подключенные через этот сетевой мост.
Установка и первоначальная настройка
На самом деле установка Open vSwitch сводится к установке одного пакета:
$ sudo apt-get install openvswitch-switch
После установки никаких изменений не происходит, кроме запуска сервиса OVS. Создадим коммутатор:
$ sudo ovs-vsctl add-br br1
Посмотрим, что к нему подключено:
$ sudo ovs-vsctl show.
0b58d70f-e503-4ed2-833c-e24503f2e45f
Bridge "br1"
Port "br1"
Interface "br1"
type: internal
ovs_version: "2.5.2"
Мы видим, что создан коммутатор br1 с подключенным интерфейсом br1
. Если требуется, можно этот порт настроить, например задать ему определенный VLAN или порт как trunk с ограничениями по конкретным VLAN’ам. Далее подключим к нашему коммутатору свободный сетевой интерфейс ОС.
$ sudo ovs-vsctl add-port br1 eth0
![Схема подключения OVS и физического интерфейса](https://xakep.ru/wp-content/uploads/2017/09/136643/3.png)
По умолчанию этот порт начинает работать как обычный и транковый порт, пропуская все VLAN’ы. Далее можно сделать этот порт транковым для указанных VLAN ID. Или можно оставить как есть, тогда порт будет пропускать все VLAN ID. У нас структура большая, сеть может каждый день меняться, поэтому оставим как есть.
Следующим шагом обнуляем конфигурацию интерфейса eth0 и отключаем его от TCP/IP-стека операционной системы:
$ sudo ifconfig eth0 0
Далее вместо eth0 подключаем к TCP/IP-стеку ОС новый внутренний интерфейс br1
коммутатора br1. Приятная новость: OVS автоматически применяет и сохраняет свою конфигурацию, поэтому ничего особо делать не придется. Интерфейс OVS управляется, как обычный интерфейс операционной системы, а значит, идем в /etc/network/interfaces и делаем необходимые изменения — меняем eth0
на br1
, eth0
пишем как manual:
auto eth0
iface eth0 inet manual
auto br1
iface br1 inet static
address 192.168.*.160
netmask 255.255.255.0
gateway 192.168.*.1
dns-nameservers 192.168.*.2
И все! Никаких дополнительных настроек bridge, как в случае с мостом.
Подключаем наш интерфейс к порту коммутатора, на котором настройки такие: trunk-порт для всех VLAN, для VLAN ID 1 трафик не тегирован. То есть порт пропускает транком все VLAN ID и трафик без VLAN вообще. Запускаем сеть командой ifup br1
, после этого мы в сети. В некоторых случаях это может не сработать из-за правки файла настроек сети. Тогда можно попробовать запустить интерфейс вот так:
$ sudo ifconfig br1 up
Проверяем пингами доступность.
Посмотрим, что изменилось у нас на виртуальном коммутаторе:
$ sudo ovs-vsctl show
0b58d70f-e503-4ed2-833c-e24503f2e45f
Bridge "br1"
Port "eth0"
Interface "eth0"
Port "br1"
Interface "br1"
type: internal
ovs_version: "2.5.2"
Как видим, в коммутатор подключено уже два интерфейса: физический интерфейс коммутатора eth0 и интерфейс операционной системы br1.
Теперь займемся виртуальными машинами.
Настройка групп адресов KVM
Как же теперь подключить к этому коммутатору еще и виртуальные машины? Есть два стандартных пути. Первый нам уже знаком — добавляем порт в коммутатор командой ovs-vsctl add-port
, затем добавляем этот порт в виртуальную машину.
Второй путь более гибкий. Он заключается в создании групп портов KVM для OVS. Каждая группа будет принадлежать к соответствующему VLAN ID. К сожалению, настройка таких групп из Archipel или virt-manager пока недоступна. Поэтому потребуется вручную подготовить XML-файл, описывающий необходимые группы, и после этого с помощью virsh применить его.
<network>
<name>ovs-lan</name>
<forward mode='bridge'/>
<bridge name='br1'/>
<virtualport type='openvswitch'/>
<portgroup name='vlan-10'>
<vlan>
<tag id='10'/>
</vlan>
</portgroup>
<portgroup name='vlan-20'>
<vlan>
<tag id='20'/>
</vlan>
</portgroup>
<portgroup name='vlan-30'>
<vlan>
<tag id='30'/>
</vlan>
</portgroup>
<portgroup name='vlan-40'>
<vlan>
<tag id='40'/>
</vlan>
</portgroup>
<portgroup name='vlan-50'>
<vlan>
<tag id='50'/>
</vlan>
</portgroup>
<portgroup name='vlan-90'>
<vlan>
<tag id='90'/>
</vlan>
</portgroup>
<portgroup name='trunk-allvlan'>
<vlan trunk='yes'>
</vlan>
</portgroup>
<portgroup name='trunk'>
<vlan trunk='yes'>
<tag id='30'/>
<tag id='40'/>
<tag id='50'/>
</vlan>
</portgroup>
</network>
Применяем конфигурацию:
$ sudo virsh net-define /path_to/file.xml
Далее запускаем саму сеть:
$ sudo virsh net-start ovs-lan
И делаем запуск автоматическим:
$ sudo virsh net-autostart ovs-lan
Для удаления ненужных сетей можно воспользоваться Archipel (раздел NETWORK), virt-manager или выполнить команды
$ virsh net-destroy ovs-network
$ virsh net-autostart --disable ovs-network
$ virsh net-undefine ovs-network
Далее переходим к созданию виртуалок через virt-manager или открываем существующую остановленную виртуальную машину.
![Подключение виртуальных сетевых машин к порту коммутатора OVS](https://xakep.ru/wp-content/uploads/2017/09/136643/4.png)
Подключение виртуальных машин
Открываем двойным кликом требуемую виртуальную машину. Переходим по кнопке «Показать виртуальное оборудование». Выбираем NIC.
![Настройка сетевого интерфейса ВМ в virt-manager](https://xakep.ru/wp-content/uploads/2017/09/136643/5.jpg)
Далее выбираем «Создать на базе» и указываем нашу созданную сеть ovs-lan
. Появляется группа портов. Здесь можно ничего не выбирать. Тогда у нас будет обычный trunk-порт с трафиком для всех VLAN ID и обычный трафик не VLAN. Можно привязать его к одному VLAN и получать только одну сеть. В общем, в зависимости от задачи.
Мы же хотим настроить Kerio, но на определенных VLAN ID. Здесь существует несколько вариантов. Можно создавать несколько сетевых интерфейсов с разными VLAN ID. Или создать trunk-порт и внутри Kerio «нарезать» VLAN. Этот вариант предпочтительнее благодаря возможности более гибко маневрировать, не выключая и не перезагружая саму виртуальную машину для применения настроек.
После того как все успешно настроено, запускаем виртуальную машину и смотрим, что у нас изменилось на нашем коммутаторе:
d3ff1e72-0828-4e38-b5bf-3f5f02d04c70
Bridge "br1"
Port "eth0"
Interface "eth0"
Port "br1"
Interface "br1"
type: internal
Port "vnet5"
trunks: [10, 20, 30, 40, 50, 60, 70, 80, 90]
Interface "vnet5"
Видим, что виртуальная машина автоматически подключилась к порту vnet50
.
Переходим к интерфейсу управления Kerio. Идем в раздел «Интерфейсы», далее выбираем наш интерфейс, который подключили к VLAN. Открываем его двойным кликом, выбираем вкладку «Виртуальная ЛВС → Добавить или удалить виртуальные ЛВС» и перечисляем нужные VLAN’ы. После этого жмем ОK, и у нас появляются требуемые виртуальные интерфейсы. Далее настраиваем их, как обычные физические интерфейсы, подключенные напрямую в нужные коммутаторы.
![Обзор интерфейсов Kerio с подключенными VLAN ID](https://xakep.ru/wp-content/uploads/2017/09/136643/6.png)
Заключение
Описанная в статье конфигурация позволяет очень гибко и быстро добавлять любое количество сетевых интерфейсов практически любой конфигурации. Таким же образом можно переносить виртуальные серверы в сети клиентов, держа сам гипервизор далеко. Как видишь, настройка не сложнее, чем стандартный сетевой мост, а функциональность намного больше!