gitbook/趣谈网络协议/docs/11324.md
2022-09-03 22:05:03 +08:00

17 KiB
Raw Permalink Blame History

第28讲 | 云中网络的隔离GRE、VXLAN虽然住一个小区也要保护隐私

对于云平台中的隔离问题前面咱们用的策略一直都是VLAN但是我们也说过这种策略的问题VLAN只有12位共4096个。当时设计的时候看起来是够了但是现在绝对不够用怎么办呢

一种方式是修改这个协议。这种方法往往不可行,因为当这个协议形成一定标准后,千千万万设备上跑的程序都要按这个规则来。现在说改就放,谁去挨个儿告诉这些程序呢?很显然,这是一项不可能的工程。

另一种方式就是扩展在原来包的格式的基础上扩展出一个头里面包含足够用于区分租户的ID外层的包的格式尽量和传统的一样依然兼容原来的格式。一旦遇到需要区分用户的地方我们就用这个特殊的程序来处理这个特殊的包的格式。

这个概念很像咱们第22讲讲过的隧道理论,还记得自驾游通过摆渡轮到海南岛的那个故事吗?在那一节,我们说过,扩展的包头主要是用于加密的,而我们现在需要的包头是要能够区分用户的。

底层的物理网络设备组成的网络我们称为Underlay网络,而用于虚拟机和云中的这些技术组成的网络称为Overlay网络这是一种基于物理网络的虚拟化网络实现。这一节我们重点讲两个Overlay的网络技术。

GRE

第一个技术是GRE全称Generic Routing Encapsulation它是一种IP-over-IP的隧道技术。它将IP包封装在GRE包里外面加上IP头在隧道的一端封装数据包并在通路上进行传输到另外一端的时候解封装。你可以认为Tunnel是一个虚拟的、点对点的连接。

从这个图中可以看到在GRE头中前32位是一定会有的后面的都是可选的。在前4位标识位里面有标识后面到底有没有可选项这里面有个很重要的key字段是一个32位的字段里面存放的往往就是用于区分用户的Tunnel ID。32位够任何云平台喝一壶的了

下面的格式类型专门用于网络虚拟化的GRE包头格式称为NVGRE也给网络ID号24位也完全够用了。

除此之外GRE还需要有一个地方来封装和解封装GRE的包这个地方往往是路由器或者有路由功能的Linux机器。

使用GRE隧道传输的过程就像下面这张图。这里面有两个网段、两个路由器中间要通过GRE隧道进行通信。当隧道建立之后会多出两个Tunnel端口用于封包、解封包。

  1. 主机A在左边的网络IP地址为192.168.1.102它想要访问主机B主机B在右边的网络IP地址为192.168.2.115。于是发送一个包源地址为192.168.1.102目标地址为192.168.2.115。因为要跨网段访问于是根据默认的default路由表规则要发给默认的网关192.168.1.1,也即左边的路由器。

  2. 根据路由表从左边的路由器去192.168.2.0/24这个网段应该走一条GRE的隧道从隧道一端的网卡Tunnel0进入隧道。

  3. 在Tunnel隧道的端点进行包的封装在内部的IP头之外加上GRE头。对于NVGRE来讲是在MAC头之外加上GRE头然后加上外部的IP地址也即路由器的外网IP地址。源IP地址为172.17.10.10目标IP地址为172.16.11.10然后从E1的物理网卡发送到公共网络里。

  4. 在公共网络里面沿着路由器一跳一跳地走全部都按照外部的公网IP地址进行。

  5. 当网络包到达对端路由器的时候也要到达对端的Tunnel0然后开始解封装将外层的IP头取下来然后根据里面的网络包根据路由表从E3口转发出去到达服务器B。

从GRE的原理可以看出GRE通过隧道的方式很好地解决了VLAN ID不足的问题。但是GRE技术本身还是存在一些不足之处。

首先是Tunnel的数量问题。GRE是一种点对点隧道如果有三个网络就需要在每两个网络之间建立一个隧道。如果网络数目增多这样隧道的数目会呈指数性增长。

其次,GRE不支持组播因此一个网络中的一个虚机发出一个广播帧后GRE会将其广播到所有与该节点有隧道连接的节点。

另外一个问题是目前还是有很多防火墙和三层网络设备无法解析GRE因此它们无法对GRE封装包做合适地过滤和负载均衡。

VXLAN

第二种Overlay的技术称为VXLAN。和三层外面再套三层的GRE不同VXLAN则是从二层外面就套了一个VXLAN的头这里面包含的VXLAN ID为24位也够用了。在VXLAN头外面还封装了UDP、IP以及外层的MAC头。

VXLAN作为扩展性协议也需要一个地方对VXLAN的包进行封装和解封装实现这个功能的点称为VTEPVXLAN Tunnel Endpoint

