网络虚拟化--openvswitch(openstack的网络模型)

来源:互联网 发布:网络龙虎斗赌博揭秘 编辑:程序博客网 时间:2024/05/17 02:31

openvswitch

Open vSwitch即开放虚拟交换标准。是一款虚拟交换的软件。虚拟交换就是利用虚拟平台,通过软件的方式形成

交换机部件。跟传统的物理交换机相比,虚拟交换机同样具备众多优点,一是配置更加灵活。一台普通的服务器可以

配置出数十台甚至上百台虚拟交换机,且端口数目可以灵活选择。


实验环境:

centos7.3 3台。

node1 eth0 192.168.10.128/24 (仅主机 VMnet1)

eth1 (VMnet2)

网关 192.168.10.130

node2 eth0 192.168.10.129/24 (仅主机 VMnet1 ) (实现GRE 路由转发时用到,跨主机实现VLAN)

  eth1 (VMnet2)

网关 192.168.10.130

node3 eth0 192.168.10.129/24 (仅主机 VMnet1 )

  eth1 192.168.1.100 ( VMnet0 )

网关 192.168.1.1


安装openvswitch

他的安装包是在openstack的yum源里。所以配置openstack的yum源。

在CentOS中, ``extras``仓库提供用于启用 OpenStack 仓库的RPM包。 CentOS 默认启用``extras``仓库,

因此你可以直接安装用于启用OpenStack仓库的包。

# yum install centos-release-openstack-mitaka
在主机上升级包

# yum upgrade
安装openvswitch

# yum -y install openvswitch

启动openvswitch

# systemctl start openvswitch

创建一个桥设备

# ovs-vsctl add-br br-in# ovs-vsctl show1bfc1186-1781-4e91-96e9-5db9c334503e    Bridge br-in        Port br-in            Interface br-in                type: internal    ovs_version: "2.5.0"

此时一个软交换机已经诞生。他比brctl强大,多了一个VLan的功能。

ovs-vsctl 命令的使用:

show:ovsdb配置内容的查看

add-br:添加桥设备

del-br:删除桥

list-br:显示所有已定义的桥

add-port:为桥添加一个端口

del-port:移除一个端口    例:del-port br-in vif0.0

find port name=eth1:查找端口eth1的详细信息


现在激活那个eth1.然后将eth1添加至桥上

[root@localhost ~]# ip link set eth1 up[root@localhost ~]# ovs-vsctl add-port br-in eth1[root@localhost ~]# ovs-vsctl list-ports br-ineth1

查看br-in的状态

[root@localhost ~]# ovs-vsctl show1bfc1186-1781-4e91-96e9-5db9c334503e    Bridge br-in        Port br-in            Interface br-in                type: internal        Port "eth1"            Interface "eth1"    ovs_version: "2.5.0"


好了,现在启动虚拟机实例。(需要装qemu-kvm)

先创建桥接配置脚本。/etc/if-up

#!/bin/bashbridge=br-inif [ -n $1 ];then        ip link set $1 up        sleep 1        ovs-vsctl add-port $bridge $1        [ $? -eq 0 ] && exit 0 || exit 1else        echo 'Error:no port specified'        exit 2fi

启动虚拟机。

# qemu-kvm -name "test1" -m 256 -smp 1 \> -drive file=/images/cirros/cirros-0.3.5-x86_64-disk.img,media=disk,if=virtio \> -net nic,model=virtio,macaddr=52:54:00:00:00:01 \> -net tap,ifname=vif0.0,script=/etc/if-up,downscript=no \> --nographic

照此方法启动连个虚拟机。

配置两个虚拟机的IP地址。

test1 虚拟机

# ifconfig eth0 10.0.3.1 netmask 255.255.255.0 up# ifconfig eth0      Link encap:Ethernet  HWaddr 52:54:00:00:00:01            inet addr:10.0.3.1  Bcast:10.0.3.255  Mask:255.255.255.0。。。


test2 虚拟机

