您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
OpenStack 网络实现(上)
 
作者:yuwenge 来源:About云 发布于 2015-11-19
  3177  次浏览      14
 

深入理解 Neutron -- OpenStack 网络实现(1):GRE 模式

概述

Neutron 的设计目标是实现“网络即服务”,为了达到这一目标,在设计上遵循了基于“软件定义网络”实现网络虚拟化的原则,在实现上充分利用了 Linux 系统上的各种网络相关的技术。

理解了 Linux 系统上的这些概念将有利于快速理解 Neutron 的原理和实现。

涉及的 Linux 网络技术

bridge:网桥,Linux中用于表示一个能连接不同网络设备的虚拟设备,linux中传统实现的网桥类似一个hub设备,而ovs管理的网桥一般类似交换机。

br-int:bridge-integration,综合网桥,常用于表示实现主要内部网络功能的网桥。

br-ex:bridge-external,外部网桥,通常表示负责跟外部网络通信的网桥。

GRE:General Routing Encapsulation,一种通过封装来实现隧道的方式。在openstack中一般是基于L3的gre,即original pkt/GRE/IP/Ethernet

VETH:虚拟ethernet接口,通常以pair的方式出现,一端发出的网包,会被另一端接收,可以形成两个网桥之间的通道。

qvb:neutron veth, Linux Bridge-side

qvo:neutron veth, OVS-side

TAP设备:模拟一个二层的网络设备,可以接受和发送二层网包。

TUN设备:模拟一个三层的网络设备,可以接受和发送三层网包。

iptables:Linux 上常见的实现安全策略的防火墙软件。

Vlan:虚拟 Lan,同一个物理 Lan 下用标签实现隔离,可用标号为1-4094。

VXLAN:一套利用 UDP 协议作为底层传输协议的 Overlay 实现。一般认为作为 VLan 技术的延伸或替代者。

namespace:用来实现隔离的一套机制,不同 namespace 中的资源之间彼此不可见。

基本概念

Neutron管理下面的实体:

网络:隔离的 L2 域,可以是虚拟、逻辑或交换,同一个网络中的主机彼此 L2 可见。

子网:隔离的 L3 域,IP 地址块。其中每个机器有一个 IP,同一个子网的主机彼此 L3 可见。

端口:网络上虚拟、逻辑或交换端口。 所有这些实体都是虚拟的,拥有自动生成的唯一标示id,支持CRUD功能,并在数据库中跟踪记录状态。

网络

隔离的 L2 广播域,一般是创建它的用户所有。用户可以拥有多个网络。网络是最基础的,子网和端口都需要关联到网络上。

网络上可以有多个子网。同一个网络上的主机一般可以通过交换机或路由器连通起来。

子网

隔离的 L3 域,子网代表了一组分配了 IP 的虚拟机。每个子网必须有一个 CIDR 和关联到一个网络。IP 可以从 CIDR 或者用户指定池中选取。

子网可能会有一个网关、一组 DNS 和主机路由。不同子网之间 L2 是互相不可见的,必须通过一个三层网关(即路由器)经过 L3 上进行通信。

端口

可以进出流量的接口,往往绑定上若干 MAC 地址和 IP 地址,以进行寻址。一般为虚拟交换机上的虚拟接口。

虚拟机挂载网卡到端口上,通过端口访问网络。当端口有 IP 的时候,意味着它属于某个子网。

抽象系统架构

无论哪种具体的网络虚拟化实现,在启用 DVR 特性(J 版本以后支持)之前,所有流量(东西向、南北向)都需要经过网络节点的转发;DVR 特性则允许东西向流量和带有 Floating IP 的南北向流量不经过网络节点的转发,直接从计算节点的外部网络出去。

GRE 模式

下图给出了在OpenStack中网络实现的一个简化的架构示意。

一般的,OpenStack中网络实现包括vlan、gre、vxlan 等模式,此处以gre模式为例。

在OpenStack中,所有网络有关的逻辑管理均在Network节点中实现,例如DNS、DHCP以及路由等。Compute节点上只需要对所部属的虚拟机提供基本的网络功能支持,包括隔离不同租户的虚拟机和进行一些基本的安全策略管理(即security group)。

计算节点

Compute节点上包括两台虚拟机VM1和VM2,分别经过一个网桥(如qbr-XXX)连接到 br-int 网桥上。br-int 网桥再经过 br-tun 网桥(物理网络是 GRE 实现)连接到物理主机外部网络。

