多租户数据库

2024-05-11

多租户数据库(精选四篇)

多租户数据库 篇1

作为云计算的一个重要场景, SaaS (Software-as-a-Service, 软件即服务) 是一种通过因特网提供软件服务的模式。在该模式下, 租户通过网络向软件提供商租用软件, 服务商负责维护软件。这种模式具有很大优势, 诸如提高信息系统资源利用率、降低租户获取服务的平均成本等, 已经在在线学习、客户关系管理、ERP等领域获得了广泛应用, 并是未来软件模式发展的趋势。

SaaS采用B/S模式, 在应用服务层采用了无状态的技术, 容易进行扩展;但多租户数据存储采用有状态的技术, 扩展性较差, 在数据快速访问、数据迁移、性能和安全等方面仍有很多问题亟待研究。因此, 分析多租户数据存储带来的挑战, 比较SaaS中多租户数据存储模式, 具有重要的理论和现实意义。

1 多租户数据存储的挑战

1.1 性能问题

在多租户场景下, 资源在多个租户间进行共享, 存在以下性能问题:若采用虚拟化技术, 在租户间平均分配资源时, 可导致较低的资源利用率;若采用共享模式, 可能会致使少数租户的应用大量耗费系统资源, 进而导致其他租户可用资源降低和用户体验变差。

1.2 可扩展性问题

可扩展性是指在系统负载增长时, 应采用技术手段保证租户的性能体验, 包括响应时间和系统的可用性;在系统负载下降时, 应使用较少的资源来保证租户的性能体验, 降低服务的成本。

解决扩展性问题的办法有垂直扩展和水平扩展。垂直扩展是在单节点增加或减少资源, 本身具有诸如单节点故障、扩展容量受限等局限性。水平扩展是指增加或者减少节点, 具有增强系统健壮性、扩展方便等优点。

因为有数据模式的共享、租户数据多副本的存在、数据迁移等原因, 扩展机制的设计相比传统数据设计更加复杂和困难。

1.3 安全性问题

在多租户环境下, 由于资源的共享和系统维护向供应商转移, 可导致以下数据安全性问题:特定租户的数据对其他用户的暴露;相关法规的不健全导致对租户数据的恶意入侵。这就要求研究多租户数据的隔离和安全问题。

1.4 维护问题

在多租户场景下, 有观点认为系统的维护从租户转移到了更加专业的软件提供商, 可使得总维护成本下降, 但是多租户场景下, 由于多租户资源共享、租户定制导致系统的设计更加复杂, 有可能导致系统维护更加困难。所以系统的设计需要仔细考虑后期的维护问题。

2 多租户数据存储模式比较

Saas中的多租户数据有3种存储方式:租户专有数据模式、共享模式固定扩展列和共享模式扩展表。下面分别进行讨论, 并从系统设计角度加以比较。

2.1 租户专有数据模式

租户专有数据模式指每个租户拥有专属于自己的独立数据库实例, 或多个租户在共享数据库实例基础上拥有自己的独立模式。

第一种方式的优点有:技术上最容易实现、可维护性最好、租户数据安全性最好、可以进行任意扩展。缺点是:资源共享最差, 系统利用率最低, 因为同一台机器上可同时运行的数据库实例数非常有限, 而系统可能面对很庞大的租户数。

第二种方式相比第一种租户数据安全性稍有降低, 但现有条件下技术上仍然可行, 扩展性也比较好, 资源利用率有所提高, 但是相比于后面两节介绍的模式资源利用率仍然较低, 因为一个数据库实例支持的模式数目相比于租户数仍然可能有限。

2.2 共享模式固定扩展列

共享模式固定扩展列定义为:

SchemaName (TenantID, ATTR1 Type1, …, ATTRm Typem, ATTRm+1 Varchar (K) , …, ATTRm+n Varchar (K) )

这种模式下租户共享数据库实例, 若租户的数据存在相同的属性, 将各个租户的数据存储在共享模式中, 表中各个租户相同的数据使用相同的列ATT1-ATTm, 根据实际和预期的需求预留一定数量的列ATTRm+1-ATTRm+n供租户定制专有或者个性数据, 设置一个租户标识列TenantID用来区分不同租户的数据。因为预留列类型都是Varchar, 所以需要利用元数据来支持数据存储模型向逻辑模型的映射。

相比租户专有数据模式, 这种模式的优点是:资源利用率更高, 因为用数量较少的表格来存储大量数目租户的数据;便于向逻辑数据模型映射。缺点是:因为存在null值问题, 导致存储空间的浪费;隔离性较差, 需要研究租户隔离和租户数据安全机制;因为丧失了关系数据库的特性和机制, 引起一系列新问题, 比如不便于建立索引、租户个性数据的定制和向逻辑数据模型映射需要大量元数据的支持;数据量的增大和租户的竞争导致系统性能下降等。

2.3 共享模式扩展表

这种模式下定义一个基本表和一个扩展表:

SchemaName (TenantID, RowID, ATTR1 Type1, …, ATTRm Typem)

ExSchemaName (TenantID, RowID, ColName Varchar (K1) , Val Varchar (K2) )

将各个租户相同的数据存储在基本表中, 同时利用扩展表存储租户定制的数据。因为扩展表数据类型是Varchar, 所以需要利用元数据支持数据存储模型向逻辑模型的映射。

与前两者相比, 这种模式的优点是扩展性更好, 避免了过多的null值。缺点是:因为扩展表丧失了关系数据库的特性, 在数据检索、索引、更新等方面比较复杂;隔离性较差, 需要研究租户隔离和租户数据安全机制;和2.2中的模式一样, 它也要面临处理大量元数据和租户的资源竞争问题。

3 结束语

通过以上分析, 可以得出以下结论:①租户专有数据模式适用于对安全性、隔离性要求比较高的应用, 但支持的租户数目有限;②共享模式扩展列和共享模式扩展表能支持大量的租户数目, 但是隔离性较差。

相比于共享模式扩展列, 共享模式扩展表能提高存储资源利用率, 应是面向中小企业SaaS应用设计中多租户数据存储的发展方向。

文献[5]提出的Pivot Table Layout、Chunk Table Layout和Chunk Folding可借鉴以实现扩展表, 但在关系数据库系统上实现多租户数据存储尚需深入研究以下问题:数据隔离和数据安全机制;数据索引、更新的机制和算法;设计扩展机制、建立解决性能问题和负载均衡的数学模型。

参考文献

[1]C.BEZEMER, A.ZAIDMAN.Multi-tenant saaS applications:maintenance dream or nightmare[C].In Proceedings of the 4thInternaitonal Joint ERCIM/IWPSE Symposium on Software Evo-lution (IWPSE-EVOL) , 2010.

[2]SENGUPTA, ROYCHOUDHURY.Engineering multi-tenant soft-ware-as-a-service systems[C].ICSE'11, 2011.

[3]AULBACH, JACOBS, ETC.A comparison of flexible schemas forsoftware as a service[C].SICMOD, 2009.

SaaS多租户数据管理及实现策略 篇2

云计算已经成为最重要的计算技术。云计算是一个能够方便地按需对可配置计算资源 (例如网络、服务器、存储、应用程序和服务) 的共享池进行网络访问的模型[1]。目前在云计算范式中最重要的服务是软件即服务 (Saa S) , Saa S是软件的一种新型的云计算服务交付模式, 可通过互联网以“按需服务”的形式为多个用户提供应用程序。企业通过订购Saa S服务, 无需购买和维护自己的IT设施就可使用各类IT服务, 减少了软硬件、网络、系统维护的费用。而对于服务提供商, 则通过发挥Saa S的规模效应来降低综合使用成本。如Saleforce.com、Goole.com、Alisoft.com等都是Saa S应用的典型成功案例。Saa S应用程序最重要的需求是多租户的支持[2], 为了最大化Saa S的规模效应, 一般采用的都是多个租户共享一个运行实例的架构 (Multi-Tenant架构, 即多租户架构) 。

多租户是SAAS业务模型领域一种较新的软件架构, 在此架构模式中, 允许多个租户共享硬件资源以及应用程序和数据库, 并可根据租户需求配置应用程序[3]。可配置性是多租户模式的重要特征。在多租户应用中, 所有的租户都使用同一个数据库实例, 因此必须确保每个租户只能访问它们各自的数据, 因此数据隔离成为多租户应用中最为关键的问题[4]。

