Neutron 理解 (3): Open vSwitch + GRE/VxLAN 组网 [Netruon Open vSwitch + GRE/VxLAN Virutal Network]
学习 Neutron 系列文章:
(2)Neutron OpenvSwitch + VLAN 虚拟网络
(3)Neutron OpenvSwitch + GRE/VxLAN 虚拟网络
(4)Neutron L3 agent
(5)TBD
目前,OpenStack Neutron 支持使用两种隧道网络技术 通用路由封装(GRE) 和 VxLAN 来实现虚拟的二层网络。这两种技术大致看起来非常相似,都是需要使用 OpenStack 在计算和网络节点上建立隧道来传输封装的虚机发出的数据帧:
在Neutron 中使用 GRE/VxLAN 时的配置也几乎完全相同。具体可以参考我已有的几篇文章:
- 探索 OpenStack 之(8):Neutron 深入探索之 OVS + GRE 之 完整网络流程 篇
- 探索 OpenStack 之(7):Neutron 深入探索之 Open vSwitch (OVS) + GRE 之 Neutron节点篇
- 学习OpenStack之(6):Neutron 深入学习之 OVS + GRE 之 Compute node 篇
本文将不再重复说明这些配置细节。本文将试着分析两种技术本身的异同,以及Neutorn 中的代码过程。
1. GRE 技术
GRE(Generic Routing Encapsulation,通用路由协议封装)协议,是一种 IP-over-IP 的隧道,由 Cisco 和 Net-smiths 等公司于1994年提交给IETF,它对部分网络层协议(IP)的数据报进行封装,使这些被封装的数据报能够在 IPv4/IPv6 网络中传输。其协议格式见RFC2784(https://tools.ietf.org/html/rfc2784)。简单的说,GRE是一种协议封装的格式。它规定了如何用一种网络协议去封装另一种网络协议,很多网络设备都支持该协议。说得直白点,就是 GRE 将普通的包(如ip包)封装了,又安装普通的ip包的路由方式进行路由,相当于ip包外面再封装一层 GRE 包。在本例子中,在 GRE 包外围实际上又有一层公网的ip包。
GRE 使用 tunnel(隧道)技术,数据报在 tunnel 的两端封装,并在这个通路上传输,到另外一端的时候解封装。你可以认为 tunnel 是一个虚拟的点对点的连接。(实际 Point To Point 连接之后,加上路由协议及nat技术,就可以把两个隔绝的局域网连接在一起,就实现了NetToNet的互联)。一般 GRE turnel 是在多个网络设备(一般为路由器)之间建立。因为 linux 服务具备路由转发功能,所以当您缺少专业的路由设备的时候,可使用 linux 服务器实现 gre turnel 的建立(实际上巨大多数网络设备都使用unix或linux系统)。
这篇文章 很好地解释 GRE 的原理和一个应用场景。
1.1 应用场景
办公网(LAN 192.168.1.0/24,并通过固定的公网IP上网)和 IDC (LAN 10.1.1.0/24,并有多个公网ip,两者通过公网ip互联)这两个局域网 (或者任意两个不同局域网) 相互隔离。但是在日常运维和研发过程中,需要在办公网访问IDC网络。如果都通过公网 IP 绕,既不方便,也不安全;拉专线是最稳定可靠的办法,但是成本高。
1.2 使用 GRE 的配置
如果公司有多余的固定的公网 ip 或者路由器本身支持GRE,建议使用 GRE 方案。
(1)办公网路由器(linux服务器实现):局域网IP 192.168.1.254,公网 IP 180.1.1.1 配置。
cat /usr/local/admin/gre.sh #并把改脚本加入开机启动
#!/bin/bash modprobe ip_gre #加载gre模块 ip tunnel add office mode gre remote 110.2.2.2 local 180.1.1.1 ttl 255 #使用公网 IP 建立 tunnel 名字叫 ”office“ 的 device,使用gre mode。指定远端的ip是110.2.2.2,本地ip是180.1.1.1。这里为了提升安全性,你可以配置iptables,公网ip只接收来自110.2.2.2的包,其他的都drop掉。 ip link set office up #启动device office ip link set office up mtu 1500 #设置 mtu 为1500 ip addr add 192.192.192.2/24 dev office #为 office 添加ip 192.192.192.2 echo 1 > /proc/sys/net/ipv4/ip_forward #让服务器支持转发 ip route add 10.1.1.0/24 dev office #添加路由,含义是:到10.1.1.0/24的包,由office设备负责转发 iptables -t nat -A POSTROUTING -d 10.1.1.0/24 -j SNAT --to 192.192.192.2#否则 192.168.1.x 等机器访问 10.1.1.x网段不通
IDC路由器(linux服务器实现):局域网 ip:10.1.1.1,公网 ip110.2.2.2配置
cat /usr/local/admin/gre.sh#并把改脚本加入开机启动
#!/bin/bash modprobe ip_gre ip tunnel add office mode gre remote 180.1.1.1 local 110.2.2.2 ttl 255 ip link set office up ip link set office up mtu 1500 ip addr add 192.192.192.1/24 dev office #为office添加 ip 192.192.192.1 echo 1 > /proc/sys/net/ipv4/ip_forward ip route add 192.168.1.0/24 dev office iptables -t nat -A POSTROUTING -s 192.192.192.2 -d 10.1.0.0/16 -j SNAT --to 10.1.1.1 #否则192.168.1.X等机器访问10.1.1.x网段不通 iptables -A FORWARD -s 192.192.192.2 -m state --state NEW -m tcp -p tcp --dport 3306 -j DROP #禁止直接访问线上的3306,防止内网被破
配置示意图:
然后两个局域网中的机器就可以互通了。
1.3 过程
过程:
1. GRE turnel 的打通:这个过程就是双方建立turnel的过程。
2. 局域网路由过程
(1)主机 A 发送一个源为192.168.1.2,目的为 10.1.1.2 的包。
(2)封装过程
1、根据内网路由,可能是你的默认路由网关将之路由至 192.168.1.254。
2、192.168.1.254 第一次封装包,增加 GRE 包头,说明包的目的地址 192.192.192.1 和源地址192.192.192.2。
3、192.168.1.254 第二次封装包,增加公网的包头(否则在公网上无法路由),说明包的目的地址 110.2.2.2 和源地址 180.1.1.1。
4、192.168.1.254 把所有到 10.1.1.0/24 的包,原地址都转换为从192.192.192.2 出(snat)。
3. 公网路由过程:经过n个路由设备,该包最终路由到110.2.2.2。
4. 拆包过程
1、B端的路由器检测到是到达自己的 IP,就开始拆包。
2、拆包之后发现有GRE协议,就进一步拆包。
3、拆包之后发现目的地不是自己的内网ip、发现自己本地做了snat,就将其源IP替换为10.1.1.1。
5. 局域网路由
1、实际上从 10.1.1.1 出发的,到达目的地为 10.1.1.2 的包,无需路由,直接在局域网内广播。10.1.1.2 的机器确定是发送给自己的包,就接收。然后进一步处理了。
(注:以上文字皆摘自 http://h2ofly.blog.51cto.com/6834926/1544860)
1.4 GRE 的不足
GRE 技术本身还是存在一些不足之处:
(1)Tunnel 的数量问题
GRE 是一种点对点(point to point)标准。Neutron 中,所有计算和网络节点之间都会建立 GRE Tunnel。当节点不多的时候,这种组网方法没什么问题。但是,当你在你的很大的数据中心中有 40000 个节点的时候,又会是怎样一种情形呢?使用标准 GRE的话,将会有 780 millions 个 tunnels。
(2)扩大的广播域
GRE 不支持组播,因此一个网络(同一个 GRE Tunnel ID)中的一个虚机发出一个广播帧后,GRE 会将其广播到所有与该节点有隧道连接的节点。
(3)GRE 封装的IP包的过滤和负载均衡问题
目前还是有很多的防火墙和三层网络设备无法解析 GRE Header,因此它们无法对 GRE 封装包做合适的过滤和负载均衡。
2. VxLAN 技术
VxLAN 主要用于封装、转发2层报文。VXLAN 全称 Virtual eXtensible Local Area Network,简单的说就是扩充了的 VLAN,其使得多个通过三层连接的网络可以表现的和直接通过一台一台物理交换机连接配置而成的网络一样处在一个 LAN 中。
它的实现机制是,将二层报文加上个 VxLAN header,封装在一个 UDP 包中进行传输。VxLAN header 会包括一个 24 位的 ID(称为VNI),含义类似于 VLAN id 或者 GRE 的 tunnel id。GRE 一般是通过路由器来进行 GRE 协议的封装和解封的,在 VXLAN 中这类封装和解封的组件有个专有的名字叫做 VTEP。相比起 VLAN 来说,好处在于其突破了VLAN只有 4000+ 子网的限制,同时架设在 UDP 协议上后其扩展性提高了不少(因为 UDP 是高层协议,屏蔽了底层的差异,换句话说屏蔽了二层的差异)。
2.1 VXLAN 的实现
2.1.1 VxLAN 将二层数据帧封装为 UDP 包
含义:
- Outer MAC destination address (MAC address of the tunnel endpoint VTEP)
- Outer MAC source address (MAC address of the tunnel source VTEP)
- Outer IP destination address (IP address of the tunnel endpoint VTEP)
- Outer IP source address (IP address of the tunnel source VTEP)
- Outer UDP header:Src port 往往用于 load balancing,下文有提到;Dst port 即 VXLAN Port,默认值为 4789.
- VNID:表示该帧的来源虚机所在的 VXLAN 网段的 ID
特点:
- VNID: 24-bits,最大 16777216。每个不同的 24-bits VNI 代表一个 VXLAN 网段。只有同一个网段中的虚机才能互相通信。
- VXLAN Port:目的 UDP 端口,默认使用 4789 端口。用户可以自己配置。
- 两个 VTEP 之间的 VXLAN tunnels 是无状态的。
- VTEP 可以在虚拟交换机上,物理交换机或者物理服务器上通过软件或者硬件实现。
- 使用多播来传送未知目的的、广播或者多播帧。
- VTEP 不可以对 VXLAN 包分段。
2.1.2 VTEP 寻址
一个 VTEP 可以管理多个 VXLAN 隧道,每个隧道通向不同的目标。那 VTEP 接收到一个二层帧后,它怎么根据二层帧中的目的 MAC 地址找到对应的 VXLAN 隧道呢?VXLAN 利用了多播和 MAC 地址学习技术。如果它收到的帧是个广播帧比如 ARP 帧,也会经过同样的过程。
以下图为例,每个 VTEP 包含两个 VXLAN 隧道。VTEP-1 收到二层 ARP 帧1(A 要查找 B 的 MAC) 后,发出一个 Dstr IP 地址为VTEP多播组 239.1.1.1 的 VXLAN 封装包。该包会达到 VTEP-2 和 VTEP-3。VTEP-2收到后,因为目的 IP 地址不在它的范围内,丢弃该包,但是学习到了一条路径:MAC-A,VNI 10,VTEP-1-IP,它知道要到达 A 需要经过 VTEP-1 了。VTEP-3 收到后,发现目的 IP 地址是机器 B,交给 B,同时添加学习到的规则 MAC-A,VNI 10,VTEP-1-IP。B 发回响应帧后,VTEP-2 直接使用 VTEP-1 的 IP知道将它封装成三层包,通过物理网络直接到达 VTEP-1,再由它交给 A。VTEP-1 也学习到了一条规则 MAC-B,VNI 10,VTEP-2-IP。
2.1.2 VxLAN 组网
- 逻辑 VxLAN Tunnel:建立在物理的 VxLAN 网络之上,向虚机提供虚拟的二层网络,以 VNID 做区分。
- VTEP (VxLAN Tunnel End Point):对虚机的二层包封装和解封。
2.1.3 数据流向
发送端:
- 计算目的地址:Linux 内核在发送之前会检查数据帧的目的MAC地址,需要选择目的 VTEP。
- 如果是广播或者多播地址,则使用其 VNI 对应的 VXLAN group 组播地址,该多播组内所有的 VTEP 将收到该多播包;
- 如果是单播地址,如果 Linux 的 MAC 表中包含该 MAC 地址对应的目的 VTEP 地址,则使用它;
- 如果是单播地址,但是 LInux 的 MAC 表中不包含该 MAC 地址对应的目的 VTEP IP,那么使用该 VNI 对应的组播地址。
- 添加Headers:依次添加 VXLAN header,UDP header,IP header。
接收端:
- UDP监听:因为 VXLAN 利用了 UDP,所以它在接收的时候势必须要有一个 UDP server 在监听某个端口,这个是在 VXLAN 初始化的时候完成的。
- IP包剥离:一层一层剥离出原始的数据帧,交给 TCP/IP 栈,由它交给虚机。
实现代码在 这里。
2.1.5 负载均衡
组成 VXLAN 隧道的三层路由器在有多条 ECMP (Equal-cost multi-path routing)路径通往目的 VTEP 时往往会使用基于每个包( per-package) 的 负载均衡(load balancing)。因为两个 VTEP 之间的所有数据包具有相同的 outer source and destination IP addresses 和 UDP destination port,因此 ECMP 只能使用 soure UDP port。VTEP 往往将其设置为原始数据帧中的一些参数的 hash 值,这样 ECMP 就可以使用该 hash 值来区分 tunnels 直接的网络流量了。
这里有更详细的 VXLAN 介绍。
3. 相关技术对比
3.1 VLAN 和 VxLAN 的对比
该图中的网络组件和Neutorn 中相应的组件一一对应:
VLAN | VXLAN |
cloudVirBrX 对应于 br-int ethY.X 对应于 br-eth3 (物理bridge) ethY 对应于 Hypervisor NIC |
cloudVirBrX 对应于 br-int vxlanX 对应于 Neutron 中的 br-tun。 cloudbrZ 对应于 Neutorn 中的 br-tun 上的 vxlan interface。 ethY 对应于Hypervisor NIC |
3.2 GRE 和 VXLAN 对比
Feature | VXLAN | GRE |
---|---|---|
Segmentation | 24-bit VNI (VXLAN Network Identifier) | Uses different Tunnel IDs |
Theoretical scale limit | 16 million unique IDs | 16 million unique IDs |
Transport | UDP (default port 4789) | IP Protocol 47 |
Filtering | VXLAN uses UDP with a well-known destination port; firewalls and switch/router ACLs can be tailored to block only VXLAN traffic. | Firewalls and layer 3 switches and routers with ACLs will typically not parse deeply enough into the GRE header to distinguish tunnel traffic types; all GRE would need to be blocked indiscriminately. |
Protocol overhead | 50 bytes over IPv4 (8 bytes VXLAN header, 20 bytes IPv4 header, 8 bytes UDP header, 14 bytes Ethernet). | 42 bytes over IPv4 (8 bytes GRE header, 20 bytes IPv4 header, 14 bytes Ethernet). |
Handling unknown destination packets, broadcasts, and multicast | VXLAN uses IP multicast to manage flooding from these traffic types. Ideally, one logical Layer 2 network (VNI) is associated with one multicast group address on the physical network. This requires end-to-end IP multicast support on the physical data center network. | GRE has no built-in protocol mechanism to address these. This type of traffic is simply replicated to all nodes. |
IETF specification | http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-01 | http://tools.ietf.org/html/rfc2784.html |
4. Neutron 通过 OVS 对 GRE 和 VXLAN 的支持
因为 OVS 对两种协议的实现机制,Neutron 对两个协议的支持的代码和配置几乎是完全一致的,除了一些细小差别,比如名称,以及个别配置比如VXLAN的UDP端口等。OVS 在计算或者网络节点上的 br-tun 上建立多个 tunnel port,和别的节点上的 tunnel port 之间建立点对点的 GRE/VXLAN Tunnel。Neutron GRE/VXLAN network 使用 segmentation_id (VNI 或者 GRE tunnel id) 作为其网络标识,类似于 VLAN ID,来实现不同网络内网络流量之间的隔离。
4.1 隧道端口 (tunnel port)
下面是一个实例。该例子中,10.0.1.31 Hypervisor上的 br-tun 上分别有两个 GRE tunnel 端口和两个 VXLAN tunnel 端口,分别连接 目标 Hypervisor 10.0.1.39 和 21。
Bridge br-tun Port "vxlan-0a000127" Interface "vxlan-0a000127" type: vxlan options: {df_default="true", in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.39"} Port "vxlan-0a000115" Interface "vxlan-0a000115" type: vxlan options: {df_default="true", in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.21"} Port "gre-0a000127" Interface "gre-0a000127" type: gre options: {df_default="true", in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.39"} Port "gre-0a000115" Interface "gre-0a000115" type: gre options: {df_default="true", in_key=flow, local_ip="10.0.1.31", out_key=flow, remote_ip="10.0.1.21"}
当有多个节点时,Neutron 会建立一个 tunnel 网:
4.2 在不使用 l2population 时的隧道建立过程
要使用 GRE 和 VXLAN,管理员需要在 ml2 配置文件中配置 local_ip(比如该物理服务器的公网 IP),并使用配置项 tunnel_types 指定要使用的隧道类型,即 GRE 或者 VXLAN。当 enable_tunneling = true 时,Neutorn ML2 Agent 在启动时会建立 tunnel bridge,默认为 br-tun。接着,ML2 Agent 会在 br-tun 上建立 tunnel ports,作为 GRE/VXLAN tunnel 的一端。具体过程如图所示:
Neutron 默认使用 4789 作为 VXLAN port。下表中可以看出 Neutron 节点在该端口上监听来自所有源的UDP包:
root@compute1:/home/s1# netstat -lnup Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 3840 0 0.0.0.0:4789 0.0.0.0:* -
4.3 Neutron tunnel 数据流向
Neutron 中的数据流向是受 Neutron 添加在 integration bridge 和 tunnel bridge 中的 OpenFlow rules 控制的,而且和 L2 population 直接相关。具体内容在下一篇文章中会仔细分析。
4.4 MTU 问题(来源)
VXLAN 模式下虚拟机中的 mtu 最大值为1450,也就是只能小于1450,大于这个值会导致 openvswitch 传输分片,进而导致虚拟机中数据包数据重传,从而导致网络性能下降。GRE 模式下虚拟机 mtu 最大为1462。
计算方法如下:
- vxlan mtu = 1450 = 1500 – 20(ip头) – 8(udp头) – 8(vxlan头) – 14(以太网头)
- gre mtu = 1462 = 1500 – 20(ip头) – 4(gre头) – 14(以太网头)
可以配置 Neutron DHCP 组件,让虚拟机自动配置 mtu,官方文档链接 http://docs.openstack.org/juno/install-guide/install/yum/content/neutron-network-node.html
#/etc/neutron/dhcp_agent.ini [DEFAULT] dnsmasq_config_file = /etc/neutron/dnsmasq-neutron.conf #/etc/neutron/dnsmasq-neutron.conf dhcp-option-force=26,1450或1462
重启 DHCP Agent,让虚拟机重新获取 IP,然后使用 ifconfig 查看是否正确配置 mtu。
参考链接
1. GRE和VXLAN
2. https://plus.google.com/+KennethDuda/posts/2tnVCHkeVyZ
本文中大部分图片来自互联网。