VTEP相当于虚拟机网络的管家。每台物理机上都可以有一个VTEP。每个虚拟机启动的时候都需要向这个VTEP管家注册每个VTEP都知道自己上面注册了多少个虚拟机。当虚拟机要跨VTEP进行通信的时候需要通过VTEP代理进行由VTEP进行包的封装和解封装。

和GRE端到端的隧道不同VXLAN不是点对点的而是支持通过组播的来定位目标机器的而非一定是这一端发出另一端接收。

当一个VTEP启动的时候它们都需要通过IGMP协议。加入一个组播组就像加入一个邮件列表或者加入一个微信群一样所有发到这个邮件列表里面的邮件或者发送到微信群里面的消息大家都能收到。而当每个物理机上的虚拟机启动之后VTEP就知道有一个新的VM上线了它归我管。

如图虚拟机1、2、3属于云中同一个用户的虚拟机因而需要分配相同的VXLAN ID=101。在云的界面上就可以知道它们的IP地址于是可以在虚拟机1上ping虚拟机2。

虚拟机1发现它不知道虚拟机2的MAC地址因而包没办法发出去于是要发送ARP广播。

ARP请求到达VTEP1的时候VTEP1知道我这里有一台虚拟机要访问一台不归我管的虚拟机需要知道MAC地址可是我不知道啊这该咋办呢

VTEP1想我不是加入了一个微信群么可以在里面@all 一下问问虚拟机2归谁管。于是VTEP1将ARP请求封装在VXLAN里面组播出去。

当然在群里面VTEP2和VTEP3都收到了消息因而都会解开VXLAN包看里面是一个ARP。

VTEP3在本地广播了半天没人回都说虚拟机2不归自己管。

VTEP2在本地广播虚拟机2回了说虚拟机2归我管MAC地址是这个。通过这次通信VTEP2也学到了虚拟机1归VTEP1管以后要找虚拟机1去找VTEP1就可以了。

VTEP2将ARP的回复封装在VXLAN里面这次不用组播了直接发回给VTEP1。

VTEP1解开VXLAN的包发现是ARP的回复于是发给虚拟机1。通过这次通信VTEP1也学到了虚拟机2归VTEP2管以后找虚拟机2去找VTEP2就可以了。

虚拟机1的ARP得到了回复知道了虚拟机2的MAC地址于是就可以发送包了。

虚拟机1发给虚拟机2的包到达VTEP1它当然记得刚才学的东西要找虚拟机2就去VTEP2于是将包封装在VXLAN里面外层加上VTEP1和VTEP2的IP地址发送出去。

网络包到达VTEP2之后VTEP2解开VXLAN封装将包转发给虚拟机2。

虚拟机2回复的包到达VTEP2的时候它当然也记得刚才学的东西要找虚拟机1就去VTEP1于是将包封装在VXLAN里面外层加上VTEP1和VTEP2的IP地址也发送出去。

网络包到达VTEP1之后VTEP1解开VXLAN封装将包转发给虚拟机1。

有了GRE和VXLAN技术我们就可以解决云计算中VLAN的限制了。那如何将这个技术融入云平台呢

还记得将你宿舍里面的情况,所有东西都搬到一台物理机上那个故事吗?

虚拟机是你的电脑路由器和DHCP Server相当于家用路由器或者寝室长的电脑外网网口访问互联网所有的电脑都通过内网网口连接到一个交换机br0上虚拟机要想访问互联网需要通过br0连到路由器上然后通过路由器将请求NAT后转发到公网。

接下来的事情就惨了你们宿舍闹矛盾了你们要分成三个宿舍住对应上面的图你们寝室长也即路由器单独在一台物理机上其他的室友也即VM分别在两台物理机上。这下把一个完整的br0一刀三断每个宿舍都是单独的一段。

可是只有你的寝室长有公网口可以上网于是你偷偷在三个宿舍中间打了一个隧道用网线通过隧道将三个宿舍的两个br0连接起来让其他室友的电脑和你寝室长的电脑看起来还是连到同一个br0上其实中间是通过你隧道中的网线做了转发。

为什么要多一个br1这个虚拟交换机呢主要通过br1这一层将虚拟机之间的互联和物理机机之间的互联分成两层来设计中间隧道可以有各种挖法GRE、VXLAN都可以。

使用了OpenvSwitch之后br0可以使用OpenvSwitch的Tunnel功能和Flow功能。

OpenvSwitch支持三类隧道GRE、VXLAN、IPsec_GRE。在使用OpenvSwitch的时候虚拟交换机就相当于GRE和VXLAN封装的端点。

我们模拟创建一个如下的网络拓扑结构,来看隧道应该如何工作。

三台物理机每台上都有两台虚拟机分别属于两个不同的用户因而VLAN tag都得打地不一样这样才不能相互通信。但是不同物理机上的相同用户是可以通过隧道相互通信的因而通过GRE隧道可以连接到一起。