# ifconfig eth0 10.0.3.2 netmask 255.255.255.0 up# ifconfig eth0      Link encap:Ethernet  HWaddr 52:54:00:00:00:02            inet addr:10.0.3.2  Bcast:10.0.3.255  Mask:255.255.255.0。。。


两个虚拟机是可以互相ping通的。

# ping 10.0.3.2PING 10.0.3.2 (10.0.3.2): 56 data bytes64 bytes from 10.0.3.2: seq=0 ttl=64 time=5.327 ms64 bytes from 10.0.3.2: seq=1 ttl=64 time=0.037 ms。。。



接下来就可以开始试验了,将两个虚拟机放到不同的VLAN里面。

[root@localhost ~]# ovs-vsctl set port vif0.0 tag=10[root@localhost ~]# ovs-vsctl set port vif1.0 tag=11

上面的命令将vif0.0设置为10号VLan,vif1.0设置为11号VLan。


十分简单吧。

现在再来实现一个场景,就是test1和test2虚拟机在一个交换机上,并且属于不同的VLan。而test3虚拟在另

一个交换机上,并且,同在10号VLan中。如下图所示


先添加一个交换机。

# ovs-vsctl add-br br-test

修改/etc/if-up和if-down,将里面的桥由br-in改成br-test。

启动一个虚拟机test3,接在这个br-test这个交换机上。

# qemu-kvm -name "test3" -m 256 -smp 1 \-drive file=/images/cirros/test2.qcow2,media=disk,if=virtio \-net nic,model=virtio,macaddr=52:54:00:00:00:03 \-net tap,ifname=vif2.0,script=/etc/if-up2,downscript=/etc/if-down2 \--nographic \


配置网卡信息。

# ifconfig eth0 10.0.3.3 netmask 255.255.255.0 up# ifconfig eth0      Link encap:Ethernet  HWaddr 52:54:00:00:00:03            inet addr:10.0.3.3  Bcast:10.0.3.255  Mask:255.255.255.0

接着创建一对网卡,将两个交换机连在一起。

# ip link add switch0 type veth peer name switch1# ip link set switch0 up# ip link set switch1 up# ovs-vsctl add-port br-in switch0# ovs-vsctl add-port br-test switch1

将test3设置为10号VLan

# ovs-vsctl set port vif2.0 tag=10

测试一下看看。在test1上来看看。

# ping 10.0.3.3PING 10.0.3.3 (10.0.3.3): 56 data bytes64 bytes from 10.0.3.3: seq=0 ttl=64 time=1.734 ms## test1在 10 号VLAN,可以ping通test3# ping 10.0.3.2PING 10.0.3.2 (10.0.3.2): 56 data bytes --- 10.0.3.2 ping statistics ---3 packets transmitted, 0 packets received, 100% packet loss# 虽然test1和test2在同一台交换机上,但是没有在相同的VLan中。所以不能ping通、


添加网关,使得真机与虚拟机可以通信,或者说可以虚拟机上外网。

# ip netns add r0   #添加namespace# ip link add sif0 type veth peer name rif0 #添加一对网卡# ip link set sif0 up# ip link set rif0 up# ip link set rif0 netns r0  #把网卡rif0给r0# ovs-vsctl add-port br-in sif0 #把网卡sif0给br-in

激活添加在r0上的rif0网卡

# ip netns exec r0 ip link set rif0 up

并且给r0上网关添加一个IP地址。

# ip netns exec r0 ip addr add 10.0.3.254/24 dev rif0

配置dnsmasq
# yum -y install dnsmasq# ip netns exec r0 dnsmasq -F 10.0.3.200,10.0.3.230,86400 -i rif0 #配置dns服务器# ip netns exec r0 ss -unlState       Recv-Q Send-Q               Local Address:Port                              Peer Address:Port              UNCONN      0      0                                *:53                                           *:*                  UNCONN      0      0                                *:67                                           *:*                  UNCONN      0      0                               :::53                                          :::*                  



启动一个虚拟机实例。

