Open vSwitch как ядро виртуальной сети

Материал из support.qbpro.ru

В данной статье для виртуализации используется KVM/libvirt, но сразу отмечу, статья не столько о KVM, сколько именно об особенностях преимуществах использования Open vSwitch для объединения виртуальных и физических сетевых устройств посредством технологии VLAN (802.1q). В былинные времена для проброса тегированного трафика в гипервизор использовались всевозможные костыли и подпорки различной степени неожиданности (tuntap, brctl, vconfig, ebtables и прочее), что приводило к захламлению операционной системы, хостящей гипервизор, большим количеством ненужных виртуальных сетевых интерфейсов, мозолящих глаза в выводе ifconfig и вообще огорчало администраторов необходимостью строить стандартное сетевое устройство (коммутатор) из отдельных частей как какой-то велосипед. Помимо поддержки 802.1q от коммутатора на самом деле сегодня требуется еще много функций. Так необходимость в виртуальном устройстве максимально соответствующем по функционалу стандартному современному управляемому коммутатору привела к появлению проекта Open vSwitch (далее — OVS).
Opsw1.png
На КДПВ (Рисунок 1) изображен юзкейс OVS для построения песочницы для подготовки к замене наших устаревших VPN-маршрутизаторов на новые. Нужно сконфигурировать новые VPN-маршрутизаторы аналогично уже инсталлированным в нашей компании с теми же IP адресами, правилами фильтрации и настройками динамической маршрутизаци. И протестировать всё в песочнице, эмулирующей ISP (через которые соединяются VPN-маршрутизаторы) и сайты нашей локалки. Но повторюсь, эта статья не о сложностях настройки наших VPN-маршрутизаторов, а о том, как подключить их к нашей уютной виртуальной песочнице посредством VLAN вообще и OVS в частности. Начнём с самого начала, установив чистую копию ubuntu-14.04.1-server-amd64 с опцией «Virtual Machine host». После установки система имеет следующий вид:

  • Вывод утилит просмотра сетевых параметров:
   root@sandbox:~# ifconfig |grep -vE 'RX|TX|coll|inet6|MTU'
   eth0      Link encap:Ethernet  HWaddr 00:1b:78:9c:2b:fc  
             inet addr:10.0.7.1   Bcast:10.0.7.255  Mask:255.255.255.0
   
   lo        Link encap:Local Loopback  
             inet addr:127.0.0.1  Mask:255.0.0.0
   
   virbr0    Link encap:Ethernet  HWaddr 1a:70:19:e9:3c:c7  
             inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
   root@sandbox:~# route -n
   Kernel IP routing table
   Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
   0.0.0.0         10.0.7.254     0.0.0.0           UG    0      0        0 eth0
   10.0.7.0        0.0.0.0        255.255.255.0     U     0      0        0 eth0
   192.168.122.0   0.0.0.0        255.255.255.0     U     0      0        0 virbr0
   root@sandbox:~# cat /etc/network/interfaces |grep -v ^#
   auto lo
   iface lo inet loopback
   
   auto eth0
   iface eth0 inet static
       address 10.0.7.1
       netmask 255.255.255.0
       network 10.0.7.0
       broadcast 10.0.7.255
       gateway 10.0.7.254
       # dns-* options are implemented by the resolvconf package, if installed
       dns-nameservers 10.0.1.1
   root@sandbox:~# virsh net-list --all
   Name                 State      Autostart     Persistent
   ----------------------------------------------------------
   default              active     yes           yes
   root@sandbox:~# virsh net-dumpxml default
   <network>
     <name>default</name>
     <uuid>865fd53b-5bd5-430c-b7c7-664125dee9f6</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@sandbox:~# brctl show
   bridge name	bridge id		STP enabled	interfaces
   virbr0		8000.000000000000	yes

