深入理解 Neutron -- OpenStack 网络实现:VXLAN 模式

来源:互联网 发布:教程网网站源码php 编辑:程序博客网 时间:2024/06/05 06:04

VXLAN 模式下,网络的架构跟 GRE 模式类似,所不同的是,不同节点之间通过 VXLAN 隧道互通,即虚拟化层是采用的 VXLAN 协议。基本结构如下图所示:

这里写图片描述

从这张架构图中,我们可以明显的看到有两个物理主机:计算节点和网络节点,这是因为采用了网络节点集中式的部署方式。

1) 在计算节点上创建虚拟机之后,虚拟机虚拟网卡通过linux bridge(这里的qbr)与br-int连起来。这里的A就是虚拟机的虚拟网卡,B是一个tap设备。C与D是连接linux bridge与br-int的一对tap设备,一般C叫qvb,D叫qvo。br-int是ovs虚拟化出来的网桥,作为虚拟机交换机的功能。br-int通过patch-tun连接到ovs虚拟化出来的网桥br-tun上,br-tun作为通信层,通过tunnel与其他计算节点和网络节点通信。

我们在这个架构中,使用的OpenvSwitch实现虚拟交换设备的,为什么会出现Linux Bridge呢?OpenStack Networking Administration Guide给出了这样的解释:

“Ideally, the TAP device vnet0 would be connected directly to the integration bridge, br-int. Unfortunately, this isn’t possible because of how OpenStack security groups are currently implemented. OpenStack uses iptables rules on the TAP devices such as vnet0 to implement security groups, and Open vSwitch is not compatible with iptables rules that are applied directly on TAP devices that are connected to an Open vSwitch port.”

其实就是说,OpenvSwitch不支持现在的OpenStack的实现方式,因为OpenStack是把iptables规则丢在TAP设备中,以此实现了安全组功能。没办法,所以用了一个折衷的方式,在中间加一层,用Linux Bridge来实现,这样,就多了一个qbr网桥。

2)在网络节点这边与计算节点类似,也有两个ovs的网桥br-tun与br-int。如果有多个虚拟机路由会通过tap设备连接到br-int。br-ex桥的一个接口挂载的物理接口 eth0上,网包将从这个接口发送到外部网络上。另外一个是 qg-xxx 这样的接口,是连接到 router 服务的网络名字空间中,里面绑定一个路由器的外部 IP,作为 NAT 时候的地址。

其中,节点网络配置如下所示,注意数据网络接口需要 IP 地址,因为是隧道协议需要底下的三层转发支持。

网络节点

  • eth0: 9.186.100.77/24 作为管理网络(同时也是公共网络)。
  • eth1: 10.0.100.77/24 作为数据网络接口。

计算节点

  • eth0: 9.186.100.88/24 作为管理网络(同时也是公共网络)。
  • eth1: 10.0.100.88/24 作为数据网络接口。

计算节点

计算节点上运行着虚拟机。如果不启用 DVR 特性,则所有的网络相关的服务,都在网络节点上进行。即计算节点上的网络只需要实现二层转发即可。

br-int

集成网桥 br-int 规则比较简单,作为一个正常的二层交换机使用。无论下面虚拟化层是哪种技术实现,集成网桥是看不到的,只知道根据 vlan 和 mac 进行转发。

Bridge br-int       fail_mode: secure       Port br-int           Interface br-int               type: internal       Port "qvoc4493802-43"           tag: 1           Interface "qvoc4493802-43"       Port patch-tun           Interface patch-tun               type: patch               options: {peer=patch-int}       Port "qvof47c62b0-db"           tag: 1           Interface "qvof47c62b0-db"

所连接接口除了从安全网桥过来的 qvo-xxx(每个虚拟机会有一个),就是一个往外的 patch-tun 接口,连接到 br-tun 网桥。

其中,qvo-xxx 接口上会为每个网络分配一个内部 vlan 号,比如这里是同一个网络启动了两台虚机,所以 tag 都为 1。

$ sudo ovs-ofctl dump-flows br-intNXST_FLOW reply (xid=0x4): cookie=0x0, duration=52889.682s, table=0, n_packets=161, n_bytes=39290, idle_age=13, priority=1 actions=NORMAL cookie=0x0, duration=52889.451s, table=23, n_packets=0, n_bytes=0, idle_age=52889, priority=0 actions=drop

转发规则表 0 中是对所有包进行 NORMAL,表 23 中是所有包直接丢弃、其实逻辑很简单,br-int 被当作一个二层交换机,根据 vlan 和 mac 进行转发。