2 多租户数据存储方案 (Data storage schema for muti-tenant)

Saa S区别于传统技术的重要差别就是多租户模式, 多租户架构是Saa S应用的基本特性, 也是实现Saa S规模效应的基本要素。多租户就是多个租户共用一个实例, 租户的数据既有隔离又有共享, 因此多租户设计的关键是如何解决数据存储问题。

2.1 多租户数据存储方案

目前管理多租户数据主要有三种方法[5]:独立数据库、共享数据库和独立数据模式、共享数据库和共享数据模式。

独立数据库方式是指一个租户一个数据库, 如图1所示, 这是进行数据隔离最简单的方法, 该方案用户数据隔离级别最高, 安全性最好, 但成本也高。该方案的优点是:为不同的租户提供独立的数据库, 有助于简化数据模型的扩展设计, 满足不同租户的独特需求;如果出现故障, 恢复数据比较简单。该方案的缺点是:增大了数据库的安装数量, 随之带来维护成本和购置成本的增加。

共享数据库和独立数据模式是指多个或所有租户共享数据库, 但一个租户一个数据模式。如图2所示。该方案的优点是:为安全性要求较高的租户提供了一定程度的逻辑数据隔离;每个数据库可以支持更多的租户数量。缺点是:如果出现故障, 数据恢复比较困难, 因为恢复数据库将牵扯到其他租户的数据;如果需要跨租户统计数据, 存在一定困难。

共享数据库和共享数据模式是指租户共享同一个数据库, 同一个模式, 但在表中通过租户ID区分租户的数据, 如图3所示。这是共享程度最高、隔离级别最低的模式。该方案的优点是:维护和购置成本最低, 允许每个数据库支持的租户数量最多。缺点是:隔离级别最低, 安全性最低, 需要在设计开发时加大对安全的开发量;数据备份和恢复最困难, 需要逐表逐条备份和还原。

2.2 三种方案的比较及选择

从隔离和共享两个相反的方向比较, 依次是独立数据库、共享数据库和独立数据库、共享数据库和共享数据模式, 三种方案比较如图4所示, 三种方法都有各自的优缺点。选用时可以从经济性、安全性、租户以及技能等因素去考虑。

因为开发共享结构相对比较复杂, 在初始开发时需比使用独立方法设计应用程序付出更大的开发工作, 但每个服务器可支持更多的租户, 持续的运营成本更低。因此如果无法为构建一个共享模式应用提供足够的开发支持或需要尽快使应用上市而不能进行大规模开发, 那么必须更多的考虑独立的方法。

如果应用程序存储了敏感的租户数据, 客户都会对安全性有较高的预期, 需要提供强大的数据安全性保障服务水平协议 (SLA) 。通常依靠物理隔离可以提供较好的安全级别。使用共享方法存储数据也可以提供强大的数据安全, 但需要使用更复杂的设计模式。

服务的租户数量、属性和需求也是确定不同方式数据架构的因素。租户越多越要多考虑共享方法。如果各租户需存储大量的数据, 独立数据库方法可能会更好。需要支持每个租户的并发终端用户数量越大, 独立方法将越适合满足终端用户的需求。如果希望为每个租户提供增值服务, 如每个租户的备份和恢复能力, 这样的服务通过独立的方法更容易提供。

设计单实例多租户架构仍然是很新的技能, 缺乏现成的专业技能。如果设计师和职员没有足够的构建Saa S应用的经验, 他们需要获得必要的知识, 或者必须雇佣有经验的人员。在某些情况下, 独立方法比共享方法可更多地利用传统软件开发的现有知识。

3 多租户数据库实现 ( Realizing multi-tenant database)

与上述三种数据存储管理相对应的有三种实现多租户数据库的方法[6]:共享主机、共享进程和共享表。

在共享机器的方法中, 每个客户都有自己的数据库进程并且多个客户共享同一个主机。此方法无需修改数据库的实现, 基本上不会降低客户隔离度。但该方法不是池式内存, 每个数据库在每个应用服务器上都需要有自己的连接池, 套接字无法在客户间共享。

在共享进程方法中, 每个客户都有自己的表并且多个客户共享同一个数据库进程。此方法更有利于池式内存, 可方便进行每个服务器的客户数扩展。客户间可以共享连接池。

共享表方法对于池式资源是最合适的。扩展能力仅受限于数据库支持的行的数目, 比共享进程方法要提高几个数量级。客户能共享连接池, 可以成批执行管理操作。但该方法由于在磁盘上的文件是来自多个租户的混合数据, 迁移比较困难。另外混合数据分布在许多页会影响访问客户数据的性能, 共享连接池和数据使安全性成为最关键的问题。

为了实现多租户, 大多数托管服务使用查询变换把应用程序中的多个单租户逻辑模式映射到数据库中一个多租户物理模式。这种方法会降低服务器的性能, 改进的方法是在租户间共享表, 但这种技术可能会影响租户扩展应用程序的能力。最灵活的解决方案是将逻辑表映射到固定的通用结构, 如通用表和透视表。

实现共享表的多租户数据库可采用多种存储模型, 这些模型称为模式映射技术[7], 主要有基本布局、私有表布局、扩展表布局以及通用表布局、透视表布局、Chunk表布局等通用结构。

(1) 基本布局

实现多租户的最基本的技术是每个表增加一个租户ID列 (Tenant) , 所有的租户共享此表。这种方法是从服务提供者的角度而不是租户角度来看待数据, 提供了较好的合并但不具有扩展性, 传统Web应用程序大都采用此方法。

(2) 私有表布局

支持扩展性最基本的方法是每个租户设置各自的私有表。在此方法中, 查询转换层只需要重命名表名, 非常简单。此方法每个租户都有不同的业务需求, 需要有大量的表来满足每个租户的需求, 因此该技术适用于较少数量的租户。

(3) 扩展表布局

可以结合上述两种方法, 扩展成不同的表。将源表分成基表和扩展表两部分, 多个租户可以使用同样的基表, 扩展表和基表都需要一个Tenant列, 还要增加一个Row列。这种方法比私有表提供了更好的合并性, 但表的数量也会与租户数成比例增加。

(4) 通用表布局

通用结构允许创建任意形状任意数量的表。通用表是一个有Tenant列、table列和许多通用数据列的通用结构表。数据列设置成一个灵活的类型, 如VARCHAR类型, 其他的类型可转换为该类型。每个租户的每个逻辑源表的第n列映射到通用表的第n个数据列, 因此不同的租户可以以不同的方式扩展同一个表。该种方法的缺点是数据表较宽, 数据库必须要处理许多空值, 另外对索引支持不是太方便。

(5) 透视表布局

透视表是一个可选的通用结构, 在透视表中, 逻辑源表中的每一行的每个字段都对应着一行。除了上述描述的Tenant、Table和Row列, 透视表还有一个Col列指明了这一行所表示的是源表中的哪个字段以及一个数据列表示出那个字段的值。数据列可以给定一个灵活的类型, 如VARCHAR, 其他类型也可以转换为此类型。此方法无需处理许多空值, 可以较好地支持索引, 但增加了元数据, 增加了运行开销, 连接操作较费时。

(6) Chunk表布局

第三类通用表称之为Chunk表。Chunk表类似于透视表, 但有一组不同类型的数据列, col列被Chunk列取代, 一个逻辑源表被划分为多组列, 每组设置一个chunk_ID, 将一组列映射到一个Chunk表中。相比透视表, 该方法减少了存储元数据, 降低了重构逻辑源表的开销。

(7) Chunk Folding

这是一种将源表垂直划分成块放入不同物理多租户表的一种技术, 在需要的时候可进行连接。该技术将最常使用的租户列映射到传统表中, 而其他列放在Chunk表中, 数据库的“元数据开销”分摊给了专用的传统表和一组称为CHunk表的通用结构。应用Chunk Folding方法, 参考文献[8]中提出了基于Chunk Folding的自适应多租户缓存管理机制, 该机制以租户的SLA需求作为驱动, 依据租户当前访问模式, 动态生成缓存单元集并计算缓存单元集的I/O效益, 通过贪婪算法来选择缓存单元集, 使得租户SLA得到满足的同时最小化缓存资源的消耗。