# qemu-kvm -name "test6" -m 256 -smp 1 \-drive file=/images/cirros/test1.qcow2,media=disk,if=virtio \-net nic,model=virtio,macaddr=52:54:00:00:00:11 \-net tap,ifname=vif0.0,script=/etc/if-up,downscript=/etc/if-down \--nographic

查看虚拟机的配置。

# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00    inet 127.0.0.1/8 scope host lo    inet6 ::1/128 scope host        valid_lft forever preferred_lft forever2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000    link/ether 52:54:00:00:00:11 brd ff:ff:ff:ff:ff:ff    inet 10.0.3.230/24 brd 10.0.3.255 scope global eth0    inet6 fe80::5054:ff:fe00:11/64 scope link        valid_lft forever preferred_lft forever# route -nKernel IP routing tableDestination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         10.0.3.254      0.0.0.0         UG    0      0        0 eth010.0.3.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0

上述只是想让虚拟机和真机通信


最后来实现一下,如果第四台主机不仅不再一个交换机上,而且还不在一台真机上。这就有点复杂了,怎么实现呢?

可能我的描述还是有些不准确,请看看下面这张图。



test1 如何和test6去通信。(假设test1和test6处在同一个Vlan中),而不让test2和test6去通信。

这就需要GRE技术了。Generic Routing Encapsulation:通用路由封装。是一种隧道技术。

类似LVS的隧道技术,ip内有ip。


给两边的eth1网卡都加上IP,因为两台主机的eth1需要通信。

主机一:

# ip addr add 192.168.20.1/24 dev eth1

主机二:

# ip addr add 192.168.20.2/24 dev eth1

要确保。两台主机可以ping通。


在第一个主机上的br-in交换机上添加一个接口(gre0不存在没关系)

# ovs-vsctl add-port br-in gre0

将eth1配置为隧道。

# ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.20.2# ovs-vsctl list interface gre0_uuid               : ef8244cd-7d0e-4273-ade8-32ba231c6f4eadmin_state         : upbfd                 : {}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             : 0ingress_policing_burst: 0ingress_policing_rate: 0lacp_current        : []link_resets         : 0link_speed          : []link_state          : uplldp                : {}mac                 : []mac_in_use          : "8a:74:71:11:1b:64"mtu                 : []name                : "gre0"ofport              : 13ofport_request      : []options             : {remote_ip="192.168.20.2"}other_config        : {}statistics          : {collisions=0, rx_bytes=0, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=0, tx_bytes=338, tx_dropped=0, tx_errors=0, tx_packets=1}status              : {tunnel_egress_iface="eth1", tunnel_egress_iface_carrier=up}type                : gre


同样,在二号主机的eth1上通杨进行相同的配置,IP指向对方。

# ovs-vsctl add-port br-in gre0

# ovs-vsctl set interface gre0 type=gre option:remote_ip=192.168.20.1

观察一下两个主机的设置的交换机。

主机一:

[root@localhost ~]# ovs-vsctl show1bfc1186-1781-4e91-96e9-5db9c334503e    Bridge br-in        Port "vif2.0"            Interface "vif2.0"        Port "vif1.0"            Interface "vif1.0"        Port "gre0"            Interface "gre0"                type: gre                options: {remote_ip="192.168.20.2"}        Port br-in            Interface br-in                type: internal    ovs_version: "2.5.0"


主机二:

[root@localhost ~]# ovs-vsctl show88260195-15df-41d5-ab55-2401905c4c38    Bridge br-in        Port br-in            Interface br-in                type: internal        Port "vif2.0"            Interface "vif2.0"        Port "vif1.0"            Interface "vif1.0"        Port "gre0"            Interface "gre0"                type: gre                options: {remote_ip="192.168.20.1"}    ovs_version: "2.5.0"



OK,现在在主机一上启动一个虚拟机,发现,在主机二上的DHCP服务器也可以给主机一上的服务器提供IP了。

# ip addr show1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00    inet 127.0.0.1/8 scope host lo    inet6 ::1/128 scope host        valid_lft forever preferred_lft forever2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000    link/ether 52:54:00:00:00:02 brd ff:ff:ff:ff:ff:ff    inet 10.0.3.215/24 brd 10.0.3.255 scope global eth0    inet6 fe80::5054:ff:fe00:2/64 scope link        valid_lft forever preferred_lft forever


