什么是Zuul?

随着OpenStack持续集成的推广,基于OpenStack开源项目的性质,项目大,全球各地的开发人员多,变更提交频繁。Jenkins不能解决并发多、单依赖的问题,拉长了问题反馈时间。为解决该问题,源于OpenStack开源社区的基于ZUUL框架的 CI方案出现在我们的视线中。

CI简单流程图

1

Zuul组件

为了更好的理解什么是Zuul和Zuul到底是怎么工作的,需要介绍一下Zuul有哪些组件

Zuul整体架构

1

Zuul-server

Zuul-server是Zuul的主要的服务,zuul-server是作为zuul的scheduler,zuul-server从gerrit接收消息,一旦消息被接收到,zuul-server就建立工作流程,并把处理结果返回给gerrit Zuul-server跟gerrit组件交流是通过执行“gerrit stream-events”,然后等待gerrit返回的信息,另外,zuul-server也与Gearman进行通讯

Gearman

Jenkins的设计初衷并不用于并行执行,它设计中某些点使用到了全局锁,因此在Jenkins的slave节点增加到一定数量后(大约100台),Jenkins的master节点就会出现问题而成为瓶颈。同时master节点是单点部署,无法完成HA等处理。为了扩展Jenkins而引入了Gearman。
简单来说,Gearman是一个用来扩展Jenkins的一种协议,而且Gearman一开始并不是专门为Zuul开发的,但是Gearman很好的符合了Zuul的需求,因此OpenStack采用Gearman来扩展Zuul对Jenkins的调度。 在配置的时候可以选择单独创建Gearman-server或者是使用Zuul来部署Gearman,具体在/etc/zuul/zuul.conf里面进行配置:

1
2
3
4
5
[gearman_server]
listen_address = 127.0.0.1
log_config = /etc/zuul/gearman-logging.conf
start = true

把start改成true,zuul服务就会启动并管理Gearman进程

Zuul-merger

这里不要被这个组件的名字所误导了,这个组件并不是当代码全部通过测试后用来merge到主干的
当开发者提交一个change后,zuul-merger把这个change merge到一个本地forked repository中 ,这样就可以进行下一步的测试了。
可以把zuul-merger单独部署在一台服务器上也可以进行高可用部署,即部署在多台服务器上组成zuul-merger的集群
在zuul的配置文件 /etc/zuul/zuul.conf下可以对zuul-merger进行配置,在 [merger] section下面

1
2
3
4
5
6
[merger]
git_dir = /var/lib/zuul/git
log_config = /etc/zuul/merger-logging.conf
pidfile = /var/run/zuul-merger/zuul-merger.pid
zuul_url = 127.0.0.1

  • git_dir是zuul对Git repository的一个copy
  • Log_config是配置zuul-merger的log目录
  • zuul_url是zuul server的url,这个url可能有多个(zuul集群的情况下)

Zuul-cloner

Zuul-cloner不像其他组件,它没有Damon,只有一个client,用来创建job的workspace

Zuul Workflow

下图是解释当一个patch提交给gerrit的时候zuul的workflow是怎么样的

1

Gerrit

用户的patch是提交给Gerrit的,也可以是一个新的commit
一旦这个patch被提交上来,Gerrit就会publish一个event,通知其他服务来处理这个event,如Zuul、Jenkins等

Zuul Server

Zuul-server根据zuul.conf的配置来启动相应的关联进程,Zuul server会先起一个进程叫GerritWatcher,用来listen从Gerrit那边传过来的event(步骤3),在注册好所有的连接后,zuul-server会起一个Gearman,zuul-server同时会启动Gearman和Scheduler
当一个Gerrit的event被publish后,GerritWatcher就会通知scheduler,scheduler先会去检查这个event是否合法(根据layout.yaml里面定义的规则),如果通过,便会触发一个trigger event(步骤4)
Scheduler接着处理这个event,并把这个event添加到一个相关的pipeline里面(步骤5,也是根据layout.yaml里面定义的规则),接下去就是pipeline来处理这个event了,scheduler也会去检查这个event是否依赖于其他的event

Zuul Merger