4 XML支持实现多租户数据库 (XML for realizing multi-tenant database)

XML和关系数据库是两种完全不同的技术集, XML支持层次数据模型, 而数据库支持关系数据模型。关系数据库的缺点是在数据库层缺乏对租户概念的支持, 因此, 必须在通用表的行存储租户ID。在参考文献[9]中提出了一种针对多租户应用的混合模式共享技术, 该方法由两张表组成, 一张用于租户的通用内容, 如ID、名称、联系方式等, 如表1所示。

另一张扩展表针对每一个租户。扩展表由两行组成:一是租户的ID, 另一行包含了一个描述某一个租户的其他信息的XML文档, 如表2所示。每个租户都有其存储空间存储私有数据。该方法采用了将扩展表与XML文档相结合的基本思想。

当租户进行查询时, 在运行时都通过附加一个租户ID来执行, 以XML形式存储数据的优点是:特定租户数据的查询不会因要避免空值而受到干扰, 可对租户字段进行索引因而可对每一个租户进行查询优化。

5 结论 (Conclusion)

多租户是Saa S软件的一种架构模式, 可在多个租户间共享单应用实例, 最大化Saa S的规模效应。多种模式映射技术应用于多租户应用中可解决数据共享和数据隔离, 但如何更好地构建多租户架构, 设计数据管理服务, 提高性能并保证安全性, 仍然是一个很大的挑战。下一步的主要工作是设计适合实际应用环境的模式映射技术算法。

参考文献

[1]Peter Mell, Timothy Grance.The NIST definition of cloud computing[J/OL].http://csrc.nist.gov/publications/nistpubs/800-145/SP800-145.pdf, September 2011.

[2]Guo J., Sun W., Huang Y., Wang Z., Gao B.A Framework for Native Multi-Tenancy Application Development and Management[C].in Proceedings of The 9th IEEE International Conference on E-Commerce Technology and the 4 th IEEE International Conference on Enterprise Computing, Tokyo, Japan, July 23-26, 2007:551-558.

[3]Bezemer C., Zaidman A.Multi-tenant Saa S applications:maintenance dream or nightmare?[C].Proceedings of the Joint ERCIM Workshop on Software Evolution (EVOL) and International Workshop on Principles of Software Evolution (IWPSE) :88-92.

[5]G.C.Frederick Chong, R.Wolter.Multi-Tenant Data Architecture[J/OL].https://msdn.Microsoft.com/en-us/library/aa479086.aspx, 2006.

[6]Dean Jacobs, Stefan Aulbach.Ruminations on multi-tenant databases[C].In Datenbanksysteme in Business, Technologie und Web (BTW) , 12.Fachtagung des GI-Fachbereichs Datenbanken und Informationssysteme (DBIS) , Proc.7.-9.M rz, volume 103of LNI, GI, 2007:514-521.

[7]S.Aulbach, T Grust, D.Jacobs, A.Kemper, J.Rittinger.Multitenant databases for software as a service:Schema mapping techniques[C].Proceedings of the 34th Intetnational Conference on Management of Data (SIGMOD) , 2008:1195-1206.

[8]姚金成, 等.基于Chunk Folding的多租户数据库缓存管理机制[J].计算机学报, 2011, 34 (12) :2319-2331.

多租户数据库 篇3

关键词:多承租,Portlet,协作,可订制

0 引 言

SaaS意味着一种全新的商业模式。这种商业模式的核心特征可概括为[1,2,3]:1) 软件部署为托管服务通过互联网访问,使得整个IT基础设施的管理和维护责任从客户转移到了外部供应商。2) 用户定制自己需要的服务模块,在用户层形成个性化差异,这种定制包括特定的界面、业务流程、数据结构等,对SaaS软件的开发提出了很高的要求。3) 通过租用的方式收取费用,企业用户根据选用的功能模块的不同和使用时间的长短采取租用的方式向SaaS服务提供商付费,彻底改变了传统软件的交付行为,客户和SaaS服务提供商达成租约,客户成为服务的租户。

在软件实现层面,SaaS对软件开发带来的改变在于其提出了“多租户”这一新的概念。两个公司(租户)租用同一个部署在服务运营商处的服务,租户对服务进行定制,形成自己看到的软件形态,不同租户公司内部的用户所看到的是不同的软件,彼此之间相互透明。在软件体系结构上对多租户支持的不同实现方法形成了SaaS软件成熟度模型[4]。如图1所示。

Level1成熟度相当于原来的ASP(Application Service Provider)模式,在实现层面上每个租户对应一个软件实例,每个实例根据租户的特性需求开发,彼此不同相互独立。Level2成熟度也是每个租户一个软件实例,但这些实例都是基于同一套相同的代码和数据结构,不需要根据每个用户的需求进行重新开发,在代码开发时充分考虑了可配置性,针对不同的租户采用灵活的配置来生成软件实例。Level3成熟度是指用一个软件实例满足所有租户的要求,除了可配置之外还增加了“多承租”特性,使同一实例能够承担多租户的请求,而租户的UI、流程、数据结构等都通过技术手段加以隔离。这就是SaaS模式下的多承租体系结构。Level4成熟度是在Level3的基础上加入了负载均衡,以便提高应用的性能和可扩展性。

Level3级别的多承租体系结构和技术是SaaS软件成功的关键,它降低了服务运营商的成本,最终使SaaS模式在商业上成为可能[5]。

以SaaS的方式提供Portal服务,不仅可以利用云计算等后台技术降低服务运营商的成本,而且其租用模式也大大降低了服务使用者的维护成本,这将使Portal产品更加具有市场竞争优势。Portal系统由若干Portlet组件构成[6],规范定义了Portlet间的协作方式。在SaaS模式下不同租户必然有自己特殊的协作需求,这就要求Portal系统提供租户可订制的Portlet协作方式,对现有规范所定义的协作模型提出了全新的挑战。

1 现有Portlet协作规范对多租户的支持

1.1 Portlet协作规范

JSR286规范是门户技术的核心,它完整地定义了Portlet组件的使用方法和接口,规范定义Portlet组件有两种专门的协作方式:

一是基于公共渲染参数的协作。可以定义在各Portlet间共享的公共渲染参数,在动作处理阶段组件可以设置该参数的值,在随后的Render阶段支持该共享参数的Portlet都能看到被设置的值,以此来达到协作的目的。

二是基于事件的协作。组件间还可以通过事件机制进行协作,在动作处理阶段组件发送定义好的事件,事件的发生会引起其它组件的被调用,在事件处理阶段组件仍然可以继续发送事件。如下配置片断所示:

<public-render-parameter>

<identifier>foo</identifier>

<qname xmlns:x=″http://example.com/params″>x:foo2</qname>

</public-render-parameter>

<event-definition>

<name>event1</name>

<value-type>java.lang.String</value-type>

</event-definition>

<portlet-name>portletA</portlet-name>

<supported-public-render-parameter>

<name>foo</name>

</supported-public-render-parameter>

<supported-publishing-event>

<name>event1<name>

</supported-publishing-event>

定义了公共渲染参数foo和事件event1,且PortletA声明了支持公共渲染参数foo并且可发送event1。

1.2 对多租户的支持

当Portal系统SaaS化时,不同的租户将定制自己需要的Portlet组件协作方式。但现有协作规范只能以Level1级别的方式来实现多租户对Portlet协作的定制,即为每个租户单独开发和部署其专有的Portlet组件。这种非“多承租”方式给Portal的SaaS化带来了极大的开发负担。

现有规范定义的协作模式无法区分不同租户对同一组件定义的不同的事件接收与发送集合,虽然在配制文件中不会造成冲突,但是由于不能区分不同租户的定制,会给容器带来混乱和极大的运行时开销。如图2(a)所示。