对于物理网络通过vlan来隔离的情况,则一般会存在一个br-eth网桥,替代 br-tun 网桥。

qbr

在VM1中,虚拟机的网卡实际上连接到了物理机的一个TAP设备(即A,常见名称如tap-XXX)上,A则进一步通过VETH pair(A-B)连接到网桥qbr-XXX的端口vnet0(端口B)上,之后再通过VETH pair(C-D)连到br-int网桥上。一般C的名字格式为qvb-XXX,而D的名字格式为qvo-XXX。注意它们的名称除了前缀外,后面的id都是一样的,表示位于同一个虚拟机网络到物理机网络的连接上。

之所以TAP设备A没有直接连接到网桥br-int上,是因为OpenStack需要通过iptables实现security group的安全策略功能。目前openvswitch并不支持应用iptables规则的Tap设备。

因为qbr的存在主要是为了辅助iptables来实现security group功能,有时候也被称为firewall bridge。详见security group部分的分析【后面篇章会给出】。

br-int

一个典型的br-int的端口如下所示:

Bridge br-int
Port "qvo-XXX"
tag: 1
Interface "qvo-XXX"
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port br-int
Interface br-int
type: internal

其中br-int为内部端口。

端口patch-tun(即端口E,端口号为1)连接到br-tun上,实现到外部网络的隧道。 端口qvo-XXX(即端口D,端口号为2)带有tag1,说明这个口是一个1号vlan的access端口。虚拟机发出的从该端口到达br-int的网包将被自动带上vlan tag 1,而其他带有vlan tag 1的网包则可以在去掉vlan tag后从该端口发出(具体请查询vlan access端口)。这个vlan tag是用来实现不同网络相互隔离的,比如租户创建一个网络(neutron net-create),则会被分配一个唯一的vlan tag。

br-int在GRE模式中作为一个NORMAL交换机使用,因此有效规则只有一条正常转发。如果两个在同一主机上的vm属于同一个tenant的(同一个vlan tag),则它们之间的通信只需要经过br-int即可。

# ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=10727.864s, table=0, n_packets=198, n_bytes=17288, idle_age=13, priority=1 actions=NORMAL

br-tun

一个典型的br-tun上的端口类似:

Bridge br-tun
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Port "gre-1"
Interface "gre-1"
type: gre
options: {in_key=flow, local_ip="10.0.0.101", out_key=flow, remote_ip="10.0.0.100"}
Port br-tun
Interface br-tun
type: internal

其中patch-int(即端口F,端口号为1)是连接到br-int上的veth pair的端口,gre-1口(即端口G,端口号为2)对应vm到外面的隧道。

gre-1端口是虚拟gre端口,当网包发送到这个端口的时候,会经过内核封包,然后从10.0.0.101发送到10.0.0.100,即从本地的物理网卡(10.0.0.101)发出。

br-tun将带有vlan tag的vm跟外部通信的流量转换到对应的gre隧道,这上面要实现主要的转换逻辑,规则要复杂,一般通过多张表来实现。

典型的转发规则为:

# ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=10970.064s, table=0, n_packets=189, n_bytes=16232, idle_age=16, priority=1,in_port=1 actions=resubmit(,1)
cookie=0x0, duration=10906.954s, table=0, n_packets=29, n_bytes=5736, idle_age=16, priority=1,in_port=2 actions=resubmit(,2)
cookie=0x0, duration=10969.922s, table=0, n_packets=3, n_bytes=230, idle_age=10962, priority=0 actions=drop
cookie=0x0, duration=10969.777s, table=1, n_packets=26, n_bytes=5266, idle_age=16, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
cookie=0x0, duration=10969.631s, table=1, n_packets=163, n_bytes=10966, idle_age=21, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)
cookie=0x0, duration=688.456s, table=2, n_packets=29, n_bytes=5736, idle_age=16, priority=1,tun_id=0x1 actions=mod_vlan_vid:1,resubmit(,10)
cookie=0x0, duration=10969.488s, table=2, n_packets=0, n_bytes=0, idle_age=10969, priority=0 actions=drop
cookie=0x0, duration=10969.343s, table=3, n_packets=0, n_bytes=0, idle_age=10969, priority=0 actions=drop
cookie=0x0, duration=10969.2s, table=10, n_packets=29, n_bytes=5736, idle_age=16, 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=682.603s, table=20, n_packets=26, n_bytes=5266, hard_timeout=300, idle_age=16, hard_age=16, priority=1,vlan_tci=0x0001/0x0fff, dl_dst=fa:16:3e:32:0d:db actions=load:0->NXM_OF_VLAN_TCI[],load:0x1->NXM_NX_TUN_ID[],output:2
cookie=0x0, duration=10969.057s, table=20, n_packets=0, n_bytes=0, idle_age=10969, priority=0 actions=resubmit(,21)
cookie=0x0, duration=688.6s, table=21, n_packets=161, n_bytes=10818, idle_age=21, priority=1,dl_vlan=1 actions=strip_vlan,set_tunnel:0x1,output:2
cookie=0x0, duration=10968.912s, table=21, n_packets=2, n_bytes=148, idle_age=689, priority=0 actions=drop