当scheduler触发完成trigger event后,把整个代码克隆下来,并把更改的代码并入主干的工作是由zuul-merger来完成的。在步骤6中,merger会从gearman那边获得一个“merge job”的信息,里面包括项目的名称,分支信息,change number和ref等信息。第一步merger需要确认这个commit是不是重复的,如果是,那么就返回已经发生的commit,如果不是,那么继续下一步工作。
HEAD ref重置完成后,如果ref指向了一个不可用的分支,那么zuul就会自动选择第一个可用的分支,然后merger会通过“git fetch”来update repo,再checkout。
接下来merger尝试merge更改到repo上,如果merge成功,那么就会在zuul-server中创建一个新的reference到repo中,最后,merger会返回一个动作完成的信息。

Gearman & Jenknis

现在repo已经准备完成,在上面merger的工作完成之后,现在需要测试这个代码的更改。这步操作其实是scheduler来做的,但是需要配合Gearman来执行。Scheduler发送给Gearman,scheduler也会发送一些变量给Gearman,一般是 ‘ZUUL_’ 开头的。

Gearman接着把数据发送给Jenkins,Jenkins可能是一个集群,Jenkins在测试完成后会把结果返回给zuul,zuul再去通知gerrit是否去merge这个更改。

是否必须使用Jenkins

OpenStack社区考虑过不再使用Jenkins,只使用Zuul来代替,但是如果你的CI系统跟Jenkins强绑定的话,系统中使用了很多Jenkins的plugin,那么再去转换到non-Jenkins的环境中会有比较大的困难。当然可以慢慢利用Zuul来替换Jenkins,但是如果一定要使用Jenkins的话,那么就需要“Jenkins Gearman”这个plugin来提供支持。

Pipelines

Pipelines是Zuul重要的组成部分,每一个gerrit的change都会由一个或者多个Pipelines来进行处理

Upsteam

非Openstack核心团队的人员可以在评审代码后作出+1(好)、0(无评价)、-1(不建议合并)的评价。核心团队的成员可以给出非核心成员可给出的所有评价,此外还可以给出+2(好,approved)、-2评价(不要提交)。
标签属性中另外一列为“Verified”。只有Gerrit的非交互用户(non-interactive users)如Jenkins,才能在此属性上添加Verified标签。Verified一列可设置的值为+1(check pipeline测试通过)、-1(check pipeline测试未通过)、+2(gate pipeline测试通过)、-2(gate pipeline测试未通过)。此外,第三方搭建的外部测试平台也属于非交互用户,但是只能设置+1、-1。

Pipeline也有很多种

  • periodic – 周期性工作的pipeline,比如用于非工作时间做常规的测试
  • expermental – 如果你有一个新项目,但是不知道它是怎么工作的,那么可以用于这个expermental pipeline
  • pre-release – 触发的job是归于一个新的pre-release tags
  • release – 触发的job是归于一个release tags

定制化Pipelines

可以通过配置Zuul来定制化pipelines,可以通过更改zuul layout配置文件
下面是一个配置例子

1
2
3
4
5
6
7
8
9
10
11
12
13
- name: test
  manager: IndependentPipelineManager
  source: gerrit_internal
  trigger:
    my_gerrit:
      - event: patchset-created
  success:
    my_gerrit:
      verified: 1
  failure:
    my_gerrit
      verified: -1

可以自定义一个pipeline,取名为test,如果pipeline运行成功,那么返回给gerrit +1,如果失败,那么返回给gerrit -1
上面的配置文件中还有

1
2
manager: IndependentPipelineManager  

这个是用来决定pipeline具体是怎么工作的

IndependentPipelineManager

IndependentPipelineManager是当pipeline在处理信息是不需要关心信息处理的顺序的时候使用,在一些patch提交时,在其他test正在运行的时候,也不会对这个patch提交产生影响,当前提交的patch是相对独立的,那么就可以使用IndependentPipelineManager

DependentPipelineManager

DependentPipelineManager则是当pipeline在处理信息是不需要关心信息处理的顺序的时候使用,如果当你同时提交了多个patch,当一个patch test failed的时候,那么同时提交的相关联的patch都需要再次test一次。
Zuul同时还可以很好的处理具有复杂依赖关系的多个patch。它能监控正在执行的任务,并可提前结束掉因依赖的patch测试失败而必定失败的测试任务。

参考文献

http://stackeye.com/2014/06/openstack-ci/

https://docs.openstack.org/infra/manual/zuulv3.html

SDN概念