租户1定制了PortletA与PortletB以事件Event1进行协作,租户2则定制PortletA与PortletC以事件Event1进行协作,现有的组件模型规范下组件容器感知到的是如图2(b)中的样子,即PortletA以事件Event1同时和PortletB与PortletC进行协作。当事件Event1被触发时,容器同时调用组件PortletB与PortletC的事件处理方法。这种不能区分不同租户对同一组件所定义的事件接收集合与发送集合的弊端,将给协作带来流程的混乱并给容器实现带来极大的运行时开销。

本文对规范定义的协作模型进行扩展,使得扩展后的Portlet可以以单实例多租户的“Level3”级别的方式来实现多租户的定制。

2 支持多承租体系结构的Portlet协作模型

2.1 对协作配置的扩展

为了使单个Portlet组件可以感知不同租户所定制的不同的协作行为,首先扩展配置文件的表达能力,在配制文件中加入<Tenant>元素以表示租户信息。如下的配置片断所示:

<portlet-app>

<description>公司A</description>

<name>公司A</name>

<description>公司B</description>

<name>公司B</name>

定义了两个租户(公司A和公司B)。为了隔离不同租户对同一组件的协作行为增加<tenantspecific>元素,该元素为<supported-processing-event><supported-publishing-event><supported-public-render-parameter>元素的子元素,使得每一个被支持的公共渲染参数和事件都能关联到一个租户上,以此描述租户定义的协作范围,如下片断所示:

<portlet-name>portletA</portlet-name>

<supported-public-render-parameter>

<name>foo</name>

<tenantspecific>

<tenant-ref>公司A</tenant-ref>

</tenantspecific>

</supported-public-render-parameter>

<supported-publishing-event>

<name>event1<name>

<tenantspecific>

<tenant-ref>公司A</tenant-ref>

<tenant-ref>公司B</tenant-ref>

</tenantspecific>

</supported-publishing-event>

<portlet-name>portletB</portlet-name>

<supported-public-render-parameter>

<name>foo</name>

<tenantspecific>

<tenant-ref>公司A</tenant-ref>

<tenant-ref>公司B</tenant-ref>

</tenantspecific>

</supported-public-render-parameter>

<supported-processing-event>

<name>event1<name>

<tenantspecific>

<tenant-ref>公司A</tenant-ref>

</tenantspecific>

</supported-processing-event>

<portlet-name>portletC</portlet-name>

<supported-public-render-parameter>

<name>foo</name>

<tenantspecific>

<tenant-ref>公司B</tenant-ref>

</tenantspecific>

</supported-public-render-parameter>

<supported-processing-event>

<name>event1<name>

<tenantspecific>

<tenant-ref>公司B</tenant-ref>

</tenantspecific>

</supported-processing-event>

租户公司A定义了其共享参数和事件的协作范围为PortletA与PorteltB,而租户公司B定义了其共享参数的协作范围为PortletB与PortletC,事件的协作范围为PortletA与PorteltC,如图3所示。

这就使不同的租户间定制的共享参数和事件发送与接收的范围得到了隔离。

在运行时的隔离由组件容器来保证,容器必须把公共渲染参数发送到相同租户所定义的范围内且声明支持此参数的那些Portlet组件,组件容器必须仅在相同租户定制范围内的Portlet组件间共享此公共渲染参数。

事件的发送和接收也采用同样的原则,在一次请求处理间组件容器必须保证组件只能触发当前租户订制范围内的事件,对于触发的事件,组件容器只能调用当前租户订制范围内的且声明支持此事件处理的Portlet组件中的ProcessEvent方法。

对Portlet组件的配置和运行时语义做了上述修改后,组件可以识别租户的信息并有效地隔离不同租户对协作的定制,使组件可以用单实例的方式来满足多个租户的需求,满足了Level3级别的多承租体系结构的需求。

2.2 对访问接口的扩展

为了保证运行时租户定制的有效性必须在规范中增加新的接口并重新定义相关已有接口方法的语义。在规范中新增Tenant接口,租户信息由该接口得到,其包含方法为getDescription()和getName()。对已有接口的扩展如图4所示。

1) 在PortletConfig接口中新增getTenants()方法,该方法返回配制文件中所有定义的租户信息。新增getProcessingEventQNames(Tenant tenant)返回指定租户范围内该Portlet组件所有声明支持处理的事件的QName,如果没有与该租户相关的支持处理事件则返回一个空枚举对象。类似方法还有getPublicRenderParameterNames(Tenant tenant)和getPublishingEventQNames(Tenant tenant)。

2) 在PortletRequest接口中重新定义方法getPublicParameterMap(),该方法必须返回与此次请求相关联的租户定制的公共渲染参数的Map对象,如果没有与该租户相关联的公共渲染参数则返回一个空Map。该接口中一切与得到公共渲染参数相关的方法,如getParameter和getParameterMap,都应该遵守以上规则,当公共渲染参数对组件不可见时,该参数的返回值为NULL。

3) EventRequest接口中重新定义方法getEvent(),容器必须保证每次调用该方法所得到的事件为当前发起请求的租户所定制。

4) StateAwareResponse接口中重新定义方法 removePublicRenderParameter(java.lang.String name),当调用此方法时,如果被移除的公共渲染参数被当前租户所定制,则容器只移除该租户对该公共渲染参数的定制;如果该公共渲染参数不被当前租户所定制,则此调用不产生效果。setEvent和setRenderParameter方法也必须考虑当前发起请求的租户,只有当设置的事件和公共渲染参数在当前租户定制范围内时这些调用才发生效果。

5) EventResponse接口中重新定义方法setRenderParameters(EventRequest request),当被设置的是公共渲染参数时,容器必须保证只有当该公共渲染参数被当前请求所关联的租户定制的情况下此设置才发生效果。

6) BaseURL接口中的getParameterMap()方法和setParameter方法作同样的处理。PortletURL接口中的removePublicRenderParameter(java.lang.String name)方法与StateAwareResponse接口中的作同样的处理。

3 多承租可订制的Portlet协作的设计

为了实现对规范的扩展,必须对Portlet容器中portlet协作模块进行扩展,新增租户管理模块并对已有的协作实现流程进行扩展。

3.1 租户管理模块

在容器中加入租户管理模块(TenantManager),该模块提供对租户的管理,租户信息的获取和租户相关的信息过滤与隔离机制。模块主要的对外接口为:

getTenants:返回系统现有的所有租户信息,该信息可通过规范新增的Tenant接口访问。

isPublicRenderParameterAllowed:在一次请求期间,判断给定Portlet所要读取的公共渲染参数是否被某一租户所以定制。

isPublishEventAllowed:在一次请求期间,判断给定Portlet所要发布的事件是否被某一租户所定制。

isProcessPortletAllowed:在一次请求期间,判断给定事件的接收Portlet是否在某一租户的定制范围内。

3.2 基于租户的协作过滤

协作模块已经提供了两个接口来支持基于公共渲染参数的协作,在多租户模式下,每次调用setPublicRenderParameter和getPublicRenderParameter方法时,都要调用租户管理模块来进行基于租户的过滤。只有当被读取的公共渲染参数被当前的租户所定制时,此读取动作才发生效果,如图5所示。

公共渲染参数设置 Portlet在ActionProcessing或者EventProcessing阶段通过PortletResponse的setRenderParameter设定渲染参数,PortletResponse将调用协作模块的setPublicRenderParameter,该方法会调用租户管理模块的isPublicRenderParameter方法进行基于租户的过滤,如果过滤为真,则协作模块将该参数保存到共享空间中。

公共渲染参数获取 在Portal的渲染阶段,Portlet可以通过PortletRequest的getParameter等方法获取参数,该方法会调用协作模块的getPublicRenderParameter 方法取出参数,这里同样调用租户模块进行基于租户的过滤。

Portlet在动作处理时通过PortletResponse发布事件。容器已经实现了对事件的注册管理和注册事件的分发,在多租户模式下协作模块在事件注册时必须进行基于租户的过滤,只注册当前租户定制了的事件;在对注册的事件进行分发时,也必须对目标Portlet进行基于租户的过滤,只把事件分发给当前租户定制了的Portlet。图6描述了新的事件处理流程。