其中,表0中有3条规则:从端口1(即patch-int)来的,扔到表1,从端口2(即gre-1)来的,扔到表2。

cookie=0x0, duration=10970.064s, table=0, n_packets=189, n_bytes=16232,
 idle_age=16, priority=1,in_port=1 actions=resubmit(,1)
cookie=0x0, duration=10906.954s, table=0, n_packets=29, n_bytes=5736, idle_age=16, priority=1,in_port=2 actions=resubmit(,2)
cookie=0x0, duration=10969.922s, table=0, n_packets=3, n_bytes=230, idle_age=10962, priority=0 actions=drop

表1有2条规则:如果是单播(00:00:00:00:00:00/01:00:00:00:00:00),则扔到表20;如果是多播等(01:00:00:00:00:00/01:00:00:00:00:00),则扔到表21。

cookie=0x0, duration=10969.777s, table=1, n_packets=26, n_bytes=5266, 
idle_age=16, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
cookie=0x0, duration=10969.631s, table=1, n_packets=163, n_bytes=10966, idle_age=21, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)

表2有2条规则:如果是tunnel 1的网包,则修改其vlan id为1,并扔到表10;非tunnel 1的网包,则丢弃。

cookie=0x0, duration=688.456s, table=2, n_packets=29, n_bytes=5736, 
idle_age=16, priority=1,tun_id=0x1 actions=mod_vlan_vid:1,resubmit(,10)
cookie=0x0, duration=10969.488s, table=2, n_packets=0, n_bytes=0, idle_age=10969, priority=0 actions=drop

表3只有1条规则:丢弃。

表10有一条规则,基于learn行动来创建反向(从gre端口抵达,且目标是到vm的网包)的规则。learn行动并非标准的openflow行动,是openvswitch自身的扩展行动,这个行动可以根据流内容动态来修改流表内容。这条规则首先创建了一条新的流(该流对应vm从br-tun的gre端口发出的规则):其中table=20表示规则添加在表20;NXM_OF_VLAN_TCI[0..11]表示匹配包自带的vlan id;NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]表示L2目标地址需要匹配包的L2源地址;load:0->NXM_OF_VLAN_TCI[],去掉vlan,load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],添加tunnel号为原始tunnel号;output:NXM_OF_IN_PORT[],发出端口为原始包抵达的端口。最后规则将匹配的网包从端口1(即patch-int)发出。

cookie=0x0, duration=10969.2s, table=10, n_packets=29, n_bytes=5736, idle_age=16,
 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

表20中有两条规则,其中第一条即表10中规则利用learn行动创建的流表项,第2条提交其他流到表21。

cookie=0x0, duration=682.603s, table=20, n_packets=26, n_bytes=5266, hard_timeout=300,
 idle_age=16, hard_age=16, priority=1,vlan_tci=0x0001/0x0fff,
dl_dst=fa:16:3e:32:0d:db actions=load:0->NXM_OF_VLAN_TCI[],load:0x1->NXM_NX_TUN_ID[],output:2
cookie=0x0, duration=10969.057s, table=20, n_packets=0, n_bytes=0, idle_age=10969, priority=0 actions=resubmit(,21)

表21有2条规则,第一条是匹配所有目标vlan为1的网包,去掉vlan,然后从端口2(gre端口)发出。第二条是丢弃。