SDN的概念已经流行了很多年了,从一开始的实验室产品到2012年谷歌宣布其主干网络已经全面运行在OpenFlow上,使广域线路的利用率从30%提升到接近饱和。从而证明了OpenFlow不再仅仅是停留在学术界的一个研究模型,而是已经完全具备了可以在产品环境中应用的技术成熟度。
SDN社区力量在2014年的时候还很薄弱,控制器才只有floodlight、Ryu和极不成熟的opendaylight,科研机构和高校都还在用mininet在做模拟实验,后来有了运营商主导的ONOS控制器、Juniper OpenContrail和华为的DragonFlow,和较为成熟的OpenvSwitch情况才有所好转,可以利用X86服务器搭建小型的SDN网络。
到现在出现了很多白牌交换机厂商,有了很多商业的优秀的SDN控制器,和不仅在数据中心的场景,还有了SD-WAN等广域网场景,而现在SDN的概念也在扩大,随着OpenStack云计算的火热,由Neutron组件等优秀开源的项目,和集成的大量功能的Plugin也在推翻传统的SDN的定义。随着用户对SDN的追捧,和云计算项目的落地,不得不说SDN现在已经在大量的用户的生产环境中使用。

SDN网络选型

SDN网络的优势在这里就不展开讨论了,SDN目前有很多组网方案,来满足不同的用户场景。

(一)控制器通过南向协议来控制白牌交换机的转发

第一种实现,就是纯南向协议的实现不支持任何传统协议。通过SDN控制器来发现全网拓扑,计算路径,再通过南向协议下发流表,实现流量按策略转发。如下图所示。

1

在云计算的场景中,SDN控制器可以利用OpenStack Neutron来实现控制平面,通过OpenFlow/Netconf控制 VXLAN VTEP、GW、IP GW。它的优点是可以通过软交换机来实现网络的创建、子网的划分、路由的选择以及防火墙策略的管理等功能。

(二)松散控制模式方案(通过网络设备控制协议自学习)

VxLAN隧道自动建立以及隧道自动关联;通过标准EVPN完成隧道建立和地址学习,利用EVPN的BGP RR实现邻居发现 ,每个设备都通告自己的VxLAN信息,每个VTEP设备都有全网的VXLAN信息以及VxLAN和下一跳的关系。VTEP设备会和那些跟自己有相同VXLAN的下一跳自动建立VXLAN隧道,并将此VxLAN隧道跟这些相同的VxLAN关联。SDN控制器只负责下发服务策略,不下发控制流表,可靠性更高。注意这里是VxLAN是属于在Underlay进行网络传输的。
MAC/IP route通过MP-BGP传输到对端VTEP。现实中要求BGP连接是full mesh(任意两两互连),而为了减轻配置压力,通常会引入BGP RR(Router Reflector)。BGP RR的作用是将一个BGP Speaker的数据反射给所有其他连接的BGP peer。使用BGP RR可以使得所有的BGP Speaker只需与BGP RR建立连接,否则按照full mesh,任意一个BGP Speaker必须与其他所有的BGP peer建立BGP连接。

2

(三)VLAN模型组网

在OpenStack的环境中Neutron网络组件可以选择VLAN组网模型。VLAN模型的特点缺点是需要在传统的网络交换机上放开对应的VLAN,因此在做网络接入时需要依赖网络的规划,同时在多租户隔离上不是特别方便,仍然需要在网络交换机上做操作,即网络组网不够灵活;优点是VLAN技术比较成熟,不管是性能上还是稳定性上都比较好。

尾语

在数据中心,大致有三种方式部署软件定义的网络。一种方法是使用OpenFlow/Netconf,一种SDN的南向标准,但是经常因可扩展性差而被诟病。一种更受欢迎的方式是使用虚拟网络覆盖,即使用VxLAN Overlay的方式扩展组网。这种技术是目前应用最广泛的。另外一种主流的技术是根据开放的协议,称为BGP EVPN,这是一种在数据中心将分别属于不同的租户之间的虚拟机进行流量隔离。其非常强大,是因为其能够实现让分别位于数据中心不同部分或完全位于不同的数据中心的虚拟机之间的专用连接。其也能够使整个虚拟机从一台主机设备迁移到另一台。

目前说到虚拟交换机,通常会想到使用Open vSwitch做虚拟交换机,因为支持Open vSwitch的个人和企业都想要有一个开放的模式把他们的服务集成进OpenStack。 Open vSwitch社区做了大量的工作,希望提升Open vSwitch作为最主要虚拟交换机的地位。社区期望Open vSwitch将在软件定义网络(SDN)接管网络时代到来时,提供所有可能最好的交换服务。但是,Open vSwitch的复杂性使用户渴望更简单的网络解决方案,在这过程中需要Linux Bridge这样的简单桥接技术来支持云解决方案。