事件发布 Portlet在ActionProcessing或者EventProcessing阶段通过PortletResponse的setEvent可以发布事件。如果该事件是Portlet支持的发布事件,该事件会调用协作模块的registerEvent方法,在该方法种调用租户管理模块的isPublishEventAllowed方法进行基于的过滤,如果过滤结果为真,则该事件被注册到协作模块中。

事件分发 对于注册到协作模块中的事件,协作模块根据容器中Portlet的定义信息查找可以处理该事件的Portlet,并调用租户管理模块进行基于租户的过滤,然后请求容器对该Portlet发起事件请求。

3.3 在OncePortal系统中的实现

OncePortal[7]是由中科院软件所基于J2EE平台开发的门户中间件,目前最新版本支持JSR286规范。根据上面的设计思路,我们在OncePortal中实现了支持多租户可订制的Portlet协作模型。

在Portlet.xml文中新加入了两个元素,<tenant>元素是<portlet-app>的子元素,它用来表示租户信息。它包含两个子元素,<description>元素表示租户的描述信息;<name>元素表示租户的名称,该名称在Portlet-app范围内必须唯一,一般可使用租户的公司名称。扩展了<supported-processing-event>、<supported-publishing-event>和<supported-public-render-parameter>三个元素,在每个元素下增加了<tenantspecific>元素,该元素表示租户对事件和公共渲染参数的订制信息。它包含多个名为< tenant-ref >的子元素,该元素的内容为<tenant>元素中的<name>的值,以此表示该租户订制了该Portlet对某个协作参数的支持。

在OncePortal的Portlet容器中加入“租户管理模块(TenantManager)”。整个容器的模块结构变为如图7所示。

协作模块(CoordinationHandle)需要调用租户管理模块进行协作流程的过滤,具体方法已在3.2节中论述。应用注册模块(PortletAppRegistry)要根据新的Portlet.xml文件做修改,环境管理模块要负责提供加入租户信息的接口对象,以实现对规范定义的接口的扩展,实现细节不再赘述。

3.4 租户管理模块包结构

在容器中租户管理模块实现为租户管理服务(TenantManager),容器中的包结构如图8所示。

Service.TenantManager包中TenantManagerService类用于以服务的方式实现租户管理模块;om.tenant包中Tenant类用于实现租户数据结构,TenantInterface类用于实现租户数据接口。

4 应用案例

考虑一个以SaaS方式提供的旅行门户网站,其中一个Portlet负责输入对旅行的需求,如期望的日期、人数和地点等信息;另一Portlet(旅行定制Portlet)包装了旅行社提供的旅行定制服务,该服务可能通过Web Service的方式提供,对输入的旅行需求给出相关的旅行计划和费用。由于各大旅行社开放的Web Service接口的不同,开发了不同的旅行定制Portlet,如对中国国旅的包装(PortletForGL)和对中国青年旅行社的包装(PortletForQL)。负责输入的Portlet与旅行定制Portlet基于事件进行协作。在多租户模式下,公司A可能会选择PortletForGL来做自己的旅行规划,而公司B则选择PortletForQL来做自己的旅行规划。于是形成了租户对Portlet协作的定制。

在以前的模型下由于无法进行租户间协作范围的隔离,在系统被并发访问时很可能造成租户之间的影响,只能采取为不同的租户部署不同的应用实例的方法来满足需求,如图9(a)所示。

扩展后的模型由于有配置文件和运行时的支持可以以单实例的方式来部署系统,如图9(b)所示。不仅大大减少了系统部署和维护的开销,而且也免去了多次为不同租户定制Portlet组件的开发负担。

扩展后的协作模型并不影响程序员对Portlet组件的开发,一方面减低了Portlet组件开发的难度;另一方面也使得扩展后的接口保持与原规范的兼容,使以前的组件不必重新编译(需要改写配置文件)就可移植到新的SaaS环境中来。

5 结 语

以SaaS的方式提供Portal服务,不仅可以减少运营商的成本,而且也大大降低了购买者的维护费用,使Portal产品更具有市场竞争力。但SaaS模式的多承租架构要求软件具有更好的可订制型,以满足不同租户的个性化需求。本文通过扩展Portlet规范,增加新的配置元素以及扩展相关接口方法,给出了单实例多承租体系下支持多租户可订制的Portlet协作模型,使Portlet组件可以更好地满足SaaS下多承租体系的需求。

参考文献

[1]http://zh.wikipedia.org/wiki/SaaS.

[2]孙泠.SaaS中国模式突围[N].软件世界,2007-12-20.

[3]European Commission Information Society and Media.The Future ofCloud Computing,opportunities for European cloud computing beyond2010[R].Rapporteur for this report:Lutz Schubert[USTUTT-HLRS].

[4]Thao K T,Lam N L.A Software as a Service with Multi-tenancy Supportfor an Electronic Contract Management Application[C]//SCC’08:2008 IEEE International Conference on Services Computing.

[5]EECS Department,U C Berkeley.Above the clouds:A Berkeley Viewof cloud computing[R].2009-2-28.

[6]JSR286:Portlet Specification2.0[S].Java Community Process,2008.

多租户数据库 篇4

随着虚拟化技术的快速发展,云计算在大型数据中心网络中已经得到大规模应用,对网络的性能要求和安全要求也越来越高。与服务器虚拟化类似,网络虚拟化技术的发展使得云服务提供商能将物理网络设备抽象成虚拟的网络设备提供给租户,并允许每个租户创建自己的虚拟网络,结合租户申请的虚拟机资源定义网络拓扑,对虚拟网络进行管理[1]。

对云服务提供商而言,虚拟网络的基本需求是:允许网络中多租户共存,即在同一套物理网络环境中,支持创建多套具备独立服务模型、拓扑和IP地址空间的租户虚拟网络[2]。而从租户的角度来看,不仅要求能够创建一套独立的虚拟网络,在其中运行业务,而且要求确保租户数据的隔离和安全性,保证数据不会遭到来自其他租户以及外部网络的非法访问。

在传统物理网络环境中,不同网络之间的隔离通常由部署在网络边界处的路由器和防火墙完成。同样,虚拟网络的隔离也应当在虚拟网络的边界处实现。但相比之下,虚拟网络环境中的网络边界更加模糊,缺乏明确的定义,因此为租户虚拟网络提供路由及防火墙服务也更为复杂。同时,租户虚拟网络到实际物理网络拓扑的映射是相对分散的,同一租户控制的虚拟机很可能分布在多台物理服务器上,可见租户虚拟网络的边界可以细化到各物理服务器的边缘,需要更加细粒度的网络隔离。

结合典型的虚拟网络应用场景来看,虚拟网络中的边界可分为以下几类,如图1所示:

(1)不同租户的虚拟网络之间的边界;

(2)同一租户虚拟网络下,不同虚拟子网之间的边界;

(3)租户虚拟网络与外网之间的边界。

在当前主流的开源云平台中,已经有针对虚拟网络安全隔离的解决方案,通过为租户网络创建虚拟路由及防火墙的方式实现虚拟网络的安全隔离[3]。在现有架构下,所有租户的虚拟路由器及防火墙设备都位于同一物理节点,涉及租户网络边界的流量都被集中到该节点上进行处理,存在引发单点故障的隐患,同时也增加了虚拟机通信的网络延迟。

1 相关工作

1.1 相关研究进展

上文提到虚拟网络的边界更模糊,需要更细粒度的网络安全隔离措施。学术界针对虚拟化环境下的安全隔离问题有不少研究,并结合网络功能虚拟化(NFV)的概念,将虚拟防火墙一类的网络设备定义为网络中间件(Middle Box)。文献[4]提出Net VM平台,将防火墙、路由器一类的设备部署在虚拟化层,相比预先部署在专用硬件设备的方案更具灵活性;同时,Net VM利用Intel的DPDK库和零拷贝技术,提升了虚拟化层的网络速率和吞吐量,并实现网络高性能。文献[5]围绕网络功能虚拟化的概念,提出Click OS虚拟化平台,在其中部署高性能的中间件平台,包括虚拟防火墙、NAT、负载均衡器等,优化中间件的数据包处理,提供了一种通过软件实现网络中间件的方案。文献[11]则重点关注虚拟网络性能,提出Pulsar平台来为租户提供虚拟数据中心(VDC)的抽象模型,并保证虚拟网络性能达到租户的需求。