cookie=0x0, duration=688.6s, table=21, n_packets=161, n_bytes=10818,
 idle_age=21, priority=1,dl_vlan=1 actions=strip_vlan,set_tunnel:0x1,output:2
cookie=0x0, duration=10968.912s, table=21, n_packets=2, n_bytes=148, idle_age=689, priority=0 actions=drop

这些规则所组成的整体转发逻辑如下图所示。

网络节点

br-tun

Bridge br-tun
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Port "gre-2"
Interface "gre-2"
type: gre
options: {in_key=flow, local_ip="10.0.0.100", out_key=flow, remote_ip="10.0.0.101"}

Compute节点上发往GRE隧道的网包最终抵达Network节点上的br-tun,该网桥的规则包括:

# ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=19596.862s, table=0, n_packets=344, n_bytes=66762, idle_age=4, priority=1,in_port=1 actions=resubmit(,1)
cookie=0x0, duration=19537.588s, table=0, n_packets=625, n_bytes=125972, idle_age=4, priority=1,in_port=2 actions=resubmit(,2)
cookie=0x0, duration=19596.602s, table=0, n_packets=2, n_bytes=140, idle_age=19590, priority=0 actions=drop
cookie=0x0, duration=19596.343s, table=1, n_packets=323, n_bytes=65252, idle_age=4, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
cookie=0x0, duration=19596.082s, table=1, n_packets=21, n_bytes=1510, idle_age=5027, priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)
cookie=0x0, duration=9356.289s, table=2, n_packets=625, n_bytes=125972, idle_age=4, priority=1,tun_id=0x1 actions=mod_vlan_vid:1,resubmit(,10)
cookie=0x0, duration=19595.821s, table=2, n_packets=0, n_bytes=0, idle_age=19595, priority=0 actions=drop
cookie=0x0, duration=19595.554s, table=3, n_packets=0, n_bytes=0, idle_age=19595, priority=0 actions=drop
cookie=0x0, duration=19595.292s, table=10, n_packets=625, n_bytes=125972, idle_age=4, 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=9314.338s, table=20, n_packets=323, n_bytes=65252, hard_timeout=300, idle_age=4, hard_age=3, priority=1,vlan_tci=0x0001/0x0fff, dl_dst=fa:16:3e:cb:11:f6 actions=load:0->NXM_OF_VLAN_TCI[],load:0x1->NXM_NX_TUN_ID[],output:2
cookie=0x0, duration=19595.026s, table=20, n_packets=0, n_bytes=0, idle_age=19595, priority=0 actions=resubmit(,21)
cookie=0x0, duration=9356.592s, table=21, n_packets=9, n_bytes=586, idle_age=5027, priority=1,dl_vlan=1 actions=strip_vlan,set_tunnel:0x1,output:2
cookie=0x0, duration=19594.759s, table=21, n_packets=12, n_bytes=924, idle_age=5057, priority=0 actions=drop

这些规则跟Compute节点上br-tun的规则相似,完成tunnel跟vlan之间的转换。

br-int

Bridge br-int
Port "qr-ff19a58b-3d"
tag: 1
Interface "qr-ff19a58b-3d"
type: internal
Port br-int
Interface br-int
type: internal
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port "tap4385f950-8b"
tag: 1
Interface "tap4385f950-8b"
type: internal

该集成网桥上挂载了很多进程来提供网络服务,包括路由器、DHCP服务器等。这些进程不同的租户可能都需要,彼此的地址空间可能冲突,也可能跟物理网络的地址空间冲突,因此都运行在独立的网络名字空间中。 规则跟computer节点的br-int规则一致,表现为一个正常交换机。

# ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=18198.244s, table=0, n_packets=849, n_bytes=164654, idle_age=43, priority=1 actions=NORMAL

网络名字空间

在linux中,网络名字空间可以被认为是隔离的拥有单独网络栈(网卡、路由转发表、iptables)的环境。网络名字空间经常用来隔离网络设备和服务,只有拥有同样网络名字空间的设备,才能看到彼此。 可以用ip netns list命令来查看已经存在的名字空间。

# ip netns
qdhcp-88b1609c-68e0-49ca-a658-f1edff54a264
qrouter-2d214fde-293c-4d64-8062-797f80ae2d8f

qdhcp开头的名字空间是dhcp服务器使用的,qrouter开头的则是router服务使用的。 可以通过 ip netns exec namespaceid command 来在指定的网络名字空间中执行网络命令,例如