br-tun

br-tun 作为虚拟化层网桥,规则就要复杂一些。 要将内部过来的网包进行合理甄别,内部带着正确 vlan tag 过来的,从正确的 tunnel 扔出去;外面带着正确 tunnel 号过来的,要改到对应的内部 vlan tag 扔到里面。

Bridge br-tun        fail_mode: secure        Port "vxlan-0a00644d"            Interface "vxlan-0a00644d"                type: vxlan                options: {df_default="true", in_key=flow, local_ip="10.0.100.88", out_key=flow, remote_ip="10.0.100.77"}        Port patch-int            Interface patch-int                type: patch                options: {peer=patch-tun}        Port br-tun            Interface br-tun                type: internal

其中,端口 br-tun 是内部端口,vxlan-0a00644d 这样的端口是向其它节点发包时候的 VXLAN 隧道端点,patch-int 端口通过一条管道连接到 br-int 上的 patch-tun 端口。

正常情况下,虚拟机的流量经过 br-int 转发,经过 patch-tun 端口,抵达 patch-int 端口,从而到达 br-tun 网桥,该网桥根据自身规则将合适的网包经过 VXLAN 隧道送出去。

$ sudo ovs-ofctl dump-flows br-tunNXST_FLOW reply (xid=0x4): cookie=0x0, duration=329.194s, table=0, n_packets=31, n_bytes=2906, idle_age=29, priority=1,in_port=1 actions=resubmit(,2) cookie=0x0, duration=325.847s, table=0, n_packets=14, n_bytes=1591, idle_age=33, priority=1,in_port=2 actions=resubmit(,4) cookie=0x0, duration=328.954s, table=0, n_packets=6, n_bytes=480, idle_age=321, priority=0 actions=drop cookie=0x0, duration=328.712s, table=2, n_packets=9, n_bytes=694, idle_age=33, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20) cookie=0x0, duration=328.465s, table=2, n_packets=22, n_bytes=2212, idle_age=29, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22) cookie=0x0, duration=328.223s, table=3, n_packets=0, n_bytes=0, idle_age=328, priority=0 actions=drop cookie=0x0, duration=50.703s, table=4, n_packets=12, n_bytes=1451, idle_age=33, priority=1,tun_id=0x3e9 actions=mod_vlan_vid:1,resubmit(,10) cookie=0x0, duration=327.979s, table=4, n_packets=2, n_bytes=140, idle_age=94, priority=0 actions=drop cookie=0x0, duration=327.742s, table=10, n_packets=12, n_bytes=1451, idle_age=33, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1 cookie=0x0, duration=38.551s, table=20, n_packets=9, n_bytes=694, hard_timeout=300, idle_age=33, hard_age=33, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:83:95:fa actions=load:0->NXM_OF_VLAN_TCI[],load:0x3e9->NXM_NX_TUN_ID[],output:2 cookie=0x0, duration=327.504s, table=20, n_packets=0, n_bytes=0, idle_age=327, priority=0 actions=resubmit(,22) cookie=0x0, duration=50.94s, table=22, n_packets=11, n_bytes=1334, idle_age=29, dl_vlan=1 actions=strip_vlan,set_tunnel:0x3e9,output:2 cookie=0x0, duration=327.261s, table=22, n_packets=10, n_bytes=808, idle_age=51, priority=0 actions=drop

这些才是真正处理 VXLAN 数据包的 rule,流程如下:

这里写图片描述

table0 中的规则

cookie=0x0, duration=329.194s, table=0, n_packets=31, n_bytes=2906, idle_age=29, priority=1,in_port=1 actions=resubmit(,2) cookie=0x0, duration=325.847s, table=0, n_packets=14, n_bytes=1591, idle_age=33, priority=1,in_port=2 actions=resubmit(,4) cookie=0x0, duration=328.954s, table=0, n_packets=6, n_bytes=480, idle_age=321, priority=0 actions=drop

从 1 端口(patch-int)过来的网包,扔给表 2 处理,从 2 端口(vxlan-0a00644d)进来的网包,扔给表 4 处理。即一个处理来自内部 vm 的,一个处理来自外面的 vxlan 隧道的

table2 中的规则

cookie=0x0, duration=53316.397s, table=2, n_packets=0, n_bytes=0, idle_age=53316, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)cookie=0x0, duration=53316.162s, table=2, n_packets=161, n_bytes=39562, idle_age=422, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22)

即里面过来的单播包,扔给表 20 处理;多播和广播包,扔给表 22 处理。