但是Open vSwitchh支持者会指出Linux Bridge 缺少可扩展性的隧道模型。Linuxbridge是二层概念,不能支持GRE的三层隧道技术,vxlan模型是在linux kernel较高版本(3.9以上)才native支持的。因此有这些观点的网络专家们,他们会比较坚定的认为复杂的解决方案比一个简单的解决方案要好。

当然,Linux Bridge已经发生了变化,也有助于缩小使用Open vSwitch和Linux Bridge的之间的差距,包括添加VXLAN支持隧道技术。但是在更大的网络规模中,Linux Bridge的简单性可能会产生更大的价值。

我们都知道,OpenStack 社区官方的安装文档的步骤在liberty版本之前都是以Open vSwitch为例子的。而且从OpenStack 用户调查来看,使用 Open vSwitch的人比使用 linux bridge 多很多。

Liberty 版本之前社区官方文档都是使用 neutron-plugin-openvswitch-agent, 但是 Liberty 版本转为使用 neutron-plugin-linuxbridge-agent。社区文档只留了这么一句话,意思是Linuxbridge更加简单。

“In comparison to provider networks with Open vSwitch (OVS), this scenario relies completely on native Linux networking services which makes it the simplest of all scenarios in this guide.”

以下是Open vSwitch与Linux bridge之间的优劣势对比

(1)Open vSwitch 目前还存在不少稳定性问题,比如:

  • Kernetl panics 1.10
  • ovs-switched segfaults 1.11
  • 广播风暴
  • Data corruption 2.01

(2)于Linux bridge,Open vSwitch有以下好处:

  • Qos配置,可以为每台vm配置不同的速度和带宽
  • 流量监控
  • 数据包分析
  • 将openflow引入到ovs中,实现控制逻辑和物理交换网络分离

(3)为什么可以使用 Linux bridge?

  • 稳定性和可靠性要求:Linux bridge 有十几年的使用历史,非常成熟。
  • 易于问题诊断 (troubleshooting)
  • 社区也支持
  • 还是可以使用 Overlay 网络 VxLAN 9需要 Linux 内核 3.9 版本或者以上)

(4)使用 Linux bridge 的局限性

  • Neutron DVR 还不支持 Linux bridge
  • 不支持 GRE
  • 一些 OVS 提供但是 Neutorn 不支持的功能

(5)长期来看,随着稳定性的进一步提高,Open vSwitch 会在生产环境中成为主流。

1

Linux bridge 和 Open vSwitch 的功能对比:

可以看出:
(1)OVS 将各种功能都原生地实现在其中,这在起始阶段不可避免地带来潜在的稳定性和可调试性问题
(2)Linux bridge 依赖各种其他模块来实现各种功能,而这些模块的发布时间往往都已经很长,稳定性较高
(3)两者在核心功能上没有什么差距,只是在集中管控和性能优化这一块Open vSwitch有一些新的功能或者优化。但是,从测试结果看,两者的性能没有明显差异:

1

1

总之,目前,Open vSwitch与Linux bridge都有各自的适合的场景,对于云用户来说也提供了更好的两种优秀的网络解决方案,除了SDN对集中管控的需求,和更新更多的网络特性时,Open vSwitch更加有优势,但是在稳定性,大规模网络部署等场景中Linux bridge 是个较好的选择。

Kuryr背景介绍

Kuryr项目在OpenStack big tent下的一个项目,目的是将容器网络与OpenStack Neutron对接。

正式介绍前,先说下Kuryr这个单词。Kuryr是一个捷克语单词kurýr,对应英语里面是courier,对应的中文意思就是信使,送信的人。从这个名字能看出来,Kuryr不生产信息,只是网络世界的搬运工。

Kuryr解决了什么问题

OpenStack和Neutron已经是成立很久并且相对比较成熟的开源项目,特别是拿Neutron来说,Neutron现在有一个很完整的生态系统,并且有大量的plugin来为Neutron提供各种各样的网络解决方案,例如LBaaS、VPNaaS、FWaaS,并且这些plugin已经在逐步得被云用户在生产环境中应用。
我们注意到容器网络方面,特别是在容器和OpenStack混合使用的环境中,每个网络解决方案都尝试为容器重新创建和启用网络,但这次使用Docker API(或任何其他抽象)OpenStack Magnum来对容器网络进行管理 Kuryr背后的想法是能够利用Neutron及其插件和服务中的抽象和功能,来为容器用例提供生产级网络。 而不是使用每个独立的Neutron插件或解决方案来做,这样就引出了文章主题 - Kuryr。
Kuryr的目标是成为两个社区Docker和Neutron之间的“集成桥梁”,进而推动Neutron(或Docker)项目的发展,以便能够满足容器网络的各种场景。