# ip netns exec qdhcp-88b1609c-68e0-49ca-a658-f1edff54a264 ip addr
71: ns-f14c598d-98: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:10:2f:03 brd ff:ff:ff:ff:ff:ff
inet 10.1.0.3/24 brd 10.1.0.255 scope global ns-f14c598d-98
inet6 fe80::f816:3eff:fe10:2f03/64 scope link
valid_lft forever preferred_lft forever

可以看到,dhcp服务的网络名字空间中只有一个网络接口“ns-f14c598d-98”,它连接到br-int的tapf14c598d-98接口上。

dhcp 服务

dhcp服务是通过dnsmasq进程(轻量级服务器,可以提供dns、dhcp、tftp等服务)来实现的,该进程绑定到dhcp名字空间中的br-int的接口上。可以查看相关的进程。

# ps -fe | grep 88b1609c-68e0-49ca-a658-f1edff54a264
nobody 23195 1 0 Oct26 ? 00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=ns-f14c598d-98 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/88b1609c-68e0-49ca-a658-f1edff54a264/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/88b1609c-68e0-49ca-a658-f1edff54a264/host --dhcp-optsfile=/var/lib/neutron/dhcp/88b1609c-68e0-49ca-a658-f1edff54a264/opts --dhcp-script=/usr/bin/neutron-dhcp-agent-dnsmasq-lease-update --leasefile-ro --dhcp-range=tag0,10.1.0.0,static,120s --conf-file= --domain=openstacklocal
root 23196 23195 0 Oct26 ? 00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=ns-f14c598d-98 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/88b1609c-68e0-49ca-a658-f1edff54a264/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/88b1609c-68e0-49ca-a658-f1edff54a264/host --dhcp-optsfile=/var/lib/neutron/dhcp/88b1609c-68e0-49ca-a658-f1edff54a264/opts --dhcp-script=/usr/bin/neutron-dhcp-agent-dnsmasq-lease-update --leasefile-ro --dhcp-range=tag0,10.1.0.0,static,120s --conf-file= --domain=openstacklocal

router服务

首先,要理解什么是router,router是提供跨subnet的互联功能的。比如用户的内部网络中主机想要访问外部互联网的地址,就需要router来转发(因此,所有跟外部网络的流量都必须经过router)。目前router的实现是通过iptables进行的。 同样的,router服务也运行在自己的名字空间中,可以通过如下命令查看:

# ip netns exec qrouter-2d214fde-293c-4d64-8062-797f80ae2d8f ip addr
66: qg-d48b49e0-aa: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:5c:a2:ac brd ff:ff:ff:ff:ff:ff
inet 172.24.4.227/28 brd 172.24.4.239 scope global qg-d48b49e0-aa
inet 172.24.4.228/32 brd 172.24.4.228 scope global qg-d48b49e0-aa
inet6 fe80::f816:3eff:fe5c:a2ac/64 scope link
valid_lft forever preferred_lft forever
68: qr-c2d7dd02-56: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:ea:64:6e brd ff:ff:ff:ff:ff:ff
inet 10.1.0.1/24 brd 10.1.0.255 scope global qr-c2d7dd02-56
inet6 fe80::f816:3eff:feea:646e/64 scope link
valid_lft forever preferred_lft forever

可以看出,该名字空间中包括两个网络接口。

第一个接口qg-d48b49e0-aa(即K)是外部接口(qg=q gateway),将路由器的网关指向默认网关(通过router-gateway-set命令指定),这个接口连接到br-ex上的tapd48b49e0-aa(即L)。

第二个接口qr-c2d7dd02-56(即N,qr=q bridge)跟br-int上的tapc2d7dd02-56口(即M)相连,将router进程连接到集成网桥上。
查看该名字空间中的路由表:

# ip netns exec qrouter-2d214fde-293c-4d64-8062-797f80ae2d8f ip route
172.24.4.224/28 dev qg-d48b49e0-aa proto kernel scope link src 172.24.4.227
10.1.0.0/24 dev qr-c2d7dd02-56 proto kernel scope link src 10.1.0.1
default via 172.24.4.225 dev qg-d48b49e0-aa

其中,第一条规则是将到172.24.4.224/28段的访问都从网卡qg-d48b49e0-aa(即K)发出。

