VXLAN

Кратко о технологии VXLAN

Virtual Extensible LAN (VXLAN) является технологией сетевой виртуализации, созданной для решения проблем масштабируемости в больших системах облачных вычислений. Она использует схожую с VLAN технику для MAC инкапсуляции Layer 2 Ethernet кадров в UDP-пакеты. VXLAN позволяет создать виртуальную L2 сеть и растянуть ее поверх L3, таких сетей может быть 2^24, т.е. больше 16 млн. Технология используется облачными провайдерами, где виртуальная машина может спокойно мигрировать между географически разделенными датацентрами.

Вот тут можно почитать подробней: http://www.vmgu.ru/news/vmware-vxlan-for-vsphere

Пример простой конфигурации VXLAN на openvswitch под ALTLinux

Попробуем настроить VXLAN на ALTLinux в самом простом варианте. Вот топология:

host1 и host2 соединены по OpenVPN через Интернет, внешние IP я тут не показываю, host2 так же соединен с host3 по Ethetnet. В терминологии VXLAN эти IP адреса являются VTEP (VXLAN Tunnel End Poin). Можно конечно использовать внешниие IP для организации VTEP, но во первых это не безопасно, во вторых host2 не имеет белого IP и находится за NAT. Для работы VXLAN используется порт 8472 UDP, убедитесь, что он не закрыт на firewall.

Установка

На host1 у меня установлен ALTLinux P7, на host2 и host3 стоит ALTLinux P8.

На всех хостах необходимо установить пакет openvswitch.

# apt-get install openvswitch

Вообще openvswitch очень мощная штука, вот официальный сайт, там можно найти много интересного: http://openvswitch.org

Далее запускаем его, можно через service, можно так:

# /etc/init.d/openvswitch start
Starting ovsdb-server                                             [ DONE ]
Configuring Open vSwitch system IDs                               [ DONE ]
Starting ovs-vswitchd                                             [ DONE ]
Enabling remote OVSDB managers                                    [ DONE ]
iptables already has a rule for gre, not explicitly enabling      [ DONE ]

Настройка

Теперь можем конфигурировать наш виртуальных коммутатор, на host1 создадим бридж:

# ovs-vsctl add-br OVS-BR0

Так же создадим порт для соединения с host2.

# ovs-vsctl add-port OVS-BR0 vxlan1 -- set Interface vxlan1 type=vxlan options:remote_ip=192.168.101.10

Посмотрим конфигурацию:

# ovs-vsctl show
627126b6-ef0f-4ff9-9a4b-446bac7f93a6
    Bridge "OVS-BR0"
        Port "vxlan1"
            Interface "vxlan1"
                type: vxlan
                options: {remote_ip="192.168.101.10"}
        Port "OVS-BR0"
            Interface "OVS-BR0"
                type: internal
    ovs_version: "2.0.1"

Далее создадим бридж и порты на host2, тут их будет два:

# ovs-vsctl add-br OVS-BR0
# ovs-vsctl add-port OVS-BR0 vxlan1 -- set Interface vxlan1 type=vxlan options:remote_ip=192.168.101.1
# ovs-vsctl add-port OVS-BR0 vxlan2 -- set Interface vxlan2 type=vxlan options:remote_ip=192.168.7.47

Смотрим получившуюся конфигурацию:

# ovs-vsctl show
65a5df63-c1ba-43c8-b60c-4e0acc26d8ce
    Bridge "OVS-BR0"
        Port "OVS-BR0"
            Interface "OVS-BR0"
                type: internal
        Port "vxlan2"
            Interface "vxlan2"
                type: vxlan
                options: {remote_ip="192.168.7.47"}
        Port "vxlan1"
            Interface "vxlan1"
                type: vxlan
                options: {remote_ip="192.168.101.1"}
    ovs_version: "2.4.1"

Создадим мост и порт на host3:

# ovs-vsctl add-br OVS-BR0
# ovs-vsctl add-port OVS-BR0 vxlan1 -- set Interface vxlan1 type=vxlan options:remote_ip:192.168.7.120

Получившийся конфиг:

# ovs-vsctl show
bed739d4-ddd8-4813-846a-a4c305209c14
    Bridge "OVS-BR0"
        Port "OVS-BR0"
            Interface "OVS-BR0"
                type: internal
        Port "vxlan1"
            Interface "vxlan1"
                type: vxlan
                options: {remote_ip="192.168.7.120"}
    ovs_version: "2.4.1"

Теперь вешаем IP адреса на наши bridge-интерфейсы,

на host1:

[root@host1 ~]# ifconfig -a OVS-BR0 192.168.99.1 netmask 255.255.255.0

на host2:

[root@host2 ~]# ifconfig -a OVS-BR0 192.168.99.2 netmask 255.255.255.0

на host3:

[root@host3 ~]# ifconfig -a OVS-BR0 192.168.99.3 netmask 255.255.255.0

Проверка

Теперь проверяем, что получилось:

с host1:

[root@host1 ~]# ping -c 3 192.168.99.2
PING 192.168.99.2 (192.168.99.2) 56(84) bytes of data.
64 bytes from 192.168.99.2: icmp_req=1 ttl=64 time=24.8 ms
64 bytes from 192.168.99.2: icmp_req=2 ttl=64 time=13.3 ms
64 bytes from 192.168.99.2: icmp_req=3 ttl=64 time=13.0 ms
--- 192.168.99.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 13.073/17.075/24.817/5.477 ms
[root@host1 ~]# ping -c 3 192.168.99.3
PING 192.168.99.3 (192.168.99.3) 56(84) bytes of data.
64 bytes from 192.168.99.3: icmp_req=1 ttl=64 time=89.7 ms
64 bytes from 192.168.99.3: icmp_req=2 ttl=64 time=14.0 ms
64 bytes from 192.168.99.3: icmp_req=3 ttl=64 time=14.4 ms
--- 192.168.99.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 14.037/39.417/89.759/35.597 ms

с host2:

[root@sf-lenovo ~]# ping -c 3 192.168.99.1
PING 192.168.99.1 (192.168.99.1) 56(84) bytes of data.
64 bytes from 192.168.99.1: icmp_req=1 ttl=64 time=12.3 ms
64 bytes from 192.168.99.1: icmp_req=2 ttl=64 time=26.5 ms
64 bytes from 192.168.99.1: icmp_req=3 ttl=64 time=14.0 ms
--- 192.168.99.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 12.385/17.651/26.532/6.316 ms
[root@sf-lenovo ~]# ping -c 3 192.168.99.3
PING 192.168.99.3 (192.168.99.3) 56(84) bytes of data.
64 bytes from 192.168.99.3: icmp_req=1 ttl=64 time=2.82 ms
64 bytes from 192.168.99.3: icmp_req=2 ttl=64 time=0.726 ms
64 bytes from 192.168.99.3: icmp_req=3 ttl=64 time=0.708 ms
--- 192.168.99.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.708/1.419/2.825/0.994 ms

с host3:

[root@host3 ~]# ping -c 3 192.168.99.1
PING 192.168.99.1 (192.168.99.1) 56(84) bytes of data.
64 bytes from 192.168.99.1: icmp_req=1 ttl=64 time=14.4 ms
64 bytes from 192.168.99.1: icmp_req=2 ttl=64 time=15.0 ms
64 bytes from 192.168.99.1: icmp_req=3 ttl=64 time=14.3 ms
--- 192.168.99.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 14.355/14.629/15.078/0.348 ms
[root@host3 ~]# ping -c 3 192.168.99.3
PING 192.168.99.3 (192.168.99.3) 56(84) bytes of data.
64 bytes from 192.168.99.3: icmp_req=1 ttl=64 time=0.059 ms
64 bytes from 192.168.99.3: icmp_req=2 ttl=64 time=0.081 ms
64 bytes from 192.168.99.3: icmp_req=3 ttl=64 time=0.078 ms
--- 192.168.99.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.059/0.072/0.081/0.013 ms

Еще вот такую информацию можно посмотреть о бридже:

[root@host2 ~]# ovs-vsctl list bridge
_uuid               : 822177df-484a-4cac-a51f-912375dabe91
auto_attach         : []
controller          : []
datapath_id         : "0000de772182ac4c"
datapath_type       : ""
datapath_version    : "<unknown>"
external_ids        : {}
fail_mode           : []
flood_vlans         : []
flow_tables         : {}
ipfix               : []
mcast_snooping_enable: false
mirrors             : []
name                : "OVS-BR0"
netflow             : []
other_config        : {}
ports               : [5114a843-629c-4945-af2c-cd8004bae4c4, 52eb30a8-0035-41fe-bd59-6104c8ff8f06, dcd6f78f-1185-4ec3-8a62-ec9cd933951a]
protocols           : []
rstp_enable         : false
rstp_status         : {}
sflow               : []
status              : {}
stp_enable          : false

Если бы мы еще создали соединение между host1 и host3, то получилось бы кольцо, что хорошо для отказоустойчивости, но в таком случае нужно влючать протокол STP, что бы рвать петли, вот так (на всех openvswitch):

# ovs-vsctl set Bridge OVS-BR0 stp_enable=true

Настроенные бриджи можно посмотреть командой:

# ovs-vsctl list-br
OVS-BR0