下来观察一下gre的基于隧道的通信技术。

# tcpdump -i eth1 -nn tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes22:23:04.841452 IP 192.168.20.1 > 192.168.20.2: GREv0, length 102: IP 10.0.3.215 > 10.0.3.230: ICMP echo request, id 26625, seq 40, length 6422:23:04.842654 IP 192.168.20.2 > 192.168.20.1: GREv0, length 102: IP 10.0.3.230 > 10.0.3.215: ICMP echo reply, id 26625, seq 40, length 6422:23:05.844358 IP 192.168.20.1 > 192.168.20.2: GREv0, length 102: IP 10.0.3.215 > 10.0.3.230: ICMP echo request, id 26625, seq 41, length 6422:23:05.846782 IP 192.168.20.2 > 192.168.20.1: GREv0, length 102: IP 10.0.3.230 > 10.0.3.215: ICMP echo reply, id 26625, seq 41, length 6422:23:06.248433 IP 192.168.20.1 > 192.168.20.2: GREv0, length 346: IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 52:54:00:00:00:01, length 29622:23:06.846852 IP 192.168.20.1 > 192.168.20.2: GREv0, length 102: IP 10.0.3.215 > 10.0.3.230: ICMP echo request, id 26625, seq 42, length 6422:23:06.848156 IP 192.168.20.2 > 192.168.20.1: GREv0, length 102: IP 10.0.3.230 > 10.0.3.215: ICMP echo reply, id 26625, seq 42, length 64


表面是192.168.20.1 在ping192.168.20.2,但是实质上有在里面封装了一个10.0.3.215 对10.0.3.230 的通信



还可以做个实验。一号主机的两台虚拟机一个在10号VLAN中,一个在11号VLAN中

二号主机的两台虚拟机一个在10号VLAN中,一个在11号VLAN中。

那么这下一号主机的两台主机是不能互相通信的。


最后再演示一下VXLAN的技术。

现在不要gre功能了,VXLAN本身支持VLAN的功能,有极大的提升了数量,还有基于隧道的技术。

所以要先取消gre。

# ovs-vsctl del-port br-in gre0

两个节点都需要去执行。

添加VXLAN

主机一:

# ovs-vsctl add-port br-in vx0 
ovs-vsctl: Error detected while setting up 'vx0'.  See ovs-vswitchd log for details.

# ovs-vsctl set interface vx0 type=vxlan options:remote_ip=192.168.20.2


主机二:

# ovs-vsctl add-port br-in vx0

ovs-vsctl: Error detected while setting up 'vx0'.  See ovs-vswitchd log for details.

# ovs-vsctl set interface vx0 type=vxlan options:remote_ip=192.168.20.1



OK了,看,是不是和gre很像很像。


最后配置整个openstack 的网络模型。整个网络模型是这样的。再由一个节点让,所有的内部虚拟机可以去访问

外部网络,同时呢,又可以让外部网络可以访问内部虚拟机网络。

这下就需要第三台主机了,这台主机专门去做网络节点,负责网络数据的转发(内网与外网之间)

这台主机的模型是这样的。3块网卡,一个桥接(用来与外部网络去通信)