第二条规则是将到10.1.0.0/24段的访问都从网卡qr-c2d7dd02-56(即N)发出。 最后一条是默认路由,所有的通过qg-d48b49e0-aa网卡(即K)发出。 floating ip服务同样在路由器名字空间中实现,例如如果绑定了外部的floating ip 172.24.4.228到某个虚拟机10.1.0.2,则nat表中规则为:

# ip netns exec qrouter-2d214fde-293c-4d64-8062-797f80ae2d8f iptables -t nat -S
-P PREROUTING ACCEPT
-P POSTROUTING ACCEPT
-P OUTPUT ACCEPT
-N neutron-l3-agent-OUTPUT
-N neutron-l3-agent-POSTROUTING
-N neutron-l3-agent-PREROUTING
-N neutron-l3-agent-float-snat
-N neutron-l3-agent-snat
-N neutron-postrouting-bottom
-A PREROUTING -j neutron-l3-agent-PREROUTING
-A POSTROUTING -j neutron-l3-agent-POSTROUTING
-A POSTROUTING -j neutron-postrouting-bottom
-A OUTPUT -j neutron-l3-agent-OUTPUT
-A neutron-l3-agent-OUTPUT -d 172.24.4.228/32 -j DNAT --to-destination 10.1.0.2
-A neutron-l3-agent-POSTROUTING ! -i qg-d48b49e0-aa ! -o qg-d48b49e0-aa -m conntrack ! --ctstate DNAT -j ACCEPT
-A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697
-A neutron-l3-agent-PREROUTING -d 172.24.4.228/32 -j DNAT --to-destination 10.1.0.2
-A neutron-l3-agent-float-snat -s 10.1.0.2/32 -j SNAT --to-source 172.24.4.228
-A neutron-l3-agent-snat -j neutron-l3-agent-float-snat
-A neutron-l3-agent-snat -s 10.1.0.0/24 -j SNAT --to-source 172.24.4.227
-A neutron-postrouting-bottom -j neutron-l3-agent-snat

其中SNAT和DNAT规则完成外部floating ip到内部ip的映射:

-A neutron-l3-agent-OUTPUT -d 172.24.4.228/32 -j DNAT --to-destination 10.1.0.2
-A neutron-l3-agent-PREROUTING -d 172.24.4.228/32 -j DNAT --to-destination 10.1.0.2
-A neutron-l3-agent-float-snat -s 10.1.0.2/32 -j SNAT --to-source 172.24.4.228

另外有一条SNAT规则把所有其他的内部IP出来的流量都映射到外部IP 172.24.4.227。这样即使在内部虚拟机没有外部IP的情况下,也可以发起对外网的访问。

-A neutron-l3-agent-snat -s 10.1.0.0/24 -j SNAT --to-source 172.24.4.227

br-ex

Bridge br-ex
Port "eth1"
Interface "eth1"
Port br-ex
Interface br-ex
type: internal
Port "qg-1c3627de-1b"
Interface "qg-1c3627de-1b"
type: internal

br-ex上直接连接到外部物理网络,一般情况下网关在物理网络中已经存在,则直接转发即可。

# ovs-ofctl dump-flows br-exNXST_FLOW reply (xid=0x4): 
                          cookie=0x0, duration=23431.091s, table=0, n_packets=893539, 
                          n_bytes=504805376, idle_age=0, priority=0 actions=NORMAL

如果对外部网络的网关地址配置到了br-ex(即br-ex作为一个网关):

# ip addr add 172.24.4.225/28 dev br-ex

需要将内部虚拟机发出的流量进行SNAT,之后发出。

# iptables -A FORWARD -d 172.24.4.224/28 -j ACCEPT
# iptables -A FORWARD -s 172.24.4.224/28 -j ACCEPT
# iptables -t nat -I POSTROUTING 1 -s 172.24.4.224/28 -j MASQUERADE

深入理解 Neutron -- OpenStack 网络实现(2):VLAN 模式

Vlan模式下的系统架构跟GRE模式下类似,如下图所示。

需要注意的是,在vlan模式下,vlan tag的转换需要在br-int和br-ethx两个网桥上进行相互配合。即br-int负责从int-br-ethX过来的包(带外部vlan)转换为内部vlan,而br-ethx负责从phy-br-ethx过来的包(带内部vlan)转化为外部的vlan。

(个人对vlan tag的理解,应该是对vlan的一个人为标记,起到识别的作用)