可见学术界多数研究的重点关注集成、管理和扩展中间件部署的能力和虚拟化I/O问题,旨在提升数据包通过虚拟机与物理机之间的速率,提高中间件平台的可用性。此外,Cloud MB项目[6]关注虚拟网络服务初始放置的优化,期望在物理拓扑和流分布可知的情况下,通过启发式算法计算出虚拟网络服务部署的合理位置,避免可能导致性能瓶颈的机架间流量。文献[2,10]都为多租户提供独立的IP地址空间,采用数据包封装技术来区分并隔离不同租户。

而在工业界,针对虚拟网络层面的安全隔离问题,有不少解决方案试图通过定义虚拟网络的边界,并在相应边界物理节点部署虚拟路由及防火墙的方式来实现隔离。云计算环境中提供的服务范围越来越广,防火墙即服务的概念也已产生,虚拟防火墙及路由器以服务的方式提供给租户,租户可以为自己的子网申请虚拟路由器及防火墙,并为虚拟网络的防火墙添加策略和规则。

在安全隔离的部署架构方面,以VMWare的NSX[7]为代表的商用虚拟网络解决方案中已经提出了分布式逻辑路由,以及分布式虚拟防火墙的概念。该方案采用位于物理网络边界的集中式节点处理南北向流量(租户虚拟机与外部网络的流量)、位于各物理服务器内部的分布式虚拟路由/防火墙处理东西向流量(跨物理机的虚拟机之间的流量)。

而在主流开源云平台(如Open Stack)[3]中仍然采取集中部署虚拟路由器及防火墙的方式,即专设一台服务器(或专用硬件网络设备)作为网络节点,在该网络节点上为每个租户部署虚拟路由器,并配置虚拟防火墙作用在虚拟路由器上。这种部署方式的思路就是将虚拟网络的边界集中到统一的节点,所有涉及租户网络边界的流量都被集中到网络节点上进行处理。但这样的实现方式容易引发单点故障,下一节将具体分析其中存在的问题。

1.2 集中式虚拟路由的问题

上文中图1给出了虚拟网络边界的3种场景。Open Stack允许租户分别创建各自的虚拟路由和虚拟防火墙,不同租户的虚拟路由器之间默认没有关联,无法相互访问,因此可以达到隔离多租户虚拟网络的目的,但在处理(2)、(3)两类网络边界场景时,存在不合理之处。

图2是Open Stack实现虚拟网络隔离的路由模式,其中网络节点是Open Stack专设的实现虚拟网络功能的物理服务器节点,所有租户的虚拟路由器均部署在网络节点上,虚拟防火墙的规则作用在相应虚拟路由器上,而计算节点则是部署了虚拟机管理程序(Hypervisor)及虚拟机资源的物理服务器。为便于说明问题,假设租户A创建了一套虚拟网络,配置了两个子网,子网下的虚拟机分布在不同计算节点上。

在同租户不同子网边界方面:由于云计算的一大特点是东西向流量增大,业务运行时,跨物理机的虚拟机之间经常进行通信。在现有的网络架构下,跨子网的网络通信流量都需要通过网络节点上的虚拟路由器进行转发。图2中深色箭头对应的路径是租户A不同子网下的虚拟机之间通信时的数据包路径,其中位于子网1的虚拟机VM1与位于子网2的虚拟机VM2通信,数据包经过位于网络节点的虚拟路由器和虚拟防火墙。

在租户与外网边界方面:虚拟机与外部网络之间的通信流量也需要经过网络节点,通过网络地址转换(NAT)和防火墙规则的过滤,如图2中浅色箭头所示。租户A的虚拟机数据包在通往外网的过程中经过网络节点,通过部署在虚拟路由器上的NAT规则进行IP地址转换,获取外网IP资源,同时也经过部署在虚拟路由器上的虚拟防火墙规则进行过滤,防止与外网间的非法通信。

因此,在多租户的场景下,现有的虚拟网络隔离实现模式会导致租户虚拟机的大部分流量都经过单一物理节点,对网络节点造成极大的负载压力。如果采用集中式部署的虚拟网络隔离架构,将网络节点作为实现网络功能和服务的单一节点,很容易引发单点故障问题;同时,由于租户网络隔离机制需要采用基于VXLAN的覆盖网络协议,对虚拟机网络数据包进行封装(在第2节详细介绍),虚拟机数据包在不同物理节点间的转发都会经过封装与解封装的过程。数据包统一经过网络节点处理,进一步增加了通信的网络延迟。因此现有的虚拟网络隔离架构存在引发单点故障的隐患以及网络延迟的问题,不具有高可用性和可扩展性。

虚拟网络边界相比传统网络而言更加模糊和复杂,需要更明确的网络边界节点定义以及更合理的网络边界隔离的解决方案。针对虚拟网络的高可用性问题,文献[2]采用的解决方案是关键组件集群式部署,即发生故障时可切换到集群中的备用设备,从而保证高可用。而本文则是从路由模式的角度出发,针对开源云平台中存在的问题,提出了一种分布式实现多租户虚拟网络隔离的解决方案。

2 虚拟网络隔离的分布式实现

2.1 总体架构

与当前主流云平台(如Open Stack)的虚拟网络隔离方式不同,本文提出了一种虚拟网络安全隔离的分布式实现方式,将租户虚拟路由器和防火墙分布到每个计算节点中。总体思路是把原本集中到单一物理节点的虚拟网络边界分散到各台物理服务器,从而将原本集中于同一节点的网络流量分摊到各物理服务器,降低单点故障造成损失的可能性。即使在某个节点上出现故障,也只影响这台服务器上的虚拟机通信,网络中的其他虚拟机仍可以正常通信。

图3的路由模式图给出的是同一租户的虚拟网络(包括子网和分布式虚拟路由)。本文的方案在支持多租户方面,允许每个租户创建相互独立的虚拟子网和虚拟路由器,即同一台物理服务器上可能包含多个租户创建的虚拟路由器和防火墙,利用Linux内核的网络命名空间技术解决可能存在的多租户IP地址冲突问题。此外,图中的内部数据网包括计算节点间的物理网络设备(交换机、路由器等)。

可以对比图3分布式实现的路由模式与图2中Open Stack集中式实现的路由模式。在通过分布式实现的模式中,虚拟机与外网之间的通信,直接通过其所在Hypervisor上的分布式虚拟路由器通向外网;跨子网的虚拟机之间的通信,也直接通过分布式路由进行处理。这两类流量直接由计算节点上的分布式路由处理,无需通过统一的网络边界节点。

图4是本文分布式路由的物理架构图。本文采用的虚拟交换机为Open v Switch,部署在所有物理服务器上,其中虚拟交换机br-int连接Hypervisor上的所有虚拟机。而虚拟交换机br-tun作为处理VXLAN协议的端点VTEP(VXLAN-Tunnel-End Point),对虚拟机出物理服务器的流量进行VXLAN封装,通过数据网网卡转发;对于接收到的VXLAN数据包,则进行解封装处理,转发给连接虚拟机的br-int处理。此外,虚拟交换机br-ex的作用是连接外网网卡,能够处理虚拟机与外网之间的通信。

虚拟路由器利用网络命名空间技术配置,主要由子网网关端口构成,这些子网网关端口可在虚拟交换机上配置对应端口,起到连接虚拟交换机和虚拟路由器的作用。本文部署虚拟路由器的模式是:根据租户虚拟机的分布,在所有包含该租户虚拟机的物理机上为配置分布式虚拟路由器,这些分布式虚拟路由器包含租户下所有子网的网关端口。

为便于说明,设定以下场景:租户A的虚拟网络包含两个子网(子网1和2),虚拟机分布在两个计算节点上,图4中VMx-y代表计算节点x上属于子网y的虚拟机,两个计算节点各包含两台虚拟机,分别属于租户A的子网1和子网2。两个计算节点的分布式虚拟路由器上均配置了子网1和子网2的网关。

下一节将结合三类虚拟网络边界场景,具体描述分布式虚拟网络隔离的部署模式,并分析对比分布式路由与集中式路由的路由模式。

2.2 虚拟网络安全隔离分析