На КДПВ (Рисунок 1) изображен юзкейс OVS для построения песочницы для подготовки к замене наших устаревших VPN-маршрутизаторов на новые. Нужно сконфигурировать новые VPN-маршрутизаторы аналогично уже инсталлированным в нашей компании с теми же IP адресами, правилами фильтрации и настройками динамической маршрутизаци. И протестировать всё в песочнице, эмулирующей ISP (через которые соединяются VPN-маршрутизаторы) и сайты нашей локалки. Но повторюсь, эта статья не о сложностях настройки наших VPN-маршрутизаторов, а о том, как подключить их к нашей уютной виртуальной песочнице посредством VLAN вообще и OVS в частности. Начнём с самого начала, установив чистую копию ubuntu-14.04.1-server-amd64 с опцией «Virtual Machine host». После установки система имеет следующий вид:

  • Вывод утилит просмотра сетевых параметров:
   root@sandbox:~# ifconfig |grep -vE 'RX|TX|coll|inet6|MTU'
   eth0      Link encap:Ethernet  HWaddr 00:1b:78:9c:2b:fc  
             inet addr:10.0.7.1   Bcast:10.0.7.255  Mask:255.255.255.0
   
   lo        Link encap:Local Loopback  
             inet addr:127.0.0.1  Mask:255.0.0.0
   
   virbr0    Link encap:Ethernet  HWaddr 1a:70:19:e9:3c:c7  
             inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
   root@sandbox:~# route -n
   Kernel IP routing table
   Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
   0.0.0.0         10.0.7.254     0.0.0.0           UG    0      0        0 eth0
   10.0.7.0        0.0.0.0        255.255.255.0     U     0      0        0 eth0
   192.168.122.0   0.0.0.0        255.255.255.0     U     0      0        0 virbr0
   root@sandbox:~# cat /etc/network/interfaces |grep -v ^#
   auto lo
   iface lo inet loopback
   
   auto eth0
   iface eth0 inet static
       address 10.0.7.1
       netmask 255.255.255.0
       network 10.0.7.0
       broadcast 10.0.7.255
       gateway 10.0.7.254
       # dns-* options are implemented by the resolvconf package, if installed
       dns-nameservers 10.0.1.1
   root@sandbox:~# virsh net-list --all
   Name                 State      Autostart     Persistent
   ----------------------------------------------------------
   default              active     yes           yes
   root@sandbox:~# virsh net-dumpxml default
   <network>
     <name>default</name>
     <uuid>865fd53b-5bd5-430c-b7c7-664125dee9f6</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@sandbox:~# brctl show
   bridge name	bridge id		STP enabled	interfaces
   virbr0		8000.000000000000	yes	

Всё очень стандартно, ни чего необычного. На картинке всё еще проще:
Opsw2.png
Устанавливаем openvswitch:

apt-get install openvswitch-switch

После его установки ни каких изменений в сетевых параметрах не происходит, лишь запускается сервис OVS, ждущий наших распоряжений. Не будем заставлять его ждать. Вводим нижеприведенные команды с консоли или помещаем их во временный .sh скрипт и запускаем:

ovs-vsctl add-br ovs-br0
ovs-vsctl set port ovs-br0 tag=7
ovs-vsctl add-port ovs-br0 eth0
ovs-vsctl set port eth0 trunks=7,10,20,1010,1020,30,1030
ifconfig eth0 0
ifconfig ovs-br0 10.0.7.1/24 up
ip r add default via 10.0.7.254

переключаем хост в тегированный порт коммутатора

ovs-vsctl add-br ovs-br0

Создает почти пустой инстанс виртуального коммутатора, есть только один порт к которому и подключен одноименный внутренний интерфейс ovs-br0.

ovs-vsctl set port ovs-br0 tag=7

Конфигурируем этот порт как access-port для VLAN 7.

ovs-vsctl add-port ovs-br0 eth0

Добавляем к нашему коммутатору еще один порт, в который переключаем интерфейс eth0.

ovs-vsctl set port eth0 trunks=7,10,20,1010,1020,30,1030