重要的是要指出,Kuryr本身不是一个网络解决方案,也不是企图成为一个网络解决方案。 Kuryr的工作重点是成为为Docker提供Neutron网络和服务的信使。

Kuryr架构

将Docker libnetwork映射到Neutron API
下图显示了Kuryr架构的基本概念,将Docker和libnetwork网络模型映射到Neutron API

1

Kuryr映射libnetwork API并在Neutron中创建适当的对象,这意味着每个实现Neutron API的解决方案现在都可以用于容器联网。 Neutron提供的所有附加功能可以应用于容器端口,例如安全组,NAT服务和浮动IP

但是,Kuryr的潜力并不止于核心API和基本扩展,Kuryr可以利用Neutron提供的网络服务及其特性,如LBaaS来实现Kubernetes服务的抽象等等

当API的映射不是非常明显,并且如果需要驱动Neutron社区的变化,Kuryr也将缩小差距。 最近的例子是标签添加到Neutron资源,允许像Kuryr这样的API客户端存储映射数据和端口转发,以便能够提供端口暴露的Docker风格(当然,所有这些仍然在审查和批准过程中)

提供通用的VIF绑定基础结构

Neutron解决方案需要支持容器网络的一个常见场景是,在这些场景中,缺乏新的端口绑定基础设施并且不支持libvirt。

Kuryr试图为各种端口类型提供通用的VIF绑定机制,这些端口类型将从Docker命名空间端点接受数据,并根据其类型(或传递给它来完成绑定)将其附加到网络解决方案基础结构。

对于运行在VM内部的容器运行的情况,VIF绑定也是需要的,这将在下一节中介绍。 这些VM不是由nova直接管理的,因此它们中没有任何OpenStack代理,这意味着需要一些机制来执行VIF绑定,并且可以从调用Shim Kuryr层的本地Docker远程驱动程序启动。 (但是这个问题仍然在讨论中)

以下图表描述了使用Kuryr的VIF绑定

1

提供Neutron插件和Kolla集成的Containerized image

Kuryr的目标是提供各种Neutron插件的一个集成工具箱,并且有望与kolla集成。
这意味着我们将为各种Neutron插件提供各种image,例如具有Kuryr层的OVS L2 Agent,Midonet,OVN。 Kolla集成将带来运营商所需的易用部署,同时不会失去对服务间认证和可配置性的控制。

嵌套的VM和Magnum用例

Kuryr希望解决的另一个用例是在用户拥有的OpenStack创建的VM(即VM容器)上部署容器的常见模式。 这种部署模式通过将用户拥有的容器与运营商拥有的Nova Compute机器分离,为容器部署提供了额外的安全层。
这个用例也被OpenStack Magnum使用,Magnum是由OpenStack Containers Team开发的OpenStack API服务,使得Docker和Kubernetes等容器编排引擎成为OpenStack中的一流资源。

已经有Neutron插件支持这种用例,并且提供了一种优雅的方式来将嵌套容器连接到不同于VM本身的网络的不同逻辑网络中,并在其上应用Neutron特性,例如OVN

使用Kuryr,OVN和MidoNet等其他Neutron供应商可以利用通用基础设施与Docker进行交互,并将重点放在完善Neutron API,并推动网络向前发展

Kuryr工作机制

一、docker那边需要先挖好坑,把网络部分的接口暴露出来。

  • docker把网络部分提取成了libnetwork,并为此实现了几个driver,host、overlay、null和remote,其中remote就是为用其他项目来管理docker的网络留的接口。remote采用rpc的方式将参数通过网络发给外部管理程序,外部程序处理好了后通过json返回结果给remote。
  • libnetwork的remote driver定义了基本的创建网络、创建port的接口,只要对应的REST Server实现了这些接口,就可以提供整套docker的网络。这些接口有:Create network、Delete network、Create endpoint、Delete endpoint、Join(绑定)、Leave(去绑定)。
  • remote driver的接口定义在 https://github.com/docker/libnetwork/blob/master/docs/remote.md
  • 用remote driver分配了设备一般是不带IP的,libnetwork使用ipam driver来管理ip。这些接口有:GetDefaultAddressSpaces 获取保留IP,RequestPool获取IP地址池,ReleasePool释放IP地址池,RequestAddress获取IP地址,ReleaseAddress释放IP地址。
  • ipam driver的接口定义在 https://github.com/docker/libnetwork/blob/master/docs/ipam.md