table3 中的规则

cookie=0x0, duration=328.223s, table=3, n_packets=0, n_bytes=

丢弃所有包。

table4 中的规则

cookie=0x0, duration=50.703s, table=4, n_packets=12, n_bytes=1451, idle_age=33, priority=1,tun_id=0x3e9 actions=mod_vlan_vid:1,resubmit(,10) cookie=0x0, duration=327.979s, table=4, n_packets=2, n_bytes=140, idle_age=94, priority=0 actions=drop

对于外部来的数据,匹配给定的 tunnel 号,添加对应的 vlan 号,扔给表 10 去学习一下后扔到 br-int 网桥。

table10 中的规则

cookie=0x0, duration=327.742s, table=10, n_packets=12, n_bytes=1451, idle_age=33, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1

主要作用是学习外部(从 tunnel)进来的包,往表 20 中添加对返程包的正常转发规则,并且从 patch-int 扔给 br-int。
使用了 openvswitch 的 learn 动作。该动作能根据处理的流来动态修改其它表中的规则。
具体来看 learn 规则:

  • table=20 说明是修改表 20 中的规则,后面是添加的规则内容;
  • NXM_OF_VLAN_TCI[0..11],匹配跟当前流同样的 VLAN 头,其中 NXM 是 Nicira Extensible Match 的缩写;
  • NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],包的目的 mac 跟当前流的源 mac 匹配;
  • load:0->NXM_OF_VLAN_TCI[],将 vlan 号改为 0;
  • load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],将 tunnel 号修改为当前的 tunnel 号;
  • output:NXM_OF_IN_PORT[],从当前入口发出。

table20 中的规则

cookie=0x0, duration=38.551s, table=20, n_packets=9, n_bytes=694, hard_timeout=300, idle_age=33, hard_age=33, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:83:95:fa actions=load:0->NXM_OF_VLAN_TCI[],load:0x3e9->NXM_NX_TUN_ID[],output:2cookie=0x0, duration=327.504s, table=20, n_packets=0, n_bytes=0, idle_age=327, priority=0 actions=resubmit(,22)

其中,第一条规则就是表 10 学习来的结果。对于 vlan 号为 1,目标 mac 是 fa:16:3e:83:95:fa(之前,我们从虚拟机内 ping 10.0.0.1,这个 mac 作为源 mac 从 tunnel 来过)的网包,去掉 vlan 号,添加当时的 vxlan 号,并从 tunnel 发出。
对于没学习到规则的网包,则扔给表 22 处理

table22 中的规则

cookie=0x0, duration=50.94s, table=22, n_packets=11, n_bytes=1334, idle_age=29, dl_vlan=1 actions=strip_vlan,set_tunnel:0x3e9,output:2cookie=0x0, duration=327.261s, table=22, n_packets=10, n_bytes=808, idle_age=51, priority=0 actions=drop

检查如果 vlan 号正确,则去掉 vlan 头后从 tunnel 扔出去。

网络节点

网络节点担负着进行网络服务的任务,包括DHCP、路由和高级网络服务等。一般包括三个网桥:br-tun、br-int 和 br-ex。

br-tun

跟计算节点类似,br-tun 作为虚拟化层网桥。 要将内部过来的网包进行合理甄别,内部带着正确 vlan tag 过来的,从正确的 tunnel 扔出去;外面带着正确 tunnel 号过来的,要改到对应的内部 vlan tag 扔到里面。

包括两个接口,跟其它接点形成 tunnel 的 vxlan-xxx 端口,以及跟 br-int 互连的 patch-int 端口。

Bridge br-tun        fail_mode: secure        Port br-tun            Interface br-tun                type: internal        Port "vxlan-0a006458"            Interface "vxlan-0a006458"                type: vxlan                options: {df_default="true", in_key=flow, local_ip="10.0.100.77", out_key=flow, remote_ip="10.0.100.88"}        Port patch-int            Interface patch-int                type: patch                options: {peer=patch-tun}

其中,端口 br-tun 是内部端口,vxlan-0a00644d 这样的端口是向其它节点发包时候的 VXLAN 隧道端点,patch-int 端口通过一条管道连接到 br-int 上的 patch-tun 端口。

查看 br-tun 上的转发规则:

$ sudo ovs-ofctl dump-flows br-tunNXST_FLOW reply (xid=0x4): cookie=0x0, duration=422.153s, table=0, n_packets=1073, n_bytes=107845, idle_age=96, priority=1,in_port=1 actions=resubmit(,2) cookie=0x0, duration=185.009s, table=0, n_packets=1076, n_bytes=102922, idle_age=96, priority=1,in_port=2 actions=resubmit(,4) cookie=0x0, duration=421.853s, table=0, n_packets=6, n_bytes=480, idle_age=62414, priority=0 actions=drop cookie=0x0, duration=421.552s, table=2, n_packets=1047, n_bytes=105725, idle_age=96, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20) cookie=0x0, duration=421.252s, table=2, n_packets=26, n_bytes=2120, idle_age=61953, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22) cookie=0x0, duration=420.939s, table=3, n_packets=0, n_bytes=0, idle_age=62420, priority=0 actions=drop cookie=0x0, duration=394.249s, table=4, n_packets=1076, n_bytes=102922, idle_age=96, priority=1,tun_id=0x3e9 actions=mod_vlan_vid:1,resubmit(,10) cookie=0x0, duration=420.628s, table=4, n_packets=0, n_bytes=0, idle_age=62420, priority=0 actions=drop cookie=0x0, duration=420.304s, table=10, n_packets=1076, n_bytes=102922, idle_age=96, priority=1 actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1 cookie=0x0, duration=1314.149s, table=20, n_packets=1006, n_bytes=101338, hard_timeout=300, idle_age=96, hard_age=95, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:52:7a:f2 actions=load:0->NXM_OF_VLAN_TCI[],load:0x3e9->NXM_NX_TUN_ID[],output:2 cookie=0x0, duration=419.977s, table=20, n_packets=0, n_bytes=0, idle_age=62419, priority=0 actions=resubmit(,22) cookie=0x0, duration=184.683s, table=22, n_packets=3, n_bytes=230, idle_age=61953, dl_vlan=1 actions=strip_vlan,set_tunnel:0x3e9,output:2 cookie=0x0, duration=419.668s, table=22, n_packets=23, n_bytes=1890, idle_age=61961, priority=0 actions=drop

这些规则跟计算节点上的 br-tun 网桥规则类似,组成如下图所示的转发逻辑。

这里写图片描述

table0中的规则:

从 1 端口(patch-int)进来的网包,扔给表 2 处理,从 2 端口(vxlan-0a00644d)进来的网包,扔给表 4 处理。即一个处理来自内部 br-int 的(这上面挂载着所有的网络服务,包括路由、DHCP 等),一个处理来自外面的 VXLAN 隧道的。

br-int

集成网桥 br-int 规则比较简单,作为一个正常的二层交换机使用。无论下面虚拟化层是哪种技术实现,集成网桥是看不到的,只知道根据 vlan 和 mac 进行转发。

Bridge br-int        fail_mode: secure        Port br-int            Interface br-int                type: internal        Port "qr-694450d6-f6"            tag: 1            Interface "qr-694450d6-f6"                type: internal        Port "tap13685e28-b0"            tag: 1            Interface "tap13685e28-b0"                type: internal        Port patch-tun            Interface patch-tun                type: patch                options: {peer=patch-int}

所连接接口包括:

  • tap-xxx,连接到网络 DHCP 服务的命名空间;
  • qr-xxx,连接到路由服务的命名空间;
  • 往外的 patch-tun 接口,连接到 br-tun 网桥。
    其中网络服务接口上会绑定内部 vlan 号,每个号对应一个网络。

br-ex

当数据从router中路由出来后,就会通过K、L传送到br-ex这个虚拟网桥上,而br-ex实际上是混杂模式加载在物理网卡上,实时接收着网络上的数据包。至此,我们的计算节点上的VM就可以与外部的网络进行自由的通信了。当然,前提是我们要给这个VM已经分配了float-ip。

核心接口有两个:一个是挂载的物理接口上,如 eth0,网包将从这个接口发送到外部网络上。
另外一个是 qg-xxx 这样的接口,是连接到 router 服务的网络名字空间中,里面绑定一个路由器的外部 IP,作为 NAT 时候的地址,另外,网络中的 floating IP 也放在这个网络名字空间中。

Bridge br-ex        Port "eth0"            Interface "eth0"        Port br-ex            Interface br-ex                type: internal        Port "qg-e76de35e-90"            Interface "qg-e76de35e-90"                type: internal

网桥的规则也很简单,作为一个正常的二层转发设备即可。

$ sudo ovs-ofctl dump-flows br-exNXST_FLOW reply (xid=0x4): cookie=0x0, duration=75072.257s, table=0, n_packets=352212, n_bytes=85641148, idle_age=0, hard_age=65534, priority=0 actions=NORMAL