引言中已经结合实际应用场景,将虚拟网络的边界分为三类,图1列举了这三类网络边界。本文的分布式虚拟网络隔离充分考虑了这三类虚拟网络边界,并有针对性地采用了相应的网络虚拟化技术。本节分别分析本文的分布式实现方案在这三类边界场景下的实际流程和相关技术。

2.2.1 多租户网络之间的边界

网络虚拟化技术使得云服务提供商能够将一套物理网络虚拟化成多套虚拟网络,分别提供给不同的租户。从租户的角度考虑,一个重要的需求就是确保租户网络的安全隔离盒独立性,防止自己的数据遭到来自其他租户的非法访问。

Open Stack现有的实现方式能够很好地支持多租户网络安全隔离,因此本文在隔离多租户虚拟网络方面基本沿用了Open Stack的思路,并将集中式路由改为分布式。在实际部署上,将原先集中部署在网络节点的租户虚拟路由器和防火墙分布到租户虚拟机所在的计算节点上,即所有包含租户A的虚拟机的物理服务器上都部署属于租户A的虚拟路由器和虚拟防火墙。

同一计算节点上可能包含多位租户所创建的虚拟路由器,连接各自的虚拟子网与外网。由于这些虚拟路由器之间默认没有关联,未配置相关联的路由规则,因此租户之间的虚拟网络无法相互访问通信,从而达到不同租户虚拟网络边界安全隔离的目的。

此外,考虑到多租户虚拟网络中,不同租户可能采用相同的内部IP地址资源,从而引起系统中路由、NAT及防火墙规则配置的冲突,因此需要使用Linux的网络命名空间技术。该技术允许在操作系统中定义多个虚拟空间,每个空间可相互独立、透明地进行网络操作,从而能很好地支持多租户虚拟网络的需求。同一物理服务器中多租户虚拟路由器的创建和管理配置正是基于网络命名空间技术实现的。

2.2.2 同租户不同子网之间的边界

传统网络中常使用VLAN技术对网络进行逻辑上的划分,但随着数据中心网络规模以及虚拟机数量的飞速增长,VLAN暴露出一些问题。近年来,VXLAN[8]协议应运而生,能够解决以下几方面的问题:

VLAN规模限制

当前的VLAN协议中,使用12位数据作为VLAN标签,最多支持4094个子网。随着数据中心规模的扩大以及租户虚拟网络增多,这一数量不足以提供必要的传播的独立性。而在VXLAN中,引入了VNI(虚拟网络标识符)的概念,从12位扩展到了24位,支持超过1600万个子网。

多租户支持

数据中心托管多个租户,而每个租户需要流量隔离。这种隔离处于第二层,正如VLAN所提供的。在三层网络的情况下,有可能有两个租户使用相同的三层寻址方案,需要以不同的方式提供隔离。VXLAN可以在现有的基础设施上运行,使用VNI封装虚拟机的数据包,建立VXLAN隧道,区分不同的虚拟子网。

交换机的虚拟机数量

在大二层网络环境下,数据流需要通过明确的网络寻址以保证准确到达目的地,因此网络设备的MAC地址表项大小,成为决定云计算环境下虚拟机的规模的上限的因素,限制了整个云计算数据中心的虚拟机数量。而通过VXLAN将虚拟机数据封装在UDP数据包中后,对网络只表现为封装后的网络参数,即VXLAN隧道端点(VTEP)的地址,因此,对于承载网络(特别是接入交换机)的MAC地址规格需求极大降低。

在本文方案中采用基于VXLAN协议的覆盖网络技术,在不同计算节点之间建立VXLAN隧道,对虚拟机之间通信的数据包进行封装,并通过VNI划分不同虚拟子网。

同租户跨子网的虚拟机之间的通信,根据虚拟机的位置分布,可以细分为同一物理机和跨物理机两种情况。在原有的集中式路由模式下,同一租户下跨子网的虚拟机之间的通信都需要经过网络节点上的虚拟路由处理。即使两台在同一物理机上的虚拟机之间通信,由于不处于同一子网,也没有本地的路由关联,因此必须先发送到网络节点。这样的步骤是十分繁琐的,不仅增加了通信中的网络延迟,也带来了引发单点故障的隐患。

通过图5说明本文的分布式路由如何处理同租户跨子网的东西向流量。

这里以不同物理机上跨子网虚拟机通信为例,即图5中VM1-1与VM2-2之间的通信。两台虚拟机分别属于子网1和子网2。

在原先的集中式路由模式下,VM1-1发出的数据包在本地没有匹配到路由规则,需要转发到网络节点上的虚拟路由进行处理,具体步骤如下:

1)VM1-1发出数据包,目的地址为VM2-2;

2)计算节点1的虚拟交换机br-int收到数据包,加上子网1的内部VLAN标签后转发到VTEP(br-tun);

3)计算节点1的br-tun将内部VLAN标签转换为子网1对应的VXLAN标识VNI,并从数据网卡通过VXLAN隧道把数据包转发到网络节点;

4)网络节点的VTEP(br-tun)对数据包进行解封装处理,将子网1的VXLAN标识转换为内部VLAN标签,并转发到虚拟交换机br-int;

5)网络节点的br-int把数据包交到虚拟路由处理,因为目的地址属于子网2,根据路由规则,数据包通过子网2网关端口转发,回到br-int;

6)网络节点的br-int把数据包加上子网2的内部VLAN标签,转发到br-tun;

7)网络节点的br-tun将内部VLAN标签转换为子网2对应的VXLAN标识VNI,并通过VXLAN隧道把数据包转发到计算节点2;

8)计算节点2的VTEP(br-tun)对数据包进行解封装处理,将子网2的VXLAN标识转换为内部VLAN标签,并转发到虚拟交换机br-int;

9)计算节点2的br-int将数据包转发到VM2-2对应端口,VM2-2接收到数据包。

可见这是一个复杂的过程,而本文在建立分布式路由后,可将跨子网虚拟机通信简化为以下步骤(与图5中的序号对应):

1)VM1-1发出数据包,目的IP地址为VM2-2;

2)计算节点1的虚拟交换机br-int收到数据包,把数据包交到分布式虚拟路由器处理,根据路由规则,将目的地址为VM2-2的数据包通过子网2网关端口转发,回到br-int;

3)计算节点1的br-int把数据包加上子网2的内部VLAN标签,转发到VTEP(br-tun);

4)计算节点1的br-tun将内部VLAN标签转换为子网2对应的VXLAN标识VNI,从数据网卡通过VXLAN隧道把数据包转发到计算节点2;

5)计算节点2的br-tun对数据包进行解封装处理,将子网2的VXLAN标识转换为内部VLAN标签,并转发到虚拟交换机br-int;

6)计算节点2的br-int将数据包转发到VM2-2对应端口,VM2-2接收到数据包。

以上通信步骤直接在计算节点间进行,无需经过网络节点处理。

在实际应用场景中,同一租户的不同虚拟机之间也存在访问控制的需求,要通过配置虚拟防火墙的方式实现。与分布式虚拟路由类似,本文的虚拟防火墙同样将原有集中式部署改为分布式部署,防火墙规则通过iptables的形式作用在分布式虚拟路由器对应的网络命名空间中。

2.2.3 租户网络与外网之间的边界

这里以虚拟机VM1-1与外部网络的通信为例,对比集中式路由与分布式路由。子网1的网关记为GW1,虚拟路由器上的外网网关记为EG1。

Open Stack原有的实现方式需要通过网络节点上的虚拟路由器,具体步骤如下:

1)VM1-1发出数据包,目的地址为外网的IP地址;

2)计算节点1的虚拟交换机br-int收到数据包,加上子网1的内部VLAN标签后转发到VTEP(br-tun);

3)计算节点1的br-tun将内部VLAN标签转换为子网1对应的VXLAN标识VNI,并从数据网卡通过VXLAN隧道把数据包转发到网络节点;

4)网络节点的VTEP(br-tun)对数据包进行解封装处理,将子网1的VXLAN标识转换为内部VLAN标签,并转发到虚拟交换机br-int;

5)网络节点的br-int把数据包交到虚拟路由处理,因为目的地址属于外部网络,使用NAT规则把数据包源地址改为外网网关端口EG1的地址;并根据路由规则,从EG1转发到外网虚拟交换机(br-ex)上;