* libnetwork的插件发现机制在 https://github.com/docker/docker/blob/master/docs/extend/plugin_api.md#plugin-discovery

二、kuryr这边就按照docker给的接口转为neutron的操作。

  • 配置文件里面定义好参数,以便能连上neutron。
  • 使用Flask(而不是wsgi)实现一个REST Server,以便接收remote driver传过来的参数。
  • 使用libnetwork的插件机制,在 /usr/lib/docker/plugins/ 目录下建立kuryr的插件描述的json文件。
  • docker daemon启动的时候,libnetwork发现kuryr这个新插件,并且通过 /Plugin.Active 验证这个插件可用。
  • 使用docker network create –driver=kuryr foo 在docker中创建一个网络
  • 用户使用docker创建一个容器的时候,指定网络为 foo
  • kuryr从libnetwork接收到请求,并用很多硬编码的schemata来验证用户输入的参数对不对,然后把创建 Network/Sandbox/Endpoint转为对应neutron的资源,发送给neutron。
  • kuryr接收neutron的结果,再用pyroute2创建veth pair,一个bind到neutron的port,一个以给veth设置netns的方式给容器。
  • kuryr把neutron返回的结果包装成libnetwork的样式,转发给libnetwork。 这样容器就能用neutron的网络了,并且可以使用因此而来的附加功能:安全组、租户网络。。。。
  • kuryr类似ovs-agent,也需要每个计算节点安装一个。

集中式VXLANIP网关方案

采用集中式VXLANIP网关方案时,不同VXLAN之间的流量以及VXLAN访问外界网络的流量全部由集中式VXLAN IP网关处理,网关压力较大,并加剧了网络带宽资源的消耗。在分布式VXLAN IP网关方案中,每台VTEP设备都可以作为VXLAN IP网关,对本地站点的流量进行三层转发,很好地缓解了网关的压力。

1

在分布式VXLAN IP网关组网中,所有的分布式VXLAN IP网关(GW)上都需要创建VSI虚接口,并为不同GW上的相同VSI虚接口配置相同的IP地址,作为VXLAN内虚拟机的网关地址。在分布式VXLAN IP网关上还需要开启本地代理ARP功能。边界网关(Border)上也需要创建VSI虚接口,并配置IP地址。

采用分布式VXLANIP网关组网方案时,三层流量通过查找ARP表项进行三层转发。

相同VXLAN内不同站点的虚拟机通信过程

相同VXLAN内不同站点的虚拟机的通信过程为:

(1)VM1广播发送ARP请求消息,获取VM4的MAC地址

(2)GW 1收到ARP请求消息后,学习VM 1的ARP信息,并代理应答该ARP请求,即:向VM 1发送ARP应答消息,应答的MAC地址为VSI虚接口10的MAC地址

(3)VM 1学习到VM 4的MAC地址为GW 1上VSI虚接口10的MAC地址

(4)GW 1将接收到的ARP请求消息中的源MAC地址修改为VSI虚接口10的MAC地址,对该消息进行VXLAN封装后,将其发送给VXLAN内的所有远端VTEP

(5)GW 2对VXLAN报文进行解封装后,学习VM 1的ARP信息(IP为10.1.1.11、MAC为GW 1上VSI虚接口10的MAC、出接口为接收该VXLAN报文的Tunnel接口),并将ARP请求消息中的源MAC修改为本地VSI虚接口10的MAC地址,在VXLAN 10的本地站点内进行广播

(6)VM 4收到ARP请求后,学习VM 1的ARP信息(IP为10.1.1.11、MAC为GW 2上VSI虚接口10的MAC),并发送ARP应答消息给本地网关GW 2

(7)GW 2从VM 4收到ARP应答消息后,学习VM 4的ARP信息,将ARP应答消息中的源MAC修改为本地VSI虚接口10的MAC地址,并根据已经学习到的ARP表项,为ARP应答消息添加VXLAN封装后发送给GW 1