下面进行一些细节的补充讨论,以Vlan作为物理网络隔离的实现。假如要实现同一个租户下两个子网,如下图所示:

计算节点

查看网桥信息,主要包括两个网桥:br-int和br-eth1:

[root@Compute ~]# ovs-vsctl show
f758a8b8-2fd0-4a47-ab2d-c49d48304f82
Bridge "br-eth1"
Port "phy-br-eth1"
Interface "phy-br-eth1"
Port "br-eth1"
Interface "br-eth1"
type: internal
Port "eth1"
Interface "eth1"
Bridge br-int
Port "qvoXXX"
tag: 1
Interface "qvoXXX"
Port "qvoYYY"
tag: 1
Interface "qvoYYY"
Port "qvoZZZ"
tag: 2
Interface "qvoZZZ"
Port "qvoWWW"
tag: 2
Interface "qvoWWW"
Port "int-br-eth1"
Interface "int-br-eth1"
Port br-int
Interface br-int
type: internal

类似GRE模式下,br-int负责租户隔离,br-eth1负责跟计算节点外的网络通信。 在Vlan模式下,租户的流量隔离是通过vlan来进行的,因此此时包括两种vlan,虚拟机在Compute Node内流量带有的local vlan和在Compute Node之外物理网络上隔离不同租户的vlan。

br-int和br-eth1分别对从端口int-br-eth1和phy-br-eth1上到达的网包进行vlan tag的处理。此处有两个网,分别带有两个vlan tag(内部tag1对应外部tag101,内部tag2对应外部tag102)。 其中,安全组策略仍然在qbr相关的iptables上实现。

br-int

与GRE模式不同的是,br-int完成从br-eth1上过来流量(从口int-br-eth1到达)的vlan tag转换,可能的规则为

#ovs-ofctl dump-flows br-int
cookie=0x0, duration=100.795s, table=0, n_packets=6, n_bytes=468, idle_age=90, priority=2,in_port=3 actions=drop
cookie=0x0, duration=97.069s, table=0, n_packets=22, n_bytes=6622, idle_age=31, priority=3,in_port=3,dl_vlan=101 actions=mod_vlan_vid:1,NORMAL
cookie=0x0, duration=95.781s, table=0, n_packets=8, n_bytes=1165, idle_age=11, priority=3,in_port=3,dl_vlan=102 actions=mod_vlan_vid:2,NORMAL
cookie=0x0, duration=103.626s, table=0, n_packets=47, n_bytes=13400, idle_age=11, priority=1 actions=NORMAL

br-eth1

br-eth1上负责从br-int上过来的流量(从口phy-br-eth1到达),实现local vlan到外部vlan的转换。

#ovs-ofctl dump-flows br-eth0
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=73.461s, table=0, n_packets=51, n_bytes=32403, idle_age=2, hard_age=65534, priority=4,in_port=4,dl_vlan=1 actions=mod_vlan_vid:101,NORMAL
cookie=0x0, duration=83.461s, table=0, n_packets=51, n_bytes=32403, idle_age=2, hard_age=65534, priority=4,in_port=4,dl_vlan=2 actions=mod_vlan_vid:102,NORMAL
cookie=0x0, duration=651.538s, table=0, n_packets=72, n_bytes=3908, idle_age=2574, hard_age=65534, priority=2,in_port=4 actions=drop
cookie=0x0, duration=654.002s, table=0, n_packets=31733, n_bytes=6505880, idle_age=2, hard_age=65534, priority=1 actions=NORMAL

网络节点

类似GRE模式下,br-eth1收到到达的网包,int-br-eth1和phy-br-eth1上分别进行vlan转换,保证到达br-int上的网包都是带有内部vlan tag,到达br-eth1上的都是带有外部vlan tag。br-ex则完成到OpenStack以外网络的连接。 查看网桥信息,包括三个网桥,br-eth1、br-int和br-ex。

