在接下来的两章中,我将分别为大家介绍与分析三款软件定义存储解决方案:CoprHD、Ceph与ScaleIO,并对后两者进行性能比较分析。
一、开源的软件定义存储—CoprHD
了解开源的CoprHD(CoprHD),需要先了解EMC ViPR。
ViPR是一款商用的、纯软件的软件定义存储解决方案,可将已有的存储环境转换为一个提供全自动存储服务的,简单易扩展的开放性平台,用来帮助用户实现全方位的软件定义数据中心。ViPR将物理存储阵列(不论是基于文件、块,还是对象的)抽象成一个虚拟的存储资源池, 以提供跨阵列的弹性存储或基于此的应用及服务。由于抽象了对底层硬件阵列的管理,所以它可将多种不同的存储设施统一集中起来管理。
存储设施一般对外提供控制路径(Control Path)及数据路径(Data Path)。简单来说,控制路径是用来管理存储设备相关的策略,数据路径则完成用户实际的读写操作。与以往只将控制路径和数据路径解耦的存储虚拟化解决方案不同,ViPR还将存储的控制路径抽象化,形成一个虚拟管理层,使得对具体存储设备的管理变成对虚拟层的操作。基于此用户可将他们的物理存储资源转化成各种形式的虚拟存储阵列,从而可以将对物理存储资源的管理变成基于策略的统一管理。控制路径和数据路径的解耦使得ViPR可以把数据管理相关的任务集中起来统一处理,而不影响原有的对文件或块的读写操作。CoprHD则是ViPR的存储路径的开源版本。在Github主页上CoprHD这样定义自己:开源软件定义存储控制器及API平台,支持基于策略的异构(块、文件与对象)存储管理、自动化。
ViPR/CoprHD提供基于块和文件的虚拟控制服务。构建在物理存储阵列上的块和文件的控制服务,包含对块卷的、NFS文件系统、CIFS共享的管理,以及一些高级数据保护服务,比如镜像、快照、克隆、复制。不同于那些公有云中虚拟计算资源,为了降低成本和简化操作,直接使用商用磁盘,从而丢失了一些上述的高级阵列特性(镜像、快照、克隆、复制)。
ViPR/CoprHD提供的块和文件的控制服务包含上述所有的在物理阵列上所见的管理功能。
(1)CoprHD架构概要
CoprHD 是构建存储云的软件平台,它的主要设计目标是来解决两大问题:
· 使一个配备了各种存储设备(块阵列、文件服务器、SAN和NAS交换机)的企业或服务提供商的数据中心看起来像是一个虚拟存储阵列,同时隐藏其内部结构和复杂性。
· 让用户拥有对虚拟存储阵列完全控制的能力,包括从简单的操作(例如卷的创建)到相当复杂的操作(如创建在不同的数据中心灾难恢复保护的卷)。这种能力的一个关键原则是通过多用户、多租户的方式来提供租户隔离、访问控制、审计、监控等功能。
CoprHD以一种厂商无关的、可扩展的方式实现这些目标,支持不同供应商的多种存储设备。CoprHD架构示意图如下图所示。
CoprHD持有在数据中心中的所有存储设备的清单,了解它们的连接性,并允许存储管理员将这些资源转化为如下虚拟设备。
· 虚拟池(Virtual Pools):可以针对虚拟池设置具体的性能和数据保护特性等。
·虚拟阵列(Virtual Arrays):把数据中心的基础措施按照容错能力、网络隔离、租客隔离等策略来分门别类。
图:CoprHD架构示意图
存储管理员可以完全控制哪些用户或租户可以访问这些虚拟池和虚拟阵列。最终用户使用一个统一的和直观的API来以一个完全自动化的方式通过虚拟池或虚拟阵列提供块卷或文件共享。CoprHD会自动完成所有隐藏的基建任务,如为卷寻找最佳位置或必要的SAN架构配置。ViPR不仅仅提供卷的创建,它还有能力执行复杂的业务流程,包含端到端的编排流程的能力、卷的创建、SAN配置、为主机绑定新创建的卷等。
从构架的角度来看,CoprHD是一个存储云的操作系统,具有如下特点:
·它提供了一整套结构良好的、直观的“系统调用”,以REST API的形式进行存储配置。
·它是一个多用户、多租户系统。正因为如此,它强制访问控制(认证、授权和分离)。
·“系统调用”具有事务性语义:从用户角度出发它们是原子的。当一个操作中的任何一个步骤出错,它们要么重试失败的操作或者回滚部分完成的工作。
·它是高并发的,允许多个“系统调用”并行执行,但是在内部执行细粒度同步以确保内部一致性。 ·它实现了自己的分布式、冗余和容错数据仓库(Data Store)来存储和管理所有配置数据。 · 它允许通用业务逻辑通过使用一组“驱动程序”来与存储设备交互并保持设备中立(Device Agnostic)。
(2)CoprHD集群
为了提供高可用性,CoprHD采用了双活(Active-Active)的集群架构设计方案,由3~5个同构、同配置的节点形成一个集群。
CoprHD集群节点间不共享任何资源,在典型的部署中,通常每个节点都是台虚拟机。如下图所示,每个节点上运行同样的一整套服务:身份验证、API、控制器异步操作、自动化、系统管理、WebUI、集群协作及列数据库服务等。
图:CoprHD 集群(3节点)示意图
CoprHD基础架构层是建立在Cassandra和Zookeeper之上的无中心分布式系统,因而具有容错性、高可用性和高可扩展性等特点。CoprHD采用了Cassandra和Zookeeper的如下的特性:
·Quorum读与写:分布式系统中,为保证分布式时间或交易操作的一致性而采用的投票通过机制被称为Quorum。如果集群中大于半数的节点在线(例如:5个节点的cluster中有3个节点在线),则整个Cassandra和Zookeeper就可以正常提供读写服务(意味着整个CoprHD系统可以允许少数节点宕机)。
·Cassandra和Zookeeper的数据副本保存在所有的节点上,每个节点都包含最终一致的CoprHD数据。 · 定期的数据修复来确保整个集群的可靠性。
CoprHD还在Cassandra和Zookeeper服务之上抽象并封装了DbClient和CoordinatorClient API,因而上层无需了解底层的如数据容错性、一致性和可用性等细节。
每个节点都在一个共同的子网中分配一个IP地址。此外CoprHD群集使用一个虚拟IP地址(VIP),外部客户通过它可以访问CoprHD REST API和CoprHD GUI。我们使用keepalived守护进程[这反过来又利用VRRP(Virtual Router Redundancy Protocol)协议],以保证在任何时间点恰好一个CoprHD节点处理网络流量给VIP。该keepalived守护进程还监视每个节点上的nginx服务器的“实时性”。nginx的作用是双重的。
·作为一个反向代理。nginx的服务器听到HTTPS端口443的请求,并根据请求的URL中的路径,将请求转发到相应的CoprHD Web服务。
·也作为嵌入负载平衡器。nginx的服务器将请求转发到本地节点或者其他节点上(目标节点的选择是通过散列请求的源IP地址)。因此,即使只有一个的nginx服务器处理,所有节点也都会参与请求处理。
同样,nginx的服务器侦听端口443,并把GUI会话分发给所有节点上可用的portalsvc实例(见下图)。
图:CoprHD 集群网络拓扑
(3)后端持久层
大多数的CoprHD服务是无状态的,它们不保存任何状态数据。除了系统和服务日志,所有CoprHD数据都是被存储在coordinatorsvc或dbsvc的(见下图)。这两种服务保证数据在每个节点上都有完整副本。
图:CoprHD 集群如何实现数据持久性
在CoprHD集群里,coordinatorsvc应被看作是一种强一致性的,为集群服务之间的协调操作而保存少量数据的存储器。例如,服务定位器、分布式锁、分布式队列等服务。coordinatorsvc在内部使用Apache Zookeeper。其他CoprHD服务使用coordinator客户端库来访问coordinatorsvc的数据。该coordinatorclient是Netflix Curator(一个流行的Zookeeper客户端)的封装,coordinatorclient库抽象出Zookeeper的所有的配置细节和分布式特性。
dbsvc是基于列的数据库。它提供了良好的可扩展性,高插入率和索引,但只能提供最终一致性(即无法保证分布式数据的实时一致性)。在内部,dbsvc是围绕Apache的Cassandra的封装。但是,为了防止临时不一致的地方,我们需要基于一个多数节点共识机制(Quorum)来保证无论是读取还是写入dbsvc的数据一致性。因此,2N + 1个节点的群集只能承受多至N个节点故障(低于N个在线节点,则Quorum投票机制不能正常工作)。其他服务使用dbclient库访问dbsvc。dbclient是一个Netflix的Astynax的封装,一个Cassandra客户端。类似于coordinatorclient,它抽离出Cassandra的复杂的分布式特性。此外,dbsvc还依赖于coordinatorsvc。
(4)CoprHD端到端如何工作
为了更好地了解CoprHD的工作原理,我们在这里通过三个简单的REST调用来帮助理解。REST调用既可以是同步的也可以是异步的,前者是实时返回,后者则通常是产生一个外部调用(返回一个指向外部任务的URN,而调用者必须poll该外部任务以获得运行结果)。
下图展示的是同步调用“GET/login”的流程。CoprHD是个多用户、多租户系统,因此大多数REST调用需要身份与权限认证token或cookie,而获得这些token或cookie依赖于外部的LDAP服务器或AD(Active Directory)。“Get/login”调用分为以下5步:
图CoprHD 同步REST调用“GET/login”
(1)发送GET请求到https://<vip>:443/login,该请求由节点2上的nginx来处理。
(2)该/login请求会被authsvc服务处理,假设客户的IP地址的哈希运算(用于负载均衡)对应节点1,则节点2的nginx会把该请求转发给节点1。
(3)authsvc会把用户信息发给外部的AD服务器。如果认证通过,则AD返回信息会包含用户的租户信息。
(4)authsvc会生成认证token,并通过dbsvc服务来存储该token及用户租户信息。
(5)最后,节点1上的authsvc会向节点2的nginx返回认证token,nginx会最终返回给用户。
在第二个例子中,我们通过异步REST调用来完成“POST /block/volumes”写操作。总共有7步操作(见下图)。
(1)发送POST请求给https://<vip>:443/block/volumes,该请求被节点2上的nginx接收(我们假设节点2对应请求中的vip)。
(2)该nginx服务器把请求转发给节点1上的apisvc。
(3)apisvc会先从该请求的header中提取认证token,并从dbsvc中获得用户信息,该信息被用来决定卷的最终放置(volume placement)。
(4)apisvc会分析请求中的信息来决定需要创建的物理卷的数量以及最优的创建策略。apisvc还会为每个卷在dbsvc(Cassandra)中创建descriptor。
(5)因为物理卷的创建是个非实时的工作,因此通常该操作通过controllersvc来异步完成。为了完成该操作apisvc会在coordinatorsvc(Zookeeper)中创建一个异步任务对象,并在存储控制队列中(coordinatorsvc)注册该操作。
(6)apisvc向外部客户端返回task identifier。而客户端可以通过该identifier来查询运行结果。
(7)在本例中,节点3的controllersvc收到了队列中的请求并负责编排卷的创建,以及在dbsvc中更新卷的descriptors。
图:CoprHD 异步REST调用“POST /block/volumes”
最后,我们来看看如何通过CoprHD的Web界面监控上面例子中的卷创建过程与结果。总共分为6小步(见下图)。
(1)浏览器指向https://<vip>/。
(2)假设节点2上的nginx服务会把该请求转发给节点1上的portalsvc服务。
(3)portalsvc会调用:https://<vip>:4443/block/volumes/<task ID>。
(4)节点2上的nginx把该调用转发给apisvc服务。
(5)apisvc通过认证cookie来获得用户与租户信息。
(6)最后,apisvc将获得任务状态并发送给portalsvc,而portalsvc会生成一个网页并最终发送给用户浏览器。
图:CoprHD访问UI来查看卷创建状态
[注]
CoprHD由EMC在2015年贡献给开源社区,不过其生命力似乎并不持久,在2016年发布过v3.0后就再也没有新的大版本的正式发布。这其中有几方面原因:一是,EMC作为一家成功的商业化公司,开源并不是其工作重点;二是 2015年底Dell收购了EMC,显然,所有的业务都会受到调整,之前负责开源initiative的团队出现了人员变动,核心人员不在的系统是很难持久发展的;三是像Linux这么成功的项目,到目前不也就一个吗?不都是靠着Linus独木苦撑,没有Linux,可能Linux OS已经早就挂掉了,C'est La Vie.