делаем этот порт транковым для указанных VLAN ID. В принципе, параметр trunks можно вообще не указывать, тогда порт будет пропускать все VLAN ID.

ifconfig eth0 0

Обнуляем конфигурацию IP для eth0. Он больше не будет связан с IP стеком OS.

ifconfig ovs-br0 10.0.7.1/24 up

Вместо eth0 к IP стеку OS прикручиваем внутренний интерфейс ovs-br0.

ip r add default via 10.0.7.254

Ну и не забываем восстановить таблицу маршрутизации Переключаем хост в тегированный порт коммутатора

Мы в сети! (с)
  • Смотрим, что же изменилось в сетевых настройках:
   root@sandbox:~# ovs-vsctl show
   40952e4d-81ad-433b-b08b-f88ccd55f26a
       Bridge "ovs-br0"
           Port "ovs-br0"
               tag: 7
               Interface "ovs-br0"
                   type: internal
           Port "eth0"
               trunks: [7,10,20,1010,1020,30,1030]
               Interface "eth0"
       ovs_version: "2.0.2"
   root@sandbox:~# ifconfig |grep -vE 'RX|TX|coll|inet6|MTU'
   eth0      Link encap:Ethernet  HWaddr 00:1b:78:9c:2b:fc  
   
   lo        Link encap:Local Loopback  
             inet addr:127.0.0.1  Mask:255.0.0.0
   
   ovs-br0   Link encap:Ethernet  HWaddr 00:1b:78:9c:2b:fc  
             inet addr:10.0.7.1  Bcast:10.0.7.255  Mask:255.255.255.0
   
   virbr0    Link encap:Ethernet  HWaddr 32:b9:dd:38:09:f5  
             inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
   root@sandbox:~# route -n
   Kernel IP routing table
   Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
   0.0.0.0         10.0.7.254      0.0.0.0         UG    0      0        0 ovs-br0
   10.0.7.0        0.0.0.0         255.255.255.0   U     0      0        0 ovs-br0
   192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0

Ну и в виде картинки:
Opsw3.png
Рисунок 3: Установили openvswitch и подключили его к IP стеку OS вместо eth0. Интерфейс коммутатора virbr0 в дальнейшем изображать не будем, он нам не интересен и ни на что не влияет. Ничего неожиданного, всё логично и интуитивно понятно. Еще один приятный момент для тех, кто уже начал беспокоиться о том, где же размещать стартовые скрипты применения этой конфигурации. Ничего особо делать и не придется, конфигурация OVS вышеуказанными командами ovs-vsctl не только применяется, но и автоматически сохраняется, так что вам не нужно переживать о несовпадение текущей и сохраненной конфигурации OVS. А файл /etc/network/interfaces нам надо лишь малость обновить в связи с заменой интерфейса eth0 на ovs-br0:

root@sandbox:~# cat /etc/network/interfaces |grep -v ^#
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto ovs-br0
iface ovs-br0 inet static
	address 10.0.7.1
	netmask 255.255.255.0
	network 10.0.7.0
	broadcast 10.0.7.255
	gateway 10.0.7.254
	# dns-* options are implemented by the resolvconf package, if installed
	dns-nameservers 10.0.1.1

Но коммутатор в данный момент всего с двумя портами, как же подключить к нему наши 5 виртуальных машин? Тут есть как минимум 2 пути. Первый, наиболее очевидный, состоит в том, чтобы с помощью команды ovs-vsctl add-port добавить порт (access или транковый — на выбор).

ovs-vsctl add-port ovs-br0 vlan10 tag=10 -- set interface vlan10 type=internal