#ovs
3bd78da8-d3b5-4112-a766-79506a7e2801
Bridge br-ex
Port "qg-VVV"
Interface "qg-VVV"
type: internal
Port br-ex
Interface br-ex
type: internal
Port "eth0"
Interface "eth0"
Bridge br-int
Port br-int
Interface br-int
type: internal
Port "int-br-eth1"
Interface "int-br-eth0"
Port "tapXXX"
tag: 1
Interface "tapXXX"
type: internal
Port "tapWWW"
tag: 2
Interface "tapWWW"
type: internal
Port "qr-YYY"
tag: 1
Interface "qr-YYY"
type: internal
Port "qr-ZZZ"
tag: 2
Interface "qr-ZZZ"
type: internal
Bridge "br-eth1"
Port "phy-br-eth1"
Interface "phy-br-eth1"
Port "br-eth1"
Interface "br-eth1"
type: internal
Port "eth1"
Interface "eth1"

br-eth1

br-eth1主要负责把物理网络上外部vlan转化为local vlan。

#ovs-ofctl dump-flows br-eth1
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=144.33s, table=0, n_packets=13, n_bytes=28404, idle_age=24, hard_age=65534, priority=4,in_port=5,dl_vlan=101 actions=mod_vlan_vid:1,NORMAL
cookie=0x0, duration=144.33s, table=0, n_packets=13, n_bytes=28404, idle_age=24, hard_age=65534, priority=4,in_port=5,dl_vlan=102 actions=mod_vlan_vid:2,NORMAL
cookie=0x0, duration=608.373s, table=0, n_packets=23, n_bytes=1706, idle_age=65534, hard_age=65534, priority=2,in_port=5 actions=drop
cookie=0x0, duration=675.373s, table=0, n_packets=58, n_bytes=10625, idle_age=24, hard_age=65534, priority=1 actions=NORMAL

br-int

br-int上挂载了大量的agent来提供各种网络服务,另外负责对发往br-eth1的流量,实现local vlan转化为外部vlan。

#ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=147294.121s, table=0, n_packets=224, n_bytes=33961, idle_age=13, hard_age=65534, priority=3,in_port=4,dl_vlan=1 actions=mod_vlan_vid:101,NORMAL
cookie=0x0, duration=603538.84s, table=0, n_packets=19, n_bytes=2234, idle_age=18963, hard_age=65534, priority=2,in_port=4 actions=drop
cookie=0x0, duration=603547.134s, table=0, n_packets=31901, n_bytes=6419756, idle_age=13, hard_age=65534, priority=1 actions=NORMAL

dnsmasq负责提供DHCP服务,绑定到某个特定的名字空间上,每个需要DHCP服务的租户网络有自己专属隔离的DHCP服务(图中的tapXXX和tapWWW上各自监听了一个dnsmasq)。

路由是L3 agent来实现,每个子网在br-int上有一个端口(qr-YYY和qr-ZZZ,已配置IP,分别是各自内部子网的网关),L3 agent绑定到上面。要访问外部的公共网络,需要通过L3 agent发出,而不是经过int-br-ex到phy-br-ex(实际上并没有网包从这个veth pair传输)。如果要使用外部可见的floating IP,L3 agent仍然需要通过iptables来进行NAT。

每个L3 agent或dnsmasq都在各自独立的名字空间中,如下图所示,其中同一租户的两个子网都使用了同一个路由器。

对于子网使用不同路由器的情况,多个路由器会在自己独立的名字空间中。例如要实现两个租户的两个子网的情况,如下图所示。

这种情况下,网络节点上的名字空间如下图所示。

br-ex

br-ex要做的事情很简单,只需要正常转发即可。

#ovs-ofctl dump-flows br-ex
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=6770.969s, table=0, n_packets=5411, n_bytes=306944, idle_age=0, hard_age=65534, priority=0 actions=NORMAL
   
3177 次浏览       14
 
相关文章

云计算的架构
对云计算服务模型
云计算核心技术剖析
了解云计算的漏洞
 
相关文档

云计算简介
云计算简介与云安全
下一代网络计算--云计算
软浅析云计算
 
相关课程

云计算原理与应用
云计算应用与开发
CMMI体系与实践
基于CMMI标准的软件质量保证
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]

专家视角看IT与架构
软件架构设计
面向服务体系架构和业务组件的思考
人人网移动开发架构
架构腐化之谜
谈平台即服务PaaS
更多...   
相关培训课程

云计算原理与应用
Windows Azure 云计算应用

摩托罗拉 云平台的构建与应用
通用公司GE Docker原理与实践
某研发中心 Openstack实践
知名电子公司 云平台架构与应用
某电力行业 基于云平台构建云服务
云计算与Windows Azure培训
北京 云计算原理与应用