6)网络节点的br-ex通过外网网卡把数据包发送到外网。

与Open Stack原有的方式相比,本文的分布式路由模式在处理虚拟机与外网之间的通信时更为直接。

如图6所示,在计算节点上设置了租户分布式路由器,并配置了外网网卡。虚拟机与外网间的通信不再像原先那样必须通过网络节点,而是通过宿主机上的分布式虚拟路由,从外网网卡直接访问外网。

下面是虚拟机VM1-1访问外网的过程(与图6中的序号对应):

1)VM1-1发出数据包,目的地址为外网的IP地址;

2)虚拟交换机br-int收到数据包,把数据包交到分布式虚拟路由器处理,在租户虚拟路由的网络命名空间中,配置了基于iptables的NAT规则,将数据包源地址从VM1-1的私有IP地址转换到外网网关EG1的IP地址,如:

iptables-A POSTROUTING-s 192.168.30.0/24-j SNAT-tosource 10.10.88.51

即数据包源地址转换为外部IP(如10.10.88.51);

3)根据虚拟路由的默认规则,确定数据包从外网网关EG1转发到外网虚拟交换机(br-ex)上;

4)网络节点的br-ex通过外网网卡把数据包发送到外网。

作为隔离过滤外部非法访问的重要手段,本文的虚拟防火墙基于iptables规则配置,与上面的NAT一样,把规则作用在虚拟路由器所在的Linux网络命名空间中。

3 部署与实验

3.1 实验环境

本文的实验环境部署在4台物理服务器上,搭建了基于Open Stack Juno版本的环境。Dell服务器的操作系统为Cent OS7,多网卡,其中控制节点使用单网卡(管理网),计算节点和网络节点使用三网卡(管理网、数据网、外网),管理网网段10.10.82.0/24,数据网网段10.10.87.0/24,外网网段10.10.88.0/24。

根据本文的分布式实现虚拟网络隔离方式,在这套实验环境中通过租户admin创建了一套基于本文分布式架构的虚拟网络,包括两个子网和4台虚拟机,虚拟机的详细信息(所在物理机、所在子网)见表1所示。

租户admin的两个子网IP端分别为192.168.30.0/24和192.168.40.0/24,对应VXLAN标识分别为5和7,两个计算节点上都有两台属于两个不同子网的虚拟机。

根据图4的物理架构,本文的实验环境运用Linux的网络命名空间技术,在两个计算节点上都创建租户admin的分布式虚拟路由器和防火墙,这两个虚拟路由器在配置上是相同的,端口包含两个子网的网关(IP地址分别为192.168.30.1和192.168.40.1),以及外网网关(IP地址10.10.88.51)。

同样,通过租户admin利用Open Stack原有的方式也创建一套类似的虚拟网络,在配置与虚拟机分布方面与表1相同,便于实验对照。

3.2 网络延迟对比

在本文第2节中,已经通过对比集中式虚拟网络隔离与分布式虚拟网络隔离,分析了分布式架构可以避免虚拟机流量集中到单一网络节点,降低单点故障的可能性;也从理论上分析了本文分布式虚拟网络隔离方案在路由步骤上更加简洁,可以减少跨子网虚拟机通信的网络延迟。本节将给出实验环境中的对比,分析Open Stack原有集中式路由与本文分布式路由在几种不同场景下的网络延迟对比。

根据上文的分析,集中式路由在处理同租户不同子网之间的边界、以及租户虚拟网络与外网边界时存在不合理之处,即租户虚拟机跨子网通信和虚拟机与外网通信这两种情况。其中租户虚拟机跨子网的通信还可以根据虚拟机在计算节点的分布,细分为同一物理机和跨物理机两种。

表1中的虚拟机VM1与VM2位于计算节点1(compute1),分别属于30和40网段,它们之间的通信属于跨子网同物理机情况;VM1与VM4分别位于计算节点1(compute1)和计算节点2(compute2),分别属于30和40网段,它们之间的通信属于跨子网跨物理机情况;而VM1与外网的通信则属于虚拟机与外网通信,本文以虚拟机访问www.fudan.edu.cn为例。

图7是本文针对三类不同场景的网络延迟实验结果对比图。柱状图中白色表示Open Stack原有方式下的网络延迟,阴影部分表示本文采用的分布式架构下的网络延迟。可以看到在三类不同场景中,分布式路由模式能有效降低虚拟机的网络延迟。

在以上三类场景中,分布式比集中式的虚拟机网络延迟低的原因是,相比Open Stack原有的集中式虚拟网络路由模式,本文的方式更为直接。不论是虚拟机跨子网通信,还是虚拟机与外网通信,数据包无需专门经过网络节点进行处理,而是直接由所在宿主机上的虚拟路由处理,从而简化了虚拟机数据包在网络中的路由步骤和流程,降低网络延迟。

实验证明,在分布式虚拟网络隔离模式下,虚拟机的数据包直接由宿主机上的分布式虚拟路由器进行处理,减少了虚拟机通信的网络延迟,从而提高虚拟网络中的效率。另一方面,避免虚拟机流量集中到同一个节点,也降低了单点故障的风险。

4 结语

当前主流开源云平台(如Open Stack)中,虚拟网络隔离采用集中式部署虚拟路由器/防火墙的方式实现,存在单点故障的隐患。本文采用分布式实现虚拟网络隔离的方式,将原先集中部署在单一节点的虚拟路由器/防火墙分布到各计算节点,从而将虚拟机通信流量直接交给宿主机上的分布式虚拟路由器处理,降低发生单点故障影响整个网络通信的可能性。即使在某个物理节点上出现故障,也只影响这台服务器上的虚拟机通信,网络中的其他虚拟机不受影响,仍可以正常通信。实验验证了本文分布式部署架构的有效性,并根据集中式路由与分布式路由的虚拟机网络延迟对比,证实本文的分布式路由可以简化虚拟机的通信流程,降低网络延迟。

本文的部署模型将租户虚拟路由器/防火墙部署在所有相关计算节点上,属于一种静态部署的方式,而云网络中虚拟机迁移与变更时常发生,虚拟路由和防火墙也面临相应的变更。下一步的研究计划是动态确定虚拟网络边界节点的位置,将分布式路由/防火墙部署到相应边界节点(即部分计算节点上),从而降低虚拟机迁移造成的影响,提高分布式配置的效率。

参考文献

[1]Jain R,Paul S.Network virtualization and software defined networking for cloud computing:a survey[J].Communications Magazine,IEEE,2013,51(11):24-31.

[2]Koponen T,Amidon K,Balland P,et al.Network virtualization in multi-tenant datacenters[C]//USENIX NSDI.2014.

[3]Open Stack[EB/OL].[2015].http://docs.openstack.org.

[4]Hwang J,Ramakrishnan K K,Wood T.Net VM:high performance and flexible networking using virtualization on commodity platforms[C]//11th USENIX Symposium on Networked Systems Design and Implementation(NSDI 14).Seattle,WA:USENIX Association.2014:445-458.

[5]Martins J,Ahmed M,Raiciu C,et al.Click OS and the art of network function virtualization[C]//Proc.USENIX NSDI.2014:459-473.

[6]Gember A,Grandl R,Anand A,et al.Stratos:Virtual middleboxes as first-class entities[J].UW-Madison TR1771,2012.

[7]VMware NSX Network Virtualization Design Guide[EB/OL].[2015].http://www.vmware.com/files/pdf/products/nsx/vmw-nsxnetwork-virtualization-design-guide.pdf.

[8]Mahalingam M,Dutt D,Duda K,et al.Virtual extensible local area network(VXLAN):A framework for overlaying virtualized layer 2 networks over layer 3 networks[J].Internet Req.Comments,2014.

[9]Open v Switch[EB/OL].[2015].http://openvswitch.org.

[10]Mudigonda J,Yalagandula P,Mogul J,et al.Net Lord:a scalable multi-tenant network architecture for virtualized datacenters.[J].Acm Sigcomm Computer Communication Review,2011,41(4):62-73.

上一篇:上海高技术产业下一篇:程序对象