直戳OpenStack痛处?IaaS开源新兵ZStack架构设计全解析
原文 http://www.csdn.net/article/2015-04-10/2824443
【编者按】 已经成为IaaS事实标准的OpenStack,仍然面临稳定性、易用性等一系列的难题,新近推出的IaaS开源项目ZStack,号称要借鉴IaaS先 辈的经验,通过新的技术架构解决OpenStack难以解决的技术问题,并得到了OpenStack社区的关注。那么,ZStack有何特色?能否实现目 标?ZStack的发起者和总架构师张鑫(Frank),撰文从架构层面全面介绍了ZStack的设计理念和技术实现,并就ZStack的市场目标和社区 规划进行了解答。以下为文章内容:
ZStack作为一款新开源IaaS软件,自发布后就迅速引起了技术圈的关注,许多朋友都对它架构特点很感兴趣。虽然在 ZStack主页 有16篇博客详细介绍了它的主要架构特点,但仍要花一定时间进行阅读才能把握其设计要点。笔者作为ZStack的发起者和总架构师,希望通过这篇文章对所有架构要点进行一次梳理,围绕它要解决的问题出发,为读者进行一个详细的介绍。
ZStack的架构特点
ZStack从诞生之初没有急于实现各种炫目的功能,而是花了大部分精力做架构设计,希望从架构上解决四个问题:易用性,稳定性,高性能,以及扩展性。ZStack的所有的架构设计,全部围绕这四个方面展开:
易用性
在易用性方面,ZStack首先考虑的是软件的安装部署与升级,其次是在长期使用的过程中的营运和维护。对于安装和部署,ZStack是一个 Java项目,在编译的完成后,所有的文件都会被打包到一个Java的WAR文件中。部署ZStack实际就是部署一个标准的Java WAR文件到Apache Tomcat这样的web container中。这种部署是Java web应用的标准部署方法,非常简单且广为熟知。即使没有IaaS经验的的用户,也可以很容易学会安装。同时ZStack对外部的依赖非常少,仅仅需要 MySQL数据库,RabbitMQ消息总线,以及Ansible系统配置管理软件,这些都是Linux各个发行版提供的软件。一个单管理节点的 ZStack部署如图所示:
如果把MySQL和RabbitMQ放到单独的机器,单管理节点的部署可以很容易扩展成多节点部署:
由于IaaS软件管理数据中心中大量的硬件,很多情况下需要安装agent到硬件上,例如安装agent到作为KVM计算节点的Linux机器。 为了让用户从手动安装配置硬件的枯燥工作中解脱出来,ZStack跟Ansible无缝集成,当用户添加一个计算节点时,ZStack调用Ansible 自动安装agent并配置系统,整个过程对用户透明。用户无需阅读冗长的文档去了解agent需要什么依赖包,需要怎么配置,这些全部由ZStack负 责。用户只需调用一个API即可。类似的设计应用在所有需要安装agent的服务,例如负责提供网络功能的虚拟机(Virutal Router VM)。
KVM agent的Ansible的配置文件如图所示:
配置文件和KVM agent的Python包都包含在Java WAR文件中,在用户调用API添加一个计算节点时,ZStack会自动找到对应的配置文件并调用Ansible去部署agent,用户甚至都不知道这个 过程的存在。此外,对于高级用户,可以通过扩展Ansible配置文件来实现运维过程中的系统维护和升级。例如为了升级KVM机器的某个安装包修复一个安 全漏洞,用户只需要在KVM的配置文件中加上相关内容,再调用ZStack的ReconnectHost API,就可以自动实现升级功能。
在监控方面,ZStack目前提供对关键的系统资源比如物理机,虚拟机的状态进行监控,任何在ZStack控制外的状态变化,例如虚拟机的意外宕 机,都会在一定的时间内被检测到并同步到数据库。此外ZStack还通过Java的JMX协议对外暴露监控自身的接口,例如监控当前系统运行的任务,系统 正在处理的消息,消息的平均处理时间和最大处理时间等。让用户可以实时了解系统动态。
丰富的查询API是ZStack为用户运维提供的一个重要功能。ZStack的查询API提供超过400万单项查询条件,400万阶乘的组合查询 条件。用户在API层面就可以完成数据库级别的资源查询。查询API带来的意义是可以打造真正企业级的UI。在优秀的企业软件中,例如微软 outlook,JIRA中,用户都可以根据自己的需求创建不同的视图。在IaaS中也有同样的需求。用户可能需要视图显示所有在同一三级网络中的虚拟 机,显示所有内存容量低于2G的物理服务器等。在没有完善的查询API支持下,UI就只能提供几个默认视图,而无法允许用户自定义视图。
ZStack的查询API的一个独特之处在于,查询框架在接收到API后可以自动生成SQL语句,无需编写代码。开发人员只要在数据库中定义了 表,然后在Java程序中用annotation描述新表与其它表之间的foreign key,再为新表继承一个查询API的基础类,所有工作就完成了。用户使用新API时,查询框架可以自动感知,根据用户的查询条件生成单表SQL以及多表 Join的SQL语句。
稳定性
IaaS软件本身是个集成项目,管理了数据中心中大量的子系统,它实际上管理着所有子系统和所有设备的状态。加之IaaS中每一个任务的执行路径 非常长,例如创建一个虚拟机就涉及到计算节点,网络节点,存储节点状态的变化,其中任何一个步骤都可能出错。一旦错误发生,由于当前IaaS缺乏回退机 制,某些子系统会遗留在中间状态。比如一个虚拟机最后创建失败了,但它的DHCP信息却可能遗留在网络节点,导致将来可能的DHCP冲突。为 此,ZStack设计了一个workflow引擎,将任务的每个操作都封装到flow中,一旦某个操作出错,workflow引擎会回退 (rollback)所以已经执行的flow,保证不会系统遗留在中间状态。
例如在上图的创建虚拟机workflow中,假设任务在VmCreateOnHypervisorFlow这一步失败了,workflow引擎会 回退前面已执行的6个flow,包括子workflow(图中计算节点分配workflow,创建网络节点虚拟机的workflow)。例如删除已创建的 网络节点虚拟机,删除已创建的虚拟磁盘,归还已分配的计算资源到计算节点等。最大程度保证系统状态的完整性。
除了可以回退外,workflow引擎还可以允许开发人员通过XML文件来配置关键任务。例如在上图中,创建虚拟机的workflow包含一个创 建网络节点虚拟机的子workflow(Creating Appliance VM sub-workflow)。这个子workflow跟创建用户虚拟机的workflow类似,只有分配网卡这个flow不同。ZStack通过配置 XML文件替换掉该条flow(图中绿色部分),就实现了创建网络节点虚拟机的逻辑。这种通过XML文件配置workflow的方式被大量运用,例如计算 节点分配器(host allocator),存储分配器(storage allocator),IP地址分配器(IP allocator)都是通过这种方式实现的。开发人员甚至不用写新代码,只需重新组合一些flow的顺序就可以实现新的业务逻辑。例如计算节点分配器里 的一些实现,就是通过组合已有的flow实现的。这种方式使ZStack的组件复用度非常高,帮助整个架构实现了松耦合。
除了workflow,ZStack在设计最初期就引入了一个类似于Eclipse的插件系统,所有核心功能都是以小插件的形式搭建起来的,保证 无论是添加新功能还是移除旧功能,都不会修改已有代码,从而保证在快速实现新功能的同时,整体系统可以保持稳定。这个插件系统的核心是扩展点 (extension point)。每个组件都可以定义自己的扩展点允许其它组件接入,从而扩展业务逻辑。
例如上图所示的安全组(security group)功能,它需要在虚拟机的不同生命期对防火墙规则进行编程。但对于虚拟机本身来说,安全组只是一个附加功能,所以并不应该实现在虚拟机自身的逻 辑当中。基于ZStack的插件系统,安全组通过虚拟机模块,网络模块等定义的扩展点插入到了虚拟机生命期,网络配置等业务逻辑中,在不修改任何已有模块 的情况下,实现成一个单独的Java JAR文件。也就是说,安全组本身不会对现有功能造成任何影响,即使删除安全组对应的JAR文件,整个系统也只是失去了这个功能而已。通过插件系 统,ZStack本身架构完全实现了松耦合。
Tag system也是ZStack一个创新。虽然很多IaaS软件也有tag的概念,但大多只是帮助用户管理资源。ZStack定义一种称为system tag的概念,插件可以通过定义system tag,在不修改已有数据库表的情况下,实现为现有表添加新的字段。例如在虚拟机表中并不存在一个字段叫hostname,ZStack的一个插件通过定 义一个vm::hostname的system tag,为虚拟机表增加了这个字段,从而允许用户在创建虚拟机时指定它的hostname。通过这种方式,插件在扩展已有功能时,无需对现有数据库表格式 进行修改,从而减轻了软件升级过程中数据库迁移的负担。
Workflow引擎,插件系统,system tag设计的核心思想是最大程度的松耦合架构,保证已有系统在快速添加新功能的情况下也能保证整体架构稳定,避免因实现新功能而反复修改已有代码,导致产品始终没有一个稳定内核的情况。
最后,ZStack从诞生开始就是测试驱动的。在ZStack中验证功能点的唯一方法就是写测试用例。我们有三个全自动化的测试系 统:Integration testing system, System testing system,以及Model-based testing system来保证整个项目的质量。其中Model-based testing system可以随机组合API生成测试用例,测试出很多正常使用情况下无法触及的死角。为了能够快速重现Model-based testing system发现的死角,我们还开发了一个回放工具,它能读入Model-based测试用例产生的日志而生成一个新测试用例,通过回放失败用例来产生一 个供开发人员调试的环境,避免了人工手动重试数千个API来重现失败用例(因为Model-based测试用例可能随机执行数日,产生数以千计甚至万计的 API调用)。下面是测试系统运行过程中的一个截图:
高性能
ZStack是目前开源软件中,唯一一款号称能够以单管理节点管理几十万物理机器,数百万虚拟机,以及响应数万并发API调用的软件。通过我们的 软件模拟器,我们测试过管理10万物理机,通过1万到3万并发API创建百万虚拟机的情况。此外我们还进行了虚拟机创建的性能测试,数据如下表:
在测试中我们只使用了单网络节点,发现DHCP/DNS软件Dnsmasq成为了性能的瓶颈。在跟Dnsmasq社区沟通后,通过打补丁的 Dnsmasq,我们能将创建10000虚拟机的时间缩短到11分钟。在使用多网络节点(多租户)的环境下,我们相信这个数据还可以进一步的提高。
ZStack的高性能受益于三个架构设计: 全异步架构,无状态服务架构,无锁架构。
全异步架构保证一个任务从API调用开始,到最后在外部设备上执行的过程都是全异步的,从而任何线程都不会因等待一个操作完成而阻塞。在我们的压 力测试中,单管理节点响应10000 API调用只用了1000个线程就可以完成。ZStack的全异步架构由三部分组成:异步消息,异步函数调用,异步HTTP调用。其中异步消息是服务之间 调用时使用的。宏观上看,ZStack的功能划分成了多个独立的服务,服务之间通过消息通信,连API都是以消息的形式实现。例如有虚拟机服务,网络服 务,存储服务等。在服务的内部存在许多组件,他们协作完成一个服务的功能。这些组件之间的调用使用的是传统的函数调用方式,通过回调函数 (callback)实现异步。最后,服务与外部agent通信时采用的是异步 HTTP调用。例如在创建KVM虚拟机时,虚拟机服务将请求提交给KVM agent后就返回了。KVM agent在虚拟机创建完成后,会通过回调HTTP链接通知虚拟机服务。
无状态服务是指通过一致性哈希环(consistent hashing ring),服务本身可以和它所管理的具体资源分离开来,服务相互之间也无需交换所管理资源的信息。例如在多管理节点部署中会存在多个虚拟机服务,他们共 同管理系统中的所有虚拟机。但每个服务自身是不需要知道哪些虚拟机是自己管理的,哪些是其它人管理的。当其它服务向虚拟机服务发送请求时,会用虚拟机的 UUID通过一致性哈希环算出管理这个虚拟机的服务,从而保证无论请求在哪个管理节点发起,最终都会被发送到相同的服务去处理。
得益于无状态服务,ZStack的所有业务逻辑无需通过锁相互竞争资源,资源竞争完全通过队列控制。由于一致性哈希环会把针对某一个资源的操作全 部转发到同一个服务,ZStack允许每个服务在内存中创建FIFO队列,以请求到达的顺序响应。对于所有操作只能顺序执行的资源,例如虚拟机,服务可以 创建并发度为1的队列,保证同一时间只有一个操作在执行。
对于允许并发操作的资源,例如物理服务器可以允许同时执行多个操作,可以创建并发度大于1的队列。
通过基于队列的无锁架构,ZStack即实现了对关键资源的操作同步,又实现了对操作并发度的控制,在提高系统的吞吐性同时,又保证了系统在大吞 吐量时的稳定性。例如物理服务器(host)资源的默认并发度是10,在系统大负荷的情况下,ZStack保证物理服务器最多响应10个请求,多的请求排 队,避免了过多的请求造成资源的崩溃。当然,资源的并发度完全是可配置的,用户可以通过API配置例如物理服务器的并发度,根据系统的负荷调整参数。
扩展性
ZStack在设计之初就考虑到了不同的用户对云的使用模式的差异性。例如公有云提供商,服务提供商,倾向于亚马逊的模式。而传统企业用户,则更 喜欢VMWare的企业虚拟化模式(Enterprise Virtualization)。基于插件系统,ZStack将每个功能实现成小插件,默认是亚马逊的EC2模式,也就是各种资源池化。然后在这个基础 上,通过一些辅助插件,ZStack可以在EC2的模式上组合出VMWare这种以虚拟机为中心的模式。这样不同的用户就可以根据自己的需求选择相应的模 式。并且两种模式还可以互通,比如以虚拟机为中心的模式也可以使用EC2模式所提供的安全组(security group),弹性IP(EIP)这样的网络服务。
除了插件系统外,ZStack也认识到很多IaaS的功能可以实现成单独的服务,并且允许开发者用他们熟悉的语言来实现。这种创建单独服务的方法 在ZStack中称为进程外插件(out-of-process plugin)。开发者可以根据自己的喜好选用自己喜欢的语言,创建与ZStack管理节点进程分离的服务。如果服务本身功能单一,可以订阅ZStack 管理节点组播到消息总线的事件(canonical events),例如账单系统就可以监听各种资源的创建和销毁事件,完全实现独立开发。对于功能复杂的服务,例如需要访问数据库的服务,可以通过写一个轻 量级的插件安装在管理节点中,然后跟进程外服务通信。第二种方式有点类似应用程序通过在操作系统中安装驱动,来实现对内核的访问。ZStack的web UI就是以这种进程外插件的方式实现的。
基于插件系统和进程外服务,ZStack可以在持续创新,开发出各种适应用户需求的应用场景的同时,保持架构的稳定和松耦合。
总结
ZStack的整个架构并非离散的功能点的组合,而是在经过精密设计后相辅相成的。例如要实现查询API自动化,数据模型就必须预先定义完备;又 比如要实现无锁架构,就必须要有无状态服务的基础。通过对架构的缜密思考,ZStack有信心解决当前IaaS行业面临的困难,为用户提供一款优秀的开源 软件。
对话张鑫
CSDN:OpenStack生态已经比较成熟,公有云私有云的成功案例都有了,我们为何还需要ZStack项目?
张鑫: IaaS领域是时候需要新鲜血液了。
自亚马逊2006年发布EC2公有云以来,IaaS(基础架构即服务)领域持续创新,先后出现了Eucalyptus, CloudStack,OpenNebula这样的开源软件。到2010年OpenStack出现,整个创新达到了一个高潮。从业者都认为云计算的春天来 了,认为传统企业可以很快的从上个世纪的IT架构中解脱出来,迅速迁移到由软件定义的数据中心。但让人大跌眼镜的是,5年过去了,Eucalyptus, CloudStack,OpenNebula已渐渐淡出人们的视线,OpenStack一统天下,却迟迟打不开企业软件的市场。就在去 年,OpenStack的发起者Rackspace,宣布不再以纯IaaS提供商的身份进入市场,而是转向专注于核心业务“为客户管理服务”,在跟以亚马 逊为首的公有云巨头的竞争中败下阵来。最近,著名OpenStack公司Nebula倒闭,给出的理由是“市场不成熟”,更是给整个IaaS产业浇了一盆 冷水。一时间各种悲观论调四起,例如认为企业云市场根本不存在,又例如公有云最终统治世界,企业不再需要自己维护数据中心。
我于2010年加入Cloud.com,作为CloudStack前核心开发人员,一直紧密的关注整个产业以及各个开源IaaS软件,深深感到市场的需求是巨大的,但当前的产品离市场的要求差距很远。随着时间的推移,这个鸿沟越来越大,丝毫没有减小的迹象。
当前开源IaaS软件的痛点可以概括为四个方面:易用性差,不稳定,性能差,难扩展。而这四个方面又是阻碍市场接受IaaS软件的至关重要的因 素。根据我多年来对各个项目的观察,认为导致目前状况的原因,并不是开源社区缺乏有才能的开发人员,而是这些项目起源太早,缺乏对市场的足够理解。这些项 目早期都是盲目模仿亚马逊EC2模式,在快速开发功能的同时自然生长,用俗话说就是“摸着石头过河”,导致了在架构设计方面思考过少,累积了大量欠账。而 前述的几个方面,又正是不从架构入手重新设计,就不能解决的问题。但我们又不能期望像OpenStack这样拥有几百万行代码的项目从底部推到重来。基于 这样的现实,我认为不重新设计一款IaaS软件是无法解决已有的问题的。在退出了原来CloudStack的工作后,我跟搭档一起建立了ZStack,希 望从根源上解决当今IaaS软件遇到的各种问题,为整个行业带来一款真正能打开企业市场的软件
CSDN:能否介绍一下ZStack的市场目标,以及社区规划?
张鑫: ZStack的最终目的,并不是为喧闹的云市场添加更多的噱头,而是解决数据中心管理的一个刚需:即面对越来越多的硬件,如何管理它们,以及如何自动化这 个管理的过程。我们相信终有一天,传统企业会摆脱人工手动配置或写脚本这种上个世纪的技术,将自身的IT架构迁移到完全通过API管理的,软件定义的数据 中心中。此外,随着企业软件技术的不断创新,最终会是以SaaS(软件即服务)的方式在IT设施中部署。到那个时候,企业软件再不是为某个操作系统所设计 的单机程序,而是为某个云设计的分布式程序。IaaS以及之上的PaaS就是这些企业软件的入口。依托ZStack的插件架构,我们完全相信我们可以逐步 完善成一个涵盖IaaS和PaaS的平台,并且由于我们是IaaS和PaaS高度集成,提供的用户体验也必然优于同类软件间的第三方集成,从而成为未来企 业软件的部署入口。
ZStack是一个开源项目,并且会一直坚持开源。我从2006年加入XEN社区到现在,就一直在开源领域工作,经历过不少成也开源败也开源的例 子。例如OpenStack发迹于社区,但现在遇到了很多困难也源于社区。对于ZStack,我们欢迎任何形式的,基于Apache 2.0许可证的贡献。同时我们会负责维护ZStack核心稳定,对于提交到核心服务的代码进行严格控制。这样的代码会是少量的,因为在插件架构下,大部分 功能会是以单独的插件方式实现。我们会推出两个目录:plugins和contribs。凡是ZStack自己的测试架构可以保证质量的插件,我们会放到 plugins目录去,由我们承诺质量。对于测试架构无法保证的插件,例如需要特殊外设配合的插件,我们会放到contribs目录,表示用户在使用时需 要自担风险。
总而言之,ZStack是个年轻的项目,是IaaS领域的一个新兵。但我们继承了先行者的经验,学到了先行者的教训,所以相信我们能比先行者走的 更远。对于现有的IaaS项目,我们也不是扮演一个挑战者,而是为这个领域提供多一个选择。用我搭档的话说:我们不是蚂蚁与大象跳舞,我们是站在大象背上 的蚂蚁,所以能看得更远。
编辑点评: 作为“站在大象背上的蚂蚁”,ZStack的插件式架构设计确有可圈可点之处。根据初步测试者的评价,ZStack也沿承了CloudStack的一些亮 点。只是目前OpenStack的社区生态已经很成熟,虽然遇到各种难题,OpenStack还是在不断的实践中得到进步,被应用于各种公有云、私有云之 中。例如金山云合伙人宋伟将在“ 2015 OpenStack技术大会 ”上分享“ Openstack 在公有云中的运用 ”, 分享金山云解决了哪些问题以及如何解决 。已经将OpenStack应用在生产环境中的用户,不太可能改换门庭。这意味着,虽有机遇,ZStack的初期发展同时还是会遇到很大的挑战。但正如张鑫所说,为这个领域提供多一个选择,总是一件好事。祝ZStack好运!(责编/周建丁)