在前面探秘一和探秘二中,我们已经分享了ZStack的拓扑结构和如何实现超高可伸缩性的能力。还记得我们在Why ZStack中说的,稳定性和灵活性是IaaS需要解决的两大问题。今天我们就来揭开ZStack超强灵活性的奥秘。
今天的内容非常的丰富,我们先来看一下什么是灵活性。所谓灵活性无非是三个方面:当需要添加新功能的时候简单方便,不拖泥带水;系统升级轻巧无障碍;IaaS云配置想改就改,无需重头搭建,改动影响仅限于被影响的部分。让我们带着这三个方面的定义来读今天的内容。
首先让我们看看通常一个自由生长出来的IaaS,它内部各个Components之间的消息传递或者说逻辑关系图吧。
是不是看起来还行?熟悉IaaS的人应该可以理解。有没有想过当你再增加一个监控,一个计费,一个管理界面的时候,它可就不只是增加三个圈圈这么简单了,这图里的连接线怕是要多上好几倍。而当你需要修改一个圈圈的数据结构和输出结果的时候,你需要更改所有和当前圈圈有联系的其他功能模块的接口。为什么会是这样?这因为在自由生长的IaaS设计之初,功能比较单一,模块很少,所以模块之间的连线简单而清晰,直连的方法最容易实现而且有效。但是当等到项目越变越大,连线越连越多的时候,一切都晚了,到最后就变成就是一个令人恐怖的拓扑结构。
多说无益,让我们直接来看看ZStack各个模块之间的关系图吧,星型拓扑结构:
每个微服务自然分离,又通过统一的Message Bus来连接。添加新的微服务,就增加一个星型节点和一条连线。是不是很清晰很简单?为什么会怎么简单呢?好像也没有为什么,这就是大自然在灵活性上的应该遵循的规则啊。
在ZStack里面,微服务的架构又被称为进程内的微服务(In Process Micro Service中文翻译实在拗口啊)。它有如下的特点:
每个服务之间相互独立,通过消息总线连接;
所有的微服务都集合在同一个进程内,也就是我们说的管理节点(Management Node)
因为通过消息总线连接,在不同管理节点上的微服务都可以相互通信(并且相互不知道是不是在相同的管理节点上)
在多管理节点上存在相同的微服务(例如都有管理计算的微服务),最后由哪个管理节点上微服务来处理任务,是由Consistent Hashing Ring选择出来的(这点我们在《ZStack架构探秘二》中有阐述)
接着让我们来看看ZStack是如何添加一个服务的。有了星型拓扑结构,添加新的微服务就变的简单起来。除了常规的微服务,IaaS的操作最终要落地在管理计算,存储和网络三大资源上。拿计算资源来举例,它有一个计算服务。在计算服务下面存在虚拟化和非虚拟化两种形式,其中虚拟化也可以分为KVM、VMWare、Xen、HyperV等。如果ZStack支持了KVM,也就是说要集成所有KVM的基本功能。另外,相比存储和网络,计算资源的种类是很少的。也就是一个可以工作的IaaS里面会集成很多的服务和具体的功能。面对可能多到数不清的微服务和具体功能,ZStack是怎么来支持的呢?可以用什么方法来保证新添加的功能既方便又不影响现有其他功能呢?ZStack采用了类似Eclipse的插件形式来实现不同的资源的管理。例如ZStack的主存储是存放虚拟机的各种Volume的,从实现上可以有NFS的主存储,iSCSI的主存储或者本地存储。那么就会去针对不同的类型实现对应的插件即可:
L2的网络也是一样的道理,可以通过Vlan,OpenVSwitch,或者VxLan来实现隔离和连通:
那具体来说,一个plugin是怎么实现的呢?ZStack的plugin根据所需要的功能可以采用不同的plugin策略:Strategy Plugin或者Oberserver Plugin。简而言之,策略插件会继承父类型的接口然后做具体的实现(例如实现NFS插件);观察者插件,会注册listener到提供注册的地方,当特别的事件发生的时候,注册的lisetener就会被调用,然后在调用中去实现插件的功能(例如在创建VM之前去登记计费。或者如下例所展示的SecurityGroup需要在不同的操作的时候去添加和删除对应的SG规则。)。
需要指出的是,ZStack的插件非常灵活。它可以编译成独立的JAR文件,由ZStack加载(成为进程内in process的一部分)。删除后,也只是失去了该插件的功能本身,而不会影响其他功能。另外,由于ZStack的服务都是通过Rabbitmq来通信的,也就是我们也支持任何可以和Rabbitmq来通讯的进程外(out-of-process)插件。所以ZStack的插件功能是非常灵活的。用户可以选择任何语言来实现自己的插件。
ZStack是如何处理错误的?能回滚错误造成的影响吗?由于IaaS管理的是非常复杂而庞大的系统,错误(由于网络,软件甚至硬件导致)发生频率一定不少。一个好的软件系统不仅仅能在一切正常的情况下能够稳定工作,更需要在不稳定的系统中能够提供稳定运行的能力。这就需要完善的容错和纠错的手段,在发生不可预见的系统的错误的时候,能够正确处理。事件回滚是处理由于出错导致的很多临时中间状态(有时候这些中间状态实际上就是系统垃圾)的有效手段。例如当创建VM的操作失败在最后一步,例如Host掉电。那么之前给VM分配的IP地址,根分区文件,数据库记录都应该通过回滚而清理掉。如果不回滚,那么系统中的就会留下很多垃圾,最终导致IaaS资源耗尽。
ZStack设计了精巧的工作流引擎(Workflow Engine)既用来管理任务执行的顺序,而且不论任务在什么地方出错都会按照原先执行的路径回滚。
ZStack 工作流引擎有如下特点:
工作流可以用XML文件或者具体编程实现;
每一个工作流都可以回滚错误;
每个工作流还可以包含子工作流用于扩展业务逻辑
让我们来看看如何通过XML文件来定义ZStack的一组工作流的:
虽然利用插件系统可以添加新的功能,但是如果我们需要对原有功能进行扩展(这个不可避免,毕竟人的认知是有限的,不能保证原有功能可以支持未来更丰富的参数),可能会改变接口或者是改变原有数据结构中的表单。这种改变导致的问题是,基于原有数据库搭建的IaaS很难迁移和升级。我们可以看到在现有的IaaS系统里,这个方面的问题非常突出。为了解决这个问题,ZStack创造性的发明了一个Tag系统。通常大家认为的Tag系统只是用于给资源打标记做归类。ZStack的Tag系统除了最基本的打标签的功能外,它还可以实现System Tag。System Tag具有两个特殊的功能:
和插件一起合作可以改变原有系统的行为;
给资源添加一个新的属性;
什么是改变原有系统行为。例如在ZStack中,一个Cluster可以挂载多个主存储。在启动VM的时候,用户通常只能选择VM的Zone,Cluster,Host等信息(如果不指定,ZStack会按照预先设计的策略自己选择)。如果用户希望VM被创建到一个特定的主存储,这个时候就可以利用系统System Tag来实现。例如我们可以实现一个特别的系统Tag,并且实现一个插件规定:当我们需要创建的VM被标注该系统Tag,那么这个VM的主存储就会在预先指定的一个主存储(该主存储也会被设置上相同的系统Tag)上创建。在ZStack中,VM可以设定DHCP Hostname。也就是在VM在获取DHCP IP地址的时候,同时也会获取一个系统分配的Hostname。但是由于这个DHCP HOSTNAM 并不是VM网卡的固定属性(因为从物理资源角度,VM NIC的确不应该具有一个Hostname的属性),最后在ZStack中,Hostname的功能也是通过系统Tag来实现的。
最后我们来谈谈IaaS部署后,满足客户需求变更的问题。前面我们基本上都是在讲怎么能够给IaaS更容易的添加功能的问题。不过判断IaaS是否灵活,还有一个非常非常关键的问题,就是IaaS根据用户的要求配置完成后运行了一段时间,用户发现原有的资源配置需要更改,IaaS能否根据用户的要求改变?这个改变是不是可以通过一两个命令就完成,还是需要重头搭建整个IaaS系统?对于ZStack来说,我们的一大杀手锏就是配置灵活易变。我们暴露了非常全面的API,既有Add/Create Resource的,也有Delete/Destroy Resource的API,还有大量的resource的挂载和卸载的API。可以说用户想改变网络拓扑,如把eth0的设备去掉,或是替换主存储的设备对ZStack来说都是小菜一碟。添加的操作其实影响还好,但是删除的操作可是会造成大面积的影响。比如删除一个host,它的影响只限于这个host上,该host上的VM会被暂时stop掉;而删除一个Cluster,会导致删除这个Cluster上所有的Hosts,卸载主存储,以及相关的VM被删除。而删除L2 Network,则会导致正在使用该L2网络的VM(可能会跨很多的Cluster)被Stop掉。在ZStack中,我们有专门计算和处理由于删除架构中的某个资源而会波及到做哪些操作的Cascade Framework。这个架构说起来其实也很轻巧,你需要构建一个大大的地图,把资源按照相互关系梳理出来。不过很可惜的是,我们没有在别的IaaS系统中发现有如此轻巧的设计,恐怕它们以后也没有办法推出类似的设计了。
有了这个资源相互影响地图后,当卸载或者删除一个资源的时候,我们就可以轻松的把受影响的资源的处理方法安装顺序调用一遍。
今天,我们一口气介绍了ZStack的五项独门秘籍,它们可都是为实现超灵活性和可扩展性而量身定做的。他们既独立发挥着作用,又有相互关联。可以说是构成ZStack架构中非常重要的5个环节。通过他们,希望大家对我们的超灵活性有了进一步的了解。我们可是绝不忽悠,是骡子是马大家拉出来遛遛。另外由于微信里的内容都是点到为止,详细内容还请大家移步我们的官网,上面详细阐述了五大秘籍的来龙去脉:
In-Process Microservice Architecture: http://zstack.org/blog/microservices.html
Plugin System: http://zstack.org/blog/plugin.html
WorkFlow Engine: http://zstack.org/blog/workflow.html
Tag System: http://zstack.org/blog/tag.html
Cascade Framework: http://zstack.org/blog/cascade.html