一个仅主机(所有的内部网络使用的线路,有可能包括openstack的主控制节点

一个仅主机(所有虚拟机计算几点,加上网络节点)


好了。这个节点需要2个虚拟交换机,一个使用openvswitch去做,因为需要VXLan创建的Vlan技术。

第一个交换机与外部网络相接,可以直接使用brctl命令去创造。

我这里直接用配置文件了,eth1网卡是桥接网卡。

ifcfg-eth1

DEVICE="eth1"BOOTPROTO="static"ONBOOT="yes"NM_CONTOLLED="no"BRIDGE="br-ex"

ifcfg-br-ex

DEVICE="br-ex"BOOTPROTO="static"ONBOOT="yes"IPADDR="192.168.1.30"NETMASK="255.255.255.0"GATEWAY="192.168.1.1"NM_CONTOLLED="no"TYPE="Bridge"

好了创建netns。

# ip netns add r0

# ip link add sin0 type veth peer name rin0

# ip link add sex0 type veth peer name rex0

# ip link set sin0 up

# ip link set sex0 up

# ip link set rin0 netns r0

# ip link set rex0 netns r0



创建新的内部桥

(在新主机上(网络控制节点))

# ovs-vsctl add-br br-in

# ovs-vsctl add-port br-in gre0

# ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.20.2

(在虚拟机主机上(192.168.20.2)再创建一个gre隧道,与之通信)


添加一对网卡。一个在r0上,一个在br-in上

# ip netns exec r0 ifconfig rin0 10.0.1.254/24 up

# ovs-vsctl add-port br-in sin0


OK,现在内部的虚拟机就可以去和10.0.1.254这个网关去联系了。

# ping 10.0.1.254(这里是10.0.1.1主机)
PING 10.0.1.254 (10.0.1.254): 56 data bytes
64 bytes from 10.0.1.254: seq=0 ttl=64 time=12.323 ms
64 bytes from 10.0.1.254: seq=1 ttl=64 time=2.020 ms


看看抓包结果。

01:27:12.187837 IP 192.168.20.3 > 192.168.20.2: GREv0, length 102: IP 10.0.1.254 > 10.0.1.1: ICMP echo reply, id 29953, seq 19, length 64


现在配置br-ex(注意:一对网卡,在r0上的需要配置Ip,在交换机上的不需要配置IP)

# brctl addif br-ex sex0

# ip netns exec r0 ifconfig rex0 192.168.1.30/24 up

# ip netns exec r0 sysctl -w net.ipv4.ip_forward=1

net.ipv4.ip_forward = 1


此时。内部网络的虚拟机已经可以去PING通网络调度节点上的外部地址了。

# ping 192.168.1.30
PING 192.168.1.30 (192.168.1.30): 56 data bytes
64 bytes from 192.168.1.30: seq=0 ttl=64 time=2.452 ms
64 bytes from 192.168.1.30: seq=1 ttl=64 time=2.754 ms
64 bytes from 192.168.1.30: seq=2 ttl=64 time=1.045 ms
64 bytes from 192.168.1.30: seq=3 ttl=64 time=5.689 ms


配置网络IP地址转换。

# ip netns exec r0 iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -j SNAT --to-source 192.168.1.30

此时,内部虚拟机已经可以去ping通网络调度主机的局域网内的主机了。


现在开始内外映射去做。内网对外网的IP访问。

所以先删掉上面配置的ip。

# ip netns exec r0 iptables -t nat -F


配置地址映射。(这个192.168.1.31是专门映射给内部虚拟机使用的)

# ip netns exec r0 ifconfig rex0:0 192.168.1.31/24 up

添加两条规则

# ip netns exec r0 iptables -t nat -A POSTROUTING -s 10.0.1.1/24 -j SNAT --to-source 192.168.1.31

# ip netns exec r0 iptables -t nat -A PREROUTING -d 192.168.1.31 -j DNAT --to-destination 10.0.1.1

好了。此时,连我的windows都可以ping通虚拟机了。



抓包得到:(192.168.1.103是windows的IP)

01:53:25.266024 IP 192.168.20.2.41374 > 192.168.20.1.4789: VXLAN, flags [I] (0x08), vni 0
IP 192.168.1.103 > 10.0.1.1: ICMP echo request, id 1, seq 10264, length 40
01:53:25.266459 IP 192.168.20.1.34056 > 192.168.20.2.4789: VXLAN, flags [I] (0x08), vni 0
IP 10.0.1.1 > 192.168.1.103: ICMP echo reply, id 1, seq 10264, length 40
01:53:25.270680 IP 192.168.20.2 > 192.168.20.3: GREv0, key=0x0, length 82: IP 10.0.1.1 > 192.168.1.103: ICMP echo reply, id 1, seq 10264, length 40

1 0
原创粉丝点击