接下来所有的Flow Table规则都设置在br1上每个br1都有三个网卡其中网卡1是对内的网卡2和3是对外的。

下面我们具体来看Flow Table的设计。

1.Table 0是所有流量的入口所有进入br1的流量分为两种流量一个是进入物理机的流量一个是从物理机发出的流量。

从port 1进来的都是发出去的流量全部由Table 1处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=1 actions=resubmit(,1)"

从port 2、3进来的都是进入物理机的流量全部由Table 3处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=2 actions=resubmit(,3)"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 in_port=3 actions=resubmit(,3)"

如果都没匹配上,就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 actions=drop"

2.Table 1用于处理所有出去的网络包分为两种情况一种是单播一种是多播。

对于单播由Table 20处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)"

对于多播由Table 21处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=1 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)"

3.Table 2是紧接着Table1的如果既不是单播也不是多播就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=2 actions=drop"

4.Table 3用于处理所有进来的网络包需要将隧道Tunnel ID转换为VLAN ID。

如果匹配不上Tunnel ID就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=3 actions=drop"

如果匹配上了Tunnel ID就转换为相应的VLAN ID然后跳到Table 10。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x1 actions=mod_vlan_vid:1,resubmit(,10)"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=3 tun_id=0x2 actions=mod_vlan_vid:2,resubmit(,10)"

5.对于进来的包Table 10会进行MAC地址学习。这是一个二层交换机应该做的事情学习完了之后再从port 1发出去。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1 table=10  actions=learn(table=20,priority=1,hard_timeout=300,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"

Table 10是用来学习MAC地址的学习的结果放在Table 20里面。Table20被称为MAC learning table。

NXM_OF_VLAN_TCI是VLAN tag。在MAC learning table中每一个entry都仅仅是针对某一个VLAN来说的不同VLAN的learning table是分开的。在学习结果的entry中会标出这个entry是针对哪个VLAN的。

NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]表示当前包里面的MAC Source Address会被放在学习结果的entry里的dl_dst里。这是因为每个交换机都是通过进入的网络包来学习的。某个MAC从某个port进来交换机就应该记住以后发往这个MAC的包都要从这个port出去因而源MAC地址就被放在了目标MAC地址里面因为这是为了发送才这么做的。

load:0->NXM_OF_VLAN_TCI[]是说在Table20中将包从物理机发送出去的时候VLAN tag设为0所以学习完了之后Table 20中会有actions=strip_vlan。

load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[]的意思是在Table 20中将包从物理机发出去的时候设置Tunnel ID进来的时候是多少发送的时候就是多少所以学习完了之后Table 20中会有set_tunnel。

output:NXM_OF_IN_PORT[]是发送给哪个port。例如是从port 2进来的那学习完了之后Table 20中会有output:2。

所以如图所示通过左边的MAC地址学习规则学习到的结果就像右边的一样这个结果会被放在Table 20里面。

6.Table 20是MAC Address Learning Table。如果不为空就按照规则处理如果为空就说明没有进行过MAC地址学习只好进行广播了因而要交给Table 21处理。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=20 actions=resubmit(,21)"

7.Table 21用于处理多播的包。

如果匹配不上VLAN ID就默认丢弃。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=0 table=21 actions=drop"

如果匹配上了VLAN ID就将VLAN ID转换为Tunnel ID从两个网卡port 2和port 3都发出去进行多播。

ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1table=21dl_vlan=1 actions=strip_vlan,set_tunnel:0x1,output:2,output:3"
ovs-ofctl add-flow br1 "hard_timeout=0 idle_timeout=0 priority=1table=21dl_vlan=2 actions=strip_vlan,set_tunnel:0x2,output:2,output:3"

小结

好了,这一节就到这里了,我们来总结一下。

  • 要对不同用户的网络进行隔离解决VLAN数目有限的问题需要通过Overlay的方式常用的有GRE和VXLAN。

  • GRE是一种点对点的隧道模式VXLAN支持组播的隧道模式它们都要在某个Tunnel Endpoint进行封装和解封装来实现跨物理机的互通。

  • OpenvSwitch可以作为Tunnel Endpoint通过设置流表的规则将虚拟机网络和物理机网络进行隔离、转换。

最后,给你留两个思考题。

  1. 虽然VXLAN可以支持组播但是如果虚拟机数目比较多在Overlay网络里面广播风暴问题依然会很严重你能想到什么办法解决这个问题吗

  2. 基于虚拟机的云比较复杂,而且虚拟机里面的网卡,到物理网络转换层次比较多,有一种比虚拟机更加轻量级的云的模式,你知道是什么吗?

我们的专栏更新到第28讲不知你掌握得如何每节课后我留的思考题你都有没有认真思考并在留言区写下答案呢我会从已发布的文章中选出一批认真留言的同学,赠送学习奖励礼券和我整理的独家网络协议知识图谱。

欢迎你留言和我讨论。趣谈网络协议,我们下期见!