А так список портов:

[root@host2 ~]# ovs-vsctl list-ports OVS-BR0
vxlan1
vxlan2

Одна из самых полезных команд, просмотр интерфейсов:

[root@host2 ~]# ovs-vsctl list interface
_uuid               : e2adc1d8-3458-49f2-b98a-86a68eeb21ae
admin_state         : up
bfd                 : {}
bfd_status          : {}
cfm_fault           : []
cfm_fault_status    : []
cfm_flap_count      : []
cfm_health          : []
cfm_mpid            : []
cfm_remote_mpids    : []
cfm_remote_opstate  : []
duplex              : []
error               : []
external_ids        : {}
ifindex             : 7
ingress_policing_burst: 0
ingress_policing_rate: 0
lacp_current        : []
link_resets         : 0
link_speed          : []
link_state          : up
lldp                : {}
mac                 : []
mac_in_use          : "de:77:21:82:ac:4c"
mtu                 : 1500
name                : "OVS-BR0"
ofport              : 65534
ofport_request      : []
options             : {}
other_config        : {}
statistics          : {collisions=0, rx_bytes=7801, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=83, tx_bytes=9911, tx_dropped=0, tx_errors=0, tx_packets=81}
status              : {driver_name=openvswitch}
type                : internal
_uuid               : a4f52dc0-4345-4c22-bb89-0c201254d4bf
admin_state         : up
bfd                 : {}
bfd_status          : {}
cfm_fault           : []
cfm_fault_status    : []
cfm_flap_count      : []
cfm_health          : []
cfm_mpid            : []
cfm_remote_mpids    : []
cfm_remote_opstate  : []
duplex              : []
error               : []
external_ids        : {}
ifindex             : 0
ingress_policing_burst: 0
ingress_policing_rate: 0
lacp_current        : []
link_resets         : 0
link_speed          : []
link_state          : up
lldp                : {}
mac                 : []
mac_in_use          : "62:78:d0:98:4e:42"
mtu                 : []
name                : "vxlan2"
ofport              : 2
ofport_request      : []
options             : {remote_ip="192.168.7.47"}
other_config        : {}
statistics          : {collisions=0, rx_bytes=1486, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=19, tx_bytes=57940, tx_dropped=0, tx_errors=0, tx_packets=1100}
status              : {tunnel_egress_iface="eth0", tunnel_egress_iface_carrier=up}
type                : vxlan
_uuid               : 2e78186f-5c3f-4e06-900a-2358b8df1b6f
admin_state         : up
bfd                 : {}
bfd_status          : {}
cfm_fault           : []
cfm_fault_status    : []
cfm_flap_count      : []
cfm_health          : []
cfm_mpid            : []
cfm_remote_mpids    : []
cfm_remote_opstate  : []
duplex              : []
error               : []
external_ids        : {}
ifindex             : 0
ingress_policing_burst: 0
ingress_policing_rate: 0
lacp_current        : []
link_resets         : 0
link_speed          : []
link_state          : up
lldp                : {}
mac                 : []
mac_in_use          : "fe:69:73:cf:d8:e3"
mtu                 : []
name                : "vxlan1"
ofport              : 3
ofport_request      : []
options             : {remote_ip="192.168.101.1"}
other_config        : {}
statistics          : {collisions=0, rx_bytes=1722, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=21, tx_bytes=58446, tx_dropped=0, tx_errors=0, tx_packets=1105}
status              : {tunnel_egress_iface="tun0", tunnel_egress_iface_carrier=up}
type                : vxlan

А вот так можно посмотреть таблицу mac-адресов:

[root@host2 ~]# ovs-appctl fdb/show OVS-BR0

 port  VLAN  MAC                Age
    3     0  06:50:58:05:ae:42    4
LOCAL     0  de:77:21:82:ac:4c    2
    2     0  a2:20:93:2f:29:40    2

Вот эти маки в arp таблице:

[root@host2 ~]# arp -a
? (192.168.99.3) at a2:20:93:2f:29:40 [ether] on OVS-BR0
? (192.168.99.1) at 06:50:58:05:ae:42 [ether] on OVS-BR0
? (192.168.7.47) at e4:11:5b:5c:58:ba [ether] on eth0

Автозапуск

Что бы это все стартовало автоматом, нужно создать конфигурацию для интерфейса OVS-BR0 в etcnet, вот пример файла options:

# cat /etc/net/ifaces/OVS-BR0/options
TYPE=bri
BOOTPROTO=static

И файла ipv4address:

# cat /etc/net/ifaces/OVS-BR0/ipv4address
192.168.99.3/24

Ну и не забываем включить сервис openvswitch в автозапуск:

# chkconfig openvswitch on