-- (две черточки) используется для выполнения нескольких команд ovs-vsctl в одну строку Затем можно будет прямо в GUI virt-manager'а выбрать его для подключения сетевого интерфейса виртуальной машины. Но мы пойдем более масштабируемым способом. При этом порты создавать вообще не нужно (как собственно и в стандартном linux core bridge). Вместо этого можно создать порт-группы для OVS. Каждая порт-группа предназначена для подключения VM к соответствующему VLAN. К сожалению, их настройка из GUI virt-manager'а недоступна, необходимо вручную подготовить простенький XML файл, описывающий необходимые порт-группы и затем применить его через API libvirt с помощью команды virsh, как указано ниже: XML-конфиг для конфигурации, показанной на Рисунке 1 Выполняем эти команды:

vi /tmp/ovs-network.xml
virsh net-define /tmp/ovs-network.xml
virsh net-start ovs-network
virsh net-autostart ovs-network
  • Пояснения:
vi /tmp/ovs-network.xml

копируем в этот файл вышеуказанное содержимое XML

virsh net-define /tmp/ovs-network.xml

конфигурируем новую сеть для KVM

virsh net-start ovs-network

запускаем её

virsh net-autostart ovs-network

делаем её запуск автоматическим

  • что бы удалить ненужную сеть
virsh net-destroy ovs-network
virsh net-autostart --disable ovs-network
virsh net-undefine ovs-network

изобразим полученное:
Opsw4.png
Рисунок4: Создали порт-группы для наших VM Создадим пару виртуальных машин VM1 и VM2 в virt-manager'е и при создании укажим Advanced options Virtual network 'ovs-network':

Bridge network

Пока оставим их выключенными подправим конфиги виртуалок

virsh edit VM1

Найдем секцию interface и добавим параметр portgroup

   <interface type='network'>
     <mac address='52:54:00:5e:b9:b2'/>
     <model type='virtio'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
   </interface>

Сделаеем так же для второй VM Если посмотреть сейчас состояние сетевых интерфейсов коммутатора и операционной системы, то увидим, что ни каких изменений не произошло. Порты на коммутаторе не добавились, лишних сетевых интерфейсов в системе не появилось. Теперь запустим обе VM:

  • и еще раз проверим состояние сетевых параметров хоста
   oot@sandbox:~# ovs-vsctl show
   40952e4d-81ad-433b-b08b-f88ccd55f26a
       Bridge "ovs-br0"
           Port "vnet0"
               tag: 10
               Interface "vnet0"
           Port "ovs-br0"
               tag: 7
               Interface "ovs-br0"
                   type: internal
           Port "eth0"
               trunks: [7, 10, 20, 1010, 1020, 30, 1030]
               Interface "eth0"
           Port "vnet1"
               tag: 20
               Interface "vnet1"
       ovs_version: "2.0.2"
   root@sandbox:~# ifconfig |grep -vE 'RX|TX|coll|inet6|MTU'
   eth0      Link encap:Ethernet  HWaddr 00:1b:78:9c:2b:fc  
   
   lo        Link encap:Local Loopback  
             inet addr:127.0.0.1  Mask:255.0.0.0
   
   ovs-br0   Link encap:Ethernet  HWaddr 00:1b:78:9c:2b:fc  
             inet addr:10.0.7.1  Bcast:10.0.7.255  Mask:255.255.255.0
   
   virbr0    Link encap:Ethernet  HWaddr 32:b9:dd:38:09:f5  
             inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
   
   vnet0     Link encap:Ethernet  HWaddr fe:54:00:5e:b9:b2  
   
   vnet1     Link encap:Ethernet  HWaddr fe:54:00:7f:40:d0  

Как видим, в коммутаторе добавились порты соответствующих порт-групп, а в системе добавилось пара интерфейсов с MAC-адресами, соответствующими VM (при выключение VM соответствующие порты и интерфейсы опять исчезнут).
Opsw5.png
Рисунок 5: запустили пару VM Еще упомяну, что 802.1q не единственная фича Open vSwitch, с его помощью можно организовать, например, бондинг двух интерфейсов и кое-что еще. Вот, собственно, и всё. Надеюсь, кому-то эта статья поможет решиться использовать Open vSwitch в своих проектах и просто песочницах вместо стандартного linux bridge.

ИСТОЧНИКИ