(8)GW 1对VXLAN报文进行解封装后,根据收到的ARP应答消息学习VM 4的ARP信息(IP为10.1.1.12、MAC为GW 2上VSI虚接口10的MAC、出接口为接收该VXLAN报文的Tunnel接口)

(9)通过上述步骤完成ARP信息的学习后,VM 1发送给VM 4的报文,根据已经学习到的ARP信息进行转发:首先发送给GW 1;GW 1对其进行VXLAN封装后,将其发送给GW 2;GW 2解封装后,将其发送给VM 4

不同VXLAN间不同站点的虚拟机通信过程

以VM 1访问VM 5为例,不同VXLAN的虚拟机的通信过程为:

(1)VM 1广播发送ARP请求消息,获取网关10.1.1.1的MAC地址

(2)GW 1收到ARP请求消息后,学习VM 1的ARP信息,并向VM 1发送ARP应答消息,应答的MAC地址为VSI虚接口10的MAC地址

(3)VM 1将访问VM 5的报文发送给GW 1

(4)GW 1在所有VXLAN内向本地站点和远端站点广播发送ARP请求,获取VM5的MAC地址。ARP请求消息中的源IP地址为20.1.1.1、源MAC地址为本地VSI虚接口20的MAC地址

(5)GW 2从VXLAN隧道上接收到VXLAN报文,对其进行解封装后,学习GW 1的ARP信息(IP为20.1.1.1、MAC为GW 1上VSI虚接口20的MAC、出接口为接收该VXLAN报文的Tunnel接口),并将ARP请求消息中的源MAC修改为本地VSI虚接口20的MAC地址,在VXLAN 20的本地站点内广播该ARP请求消息

(6)VM 5收到ARP请求后,学习GW 2的ARP信息(IP为20.1.1.1、MAC为GW 2上VSI虚接口20的MAC),并发送ARP应答消息给本地网关GW 2

(7)GW 2从VM 5收到ARP应答消息后,学习VM 5的ARP信息,将ARP应答消息中的源MAC修改为本地VSI虚接口20的MAC地址,并根据已经学习到的ARP表项,为ARP应答消息添加VXLAN封装后发送给GW 1

(8)GW 1对VXLAN报文进行解封装后,根据收到的ARP应答消息学习VM 5的ARP信息(IP为20.1.1.12、MAC为GW 2上VSI虚接口20的MAC、出接口为接收该VXLAN报文的Tunnel接口)

(9)通过上述步骤完成ARP信息的学习后,VM 1发送给VM 5的报文,根据已经学习到的ARP信息进行转发:首先发送给GW 1;GW 1对其进行VXLAN封装后,将其发送给GW 2;GW 2解封装后,将其发送给VM 5

虚拟机与外部网络的三层通信过程

虚拟机要想与外部网络进行三层通信,需要在接入虚拟机的本地分布式VXLAN IP网关上指定流量的下一跳为Border,可以通过如下方式来实现:

  • 在本地分布式VXLANIP网关上配置静态路由,指定路由下一跳为Border上同一个VXLAN对应VSI虚接口的IP地址

  • 在本地分布式VXLANIP网关上配置策略路由,设置报文的下一跳为Border上同一个VXLAN对应VSI虚接口的IP地址

以VM 1访问外部网络内的主机50.1.1.1为例,虚拟机访问外部网络的三层通信过程为:

(1)VM 1广播发送ARP请求消息,获取网关10.1.1.1的MAC地址

(2)GW 1收到ARP请求消息后,学习VM 1的ARP信息,并向VM 1发送ARP应答消息,应答的MAC地址为VSI虚接口10的MAC地址

(3)VM 1将访问外部网络的报文发送给GW 1

(4)GW 1接收到报文后,根据策略路由判断报文的下一跳地址为10.1.1.2。GW 1在VXLAN10内向本地站点和远端站点广播发送ARP请求消息,获取10.1.1.2对应的MAC地址

(5)Border对VXLAN报文进行解封装,学习GW 1的ARP信息,并通过VXLAN隧道回复ARP应答消息

(6)GW 1对VXLAN报文进行解封装,并获取到10.1.1.2的ARP信息

(7)GW 1根据获取到的信息为VM 1发送的报文封装链路层地址(10.1.1.2对应的MAC地址),并通过VXLAN隧道将报文发送给Border

(8)Border对接收到的报文进行解封装后,对报文进行三层转发