GlusterFS对象存储服务

1041

(作者:郭忠秋)

1.  引言

Gluster是一款免费的开源分布式文件系统,具有很多优点,如无中心架构、用户空间堆栈式设计、全局统一命名空间、高可用、高性能、弹性横向扩展和管理简便等等,在业界被广泛地使用。Gluster是一种兼容POSIX标准的文件系统,除了其私有的客户端访问方式外,它同时还支持工业标准的文件访问协议NFS和SMB。

然而就存储访问接口类型而言,Gluster系统本身只提供了文件访问接口,而另一个业界比较流行的免费开源存储系统Ceph,则同时支持文件、块和对象存储访问接口。在这一点上,可以说Gluster是处于劣势的。

另一方面,对象存储(Object-based Storage)近几年来比较流行,它代表了一种更简单、更可扩展的存储解决方案,通过标准的基于网络的协议可以轻松访问。对象存储没有传统文件系统的目录层次结构,而是采用一种扁平化的数据组织方式,被认为是一种支持海量用户远程访问的无限可扩展的廉价存储系统。除了国外的Amazon S3、OpenStack Swift、SwiftStack等之外,国内的BAT、华为、七牛、青云等公司也提供对象存储服务。

如果Gluster能够在其已有的良好文件存储能力基础上,同时支持对象存储访问接口,那么Gluster在业界的竞争力将会得到进一步的提升,从而可能被更多的用户所采用。幸运的是,这样的方案已经存在了,gluster-swift就是这样的一个开源项目,一个将Gluster与OpenStack Swift相结合的方案。本文主要也是讨论该方案,首先简要介绍了Swift背景、架构与原理(熟悉Swift的读者可以略过该内容),然后为读者介绍Gluster对象存储的技术实现、工作原理以及使用与测试方法,希望能抛砖引玉,至于更多的技术细节,感兴趣的读者可以网上搜索相关内容。

2.  OpenStack Swift

2010年,美国RackSpace公司将其开发的高可用分布式对象存储服务Swift,贡献给了OpenStack开源社区,作为当时OpenStack的两个核心子项目之一(另一个是美国国家航空航天局NASA提供的计算服务Nova),为其虚拟机提供永久存储服务。到目前为止,OpenStack已经拥有40多个子项目,与存储相关的项目有:对象存储Swift、块存储Cinder和文件存储Manila。

作为对象存储的一种,Swift构建在廉价的标准硬件设施之上,通过一致性哈希和数据冗余等软件技术,在舍弃一定程度的数据一致性情况下,来提供高可用性和良好扩展性,适合解决互联网应用场景下的非结构化数据存储问题,尤其适合存储永久性的静态数据,也就是需要长期保存并更新频率比较低的数据,例如,虚拟机镜像、多媒体数据和备份数据等。

2.1.    系统架构

Swift对象存储系统的总体架构可分为访问层(Access Tier)和存储层(Storage Nodes)两个部分,如下图所示:

图1.png

图1 Swift架构

 

访问层(Access Tier)

主要包括proxy node、authentication以及可选的load balancer组件,其中proxy node负责客户端RESTful请求的处理,authentication负责用户身份认证的处理,load balancer则将客户端请求按照预定策略分配到proxy node,起到负载均衡的作用。

 

存储层(Storage Nodes)

主要包括一系列的存储节点,每个存储节点上由Account server、Container server、Object server和数据一致性组件(包括replicator、updater和auditor等服务)构成。其中account server负责处理account相关操作的REST请求,container server负责处理container相关操作的REST请求,object server负责处理object相关操作的REST请求,数据一致性组件则用于保证存储数据的高可用性与一致性。

 

2.2.    工作原理

2.2.1.      数据组织模型

在Swift的每个存储节点上,采用了三层的逻辑层次结构来组织数据,即Account、Container、Object(账户/容器/对象),每一层的节点数都没有限制,可任意扩展。

如果将三层的结构表示为树状形式,则Account在对象的存储过程中用于顶层的隔离,代表的含义是租户而不是个人账户,可以把这里的租户理解为一个组织,这个组织里可以有多个个人账户,也就是说一个Account可被多个个人账户共同使用;Container则用于对象之间的隔离,类似目录或文件夹,但不能像在文件系统中嵌套使用;Object作为叶子节点,也就是Swift存储的基本单元——对象,由内容和元数据两部分组成,类似于文件系统中的文件。如下图所示:

图2.png

图2 Swift数据组织模型

2.2.2.      一致性哈希

考虑到对象存储可能面临海量数据存储的情况,Swift采用一致性哈希技术来定位一个对象的物理存储位置。普通哈希算法也可以用于定位对象,但相比于普通哈希算法,一致性哈希的优势在于增减存储节点时,可以极大地减少需要迁移的数据量,而普通哈希算法在节点发生变动时,一般会导致对象与存储节点之间的映射关系发生改变,如果系统中有大量的数据,则迁移工作将带来巨大代价。

对于一致性哈希的过程,简言之就是计算对象名称的哈希值并将其均匀地分布到一个2的N(如32)次幂的虚拟空间的节点上。如下图所示:

图3.png

图3 一致性哈希

然后Swift通过一个独特的数据结构Ring(下文会介绍),再将虚拟空间的节点映射到具体的物理存储设备上。

2.2.3.      Ring数据结构

Swift中的Ring(环)是基于一致性哈希算法构造的环,目的就是将虚拟节点映射到一组物理设备上,并提供一定的冗余度。Ring以文件的形式保存在所有proxy server节点上,Account、Container和Object三种服务分别拥有各自的Ring。当一个请求需要对Account、Container或Object执行操作时,proxy server要先查询对应的Ring,来决定要操作实体的具体存储位置。

Ring主要包括如下信息:

1)设备表:表中的每一项都对应一个物理设备,记录了该设备的具体位置信息,包括设备ID、所在region、zone、IP地址、端口号和权重等。

2)设备查询表:存储partition(分区)的各个副本(默认3个)与具体设备的映射信息,通过该表可以找到设备表中设备ID。为了减少存储节点增减带来的数据迁移量,Swift在对象和存储节点物理设备的映射之间增加了这个partition概念,partition数量一旦确定,在整个运行过程不会变。

3)partition的移位值:表示在计算哈希值之后将object名字二进制位移的位数。

用简单的示意图表示Ring的作用如下:

图4.png

图4 Ring将partition映射到物理设备示意图

Swift提供了一个命令行工具swift-ring-builder,用于构建Ring,大致分为三个步骤:

(1)创建Ring文件,(2)添加设备到Ring中,(3)分配partition。这三步分别使用了swift-ring-builder的create、add和rebalance子命令,具体操作不做介绍,请查阅相关资料。

总之,Swift引入Ring来实现对物理节点的管理,包括记录对象与其物理存储位置之间的映射,物理节点的增加和减少等。

2.2.4.      数据一致性

根据著名的CAP(consistency,availability,partition tolerance)理论,分布式系统不能同时满足3个方面,Swift放弃了强一致性,也就是CAP中的C,而选用了最终一致性模型,以此换取系统的高可用性和极好的横向扩展能力。Swift使用NWR策略(也称quorum仲裁协议),作为确保数据一致性的理论依据。其中,N为数据的副本总数,W为更新一个数据时需要保证更新成功的份数,R为读取一个数据时需要读取的副本个数。NWR模型的具体解释请见参考资料。

Swift通过数据副本来提供冗余,当一个数据的不同副本之间出现不一致时,就需要一种机制来保证各个副本之间的一致性,为此,Swift中提供了三种服务进程来解决数据的一致性问题,分别是Auditor、Updater和Replicator。Auditor负责数据的审计,通过定期的扫描检查Account、Container和Object的完整性,如发现有数据损坏,则从其他节点获取一份完好的副本来替代,这个副本的复制任务则由replicator负责完成,另外replicator还负责object的实际删除工作。Updater则负责处理由于各种原因导致Account或Container更新失败的操作,Updater会定期地扫描本地节点的Container和Object数据,然后检查相应的Account和Container节点上是否有这些数据记录,若没有则推送之。

需要注意的是,只有Container和Object有对应的Updater进程,Account并不存在对应的Updater进程,但Account有reaper进程,作用与Updater进程类似。

 

2.3.    API

Swift通过proxy server对外提供基于HTTP的RESTful API,支持对Account、Container和Object进行CRUD(create,read,update,delete)等操作。Swift存储的每一个对象都是一个RESTful资源,并拥有一个唯一的URL。总结Swift API支持的操作如下表所示:

表1.png

表1 Swift API操作

 

2.4.    认证

在访问Swift服务时,需要首先通过认证服务对用户身份进行认证,认证成功后,proxy server才会真正地处理用户请求。

Swift支持内部和外部两种认证方式。一般来说,外部认证是指向Keystone(OpenStack的一个核心的身份管理服务)服务去认证,内部认证则是指通过Swift的WSGI中间件Tempauth来进行认证。当然也可以实现一个用户自己的认证系统。无论哪种方式,用户都需要先提交自己的credentials(凭证)给认证系统,认证系统返回用户一个token(访问令牌),这个token具有时效性,可以被缓存(如通过memcached),但是会过期(默认有效期是1天)。具体使用哪种认证方式,在proxy server的配置文件中设置,详见参考资料。

以Keystone方式为例,Swift的认证大致过程如下:

图5.png

图5 Swift认证过程

 

3.  Gluster对象存储

以上介绍了Swift的基本内容,这对于理解Gluster对象存储是非常有用的,因为Gluster对象存储方案就是Gluster文件存储与Swift对象存储技术的集成,在Gluster文件系统(即volume)之上,对外提供基于对象的REST访问接口。简单来说,就是将Gluster volume作为Swift的后端(backend)文件存储系统,用于管理磁盘级数据存储。该方案为用户访问Gluster系统存储的数据提供了一种新的访问方式,除了文件访问形式外,还可以以对象的方式访问。

 

3.1.    系统架构

图6.png

图6 Gluster对象存储系统架构

Proxy Server:即Swift的Proxy Server。

Account Server:即Swift的Account Server。

Container Server:即Swift的Container Server。

Object Server:即Swift的Object Server。

Load Balancer:可选组件,用作负载均衡作用。

Authentication:认证服务,用于用户身份认证。

Memcached:可选的缓存组件,用于缓存token、account和container数据。

Gluster-swift:Gluster对象存储开源软件部分,用于在Gluster和Swift之间做适配作用,即将Swift原本对物理存储设备的一些操作,转化为对Gluster volume的相应操作。

GlusterFSD:Gluster进程代表,用于充当Swift中auditor、replicator和updater角色,在Gluster对象存储中起到维护数据高可用和一致性的作用。

Gluster volume:作为Swift的底层存储,同时也和Swift中的account概念一一对应,即一个Gluster volume就认为是一个account,Gluster对象存储限定如此。

3.2.    工作原理

Gluster对象存储的数据组织模型、Ring结构和数据一致性等,可以与Swift对比着看,以便于理解。

首先,在数据组织模型方面,Gluster对象存储与Swift相同,都是三层的逻辑结构,即account、container和object。其中Gluster volume对应account,volume中的目录对应container,目录中的文件对应object。

其次,开源的Gluster-swift组件对Swift自带的Ring文件生成工具做了包装,命名为gluster-swift-gen-builders,用于生成Gluster对象存储的专用Ring文件,同样是account、container和object都有各自的Ring文件,功能上与Swift的Ring类似,不在赘述。

最后,在数据一致性方面有很大变化,Gluster对象存储中没有了Swift中的auditor、replicator和updater等一致性服务进程,而是依靠Gluster自身提供的冗余机制(副本/EC)和自修复机制,来提供数据的高可用和一致性。

3.3.    优势

提到Gluster对象存储的优势,主要应该是能够对外提供NAS与对象存储技术统一的视角、具有高可用性、良好的横向扩展能力和弹性管理。

3.4.    限制

(1)为了与网络文件访问的方式相兼容,对象名称不能以/符号开始或结尾,名称中间也不能出现连续的/符号。

(2)由于Gluster对象存储采取了account与volume一一对应的原因,所以不支持Swift中account的管理操作。

(3)Gluster对象存储的account名称不能含有下划线符号,这是认证组件相关部分不完善导致的。

3.5.    API

由于上节的限制原因,Gluster对象存储目前支持的Swift API功能列表如下所示:

表2.png

表2 Gluster对象存储的支持的Swift API

 

3.6.    配置方法

Gluster对象存储的配置方法并不是本文的重点,然而为了文章的完整性,本文简要列出基本的配置步骤如下,详细步骤见参考文档。

(1)安装Gluster软件及其依赖包,并开启Gluster服务;

(2)创建并开启Gluster volume;

(3)通过Gluster私有协议将volume挂载到本地指定目录;

(4)安装OpenStack Swift软件及其依赖包;

(5)安装gluster-swift及其依赖包,gluster-swift是一个开源社区软件项目,是实现本文Gluster对象存储方案必不可少的软件基础,gluster-swift在Gluster和Swift之间起到桥梁的作用;

(6)设置gluster-swift的相关配置文件;

(7)使用gluster-swift-gen-builders工具为volume生成Ring文件,也就是对外导出对象存储访问接口;

(8)启动Swift服务。

以上操作都没有问题的话,该volume就已经是Gluster对象存储中的一个account了,此时可以在客户端通过RESTful接口访问该volume了。

 

4.  Gluster对象存储使用与测试

上一节介绍了Gluster对象存储的理论与配置,下面将主要讨论使用与测试两方面的内容,首先介绍了使用swift标准客户端命令行和curl命令行访问Gluster对象存储方法,然后给出Gluster对象存储对Amazon S3的兼容性测试,最后给出了基于对象存储基准测试工具COSBench的测试结果。

4.1.    Swift客户端命令

实验中已经搭建好了Gluster对象存储,但没有使用负载均衡组件,而是直接通过IP地址访问,客户端命令行工具名称为swift,Gluster对象存储中的account(也即Gluster volume)名称为voltest,IP地址为192.168.1.85,默认服务端口为8080,使用的用户名为tester,密码为testing,下面给出一些操作实例,更多操作参见swift帮助手册。

4.1.1.      创建container和更新元数据信息

(1)创建container,例如新创建一个名为container07的container,并查看

411-1.png

(2)更新container元数据信息,设置container01的 Size元数据值为Large,可以起到标记作用,并查看

411-2.png

(3)更新object元数据信息,将mytestfile对象的type元数据值设置为txt,并查看

411-3.png

4.1.2.      上传object到container

(1)上传文件到container,将本地的test.txt文件上传到container07中,并查看

412-1.png

(2)分段上传大文件到container,将文件xdfs.tar.gz分段上传到container06中,每段大小为50MB,并查看

412-2.png

此时可见,分段上传会产生一个新的container,以container06为基础,多了_segments后缀,这个目录是用于存储分段文件的,可以查看该目录,如下所示:

412-3.png

4.1.3.      列出container和object

(1)列出account下的所有container,用到了swift的list子命令

413-1.png

(2)列出container下的object,list还可以接选项,类似于ls -lh命令

413-2.png

4.1.4.      显示account、container和object元数据信息

(1)显示account信息,例如voltest的元数据如下:

414-1.png

(2)显示container信息,例如container01的元数据如下:

414-2.png

(3)显示object信息,例如mytestfile的元数据如下:

414-3.png

4.1.5.      下载object

(1)从container中下载object,例如从container01中下载mytestfile

415-1.png

(2)从container中下载object,例如下载mytestfile并重命名为mynewfile

415-2.png

(3)下载account下的所有内容,使用了-a选项

415-3.png

4.1.6.      删除container下的object

(1)删除一个container,例如删除container05

416-1.png

(2)删除一个object,例如删除container02下的argv.py

416-2.png

(3)删除account下所有内容,这是一个危险操作

416-3.png

 

4.2.    Curl命令

Curl实验使用的Gluster对象存储环境与swift命令实验相同,这里只给出了上传和下载操作命令作为示例,其余操作留给读者自行探索。

(1)进行用户认证,获取访问token

42-1.png

获取到的访问token为AUTH_tkc6acfe233d3b466dbbde010c872a35d6,用于接下来的请求操作。

(2)下载文件并将其重命名,用到了GET方法,例如下载container01下的argv.py,并命名为newargv12.py

42-2.png

(3)上传文件到指定container,用到了PUT方法,例如上传本地test.c文件到container01

42-3.png

4.3.    Amazon S3功能兼容性测试

该测试采用Amazon官方的S3cmd工具模拟S3对存储桶、对象进行上传和下载等各种操作,验证Gluster对象存储对S3功能的兼容性。实验中使用的Gluster对象存储环境与swift命令实验环境类似,除了IP地址改为192.168.1.80,另一点要说明的是在Amazon S3中把Swift中的container叫做bucket(桶)。具体测试如下表所示:

表3.png

表3 S3兼容测试结果

测试步骤与截图如下:

(1)创建桶

使用S3cmd mb命令批量创建3个桶,结果显示3个桶均已创建成功

43-1.png

(2)遍历桶

使用S3cmd ls命令查询所有桶,可查询到所有在(1)中创建的bucket

43-2.png

(3)创建对象

使用s3cmd put命令将3个本地对象上传到桶,结果显示对象创建成功

43-3.png

(4)遍历对象

使用S3cmd ls命令遍历桶内对象,所有新创建的对象都能被查询到

43-4.png

(5)按前缀遍历对象

使用S3cmd ls命令查询桶内前缀为obj1的对象,所有前缀为obj1的对象都能被查询到,如果是查询前缀为obj的对象,则前面创建的3个对象都能查到

43-5.png

(6)获取对象属性

使用S3cmd info命令查询桶内对象,结果显示对象的所有属性均能被查询到

43-7.png

43-8.png

(7)下载对象

使用s3cmd get命令批量从容器下载对象,结果显示所有对象均能被下载到本地

43-9.png

(8)删除对象

使用s3cmd del将对象obj3m从桶bucket1中删除,结果显示操作成功,然后使用s3cmd ls查询桶bucket1,结果显示对象已经被删除

43-10.png

(9)删除桶

使用s3cmd rb命令删除桶bucket2,结果显示bucket2已被删除,然后使用s3cmd ls查询系统内桶,bucket2不在显示列表中,证明bucket2成功被删除

43-11.png

4.4.    COSBench基准测试

COSBench是一款Intel公司开发的开源的对象存储性能基准测试软件,目前支持OpenStack Swift、Amazon S3、Ceph等对象存储的性能测试。如下给出了一个简单物理环境下的测试结果,仅供参考。

4.4.1.      硬件环境

硬件环境.png

4.4.2.      软件环境

软件环境.png

4.4.3.      Gluster卷构成

443-1.png

其中,卷volswift为双副本卷,由8个单盘brick构成,总容量为3.7TB,将卷volswift为Gluster对象存储volume。

4.4.4.      网络拓扑图

图7.png

图7 Gluster对象存储基准测试拓扑图

4.4.5.      测试内容与结果

为了比较全面的了解Gluster对象存储在不同对象大小级别的性能情况,本次测试选取的单个对象大小分别为10KB、100KB、1MB、10MB、100MB和1GB的六个级别进行测试。并分别测试了单个客户端和两个客户端的情况。

4.4.5.1.   单个客户端测试

使用客户端1测试对象存储,并且只通过一个存储节点(如存储节点1)访问对象存储,测试使用32线程,共128个container,结果如下:

(1)每个container中10000个object,object大小10KB

测试结果1.png

:read操作的Succ-Ratio为76%,小于80%,被COSBench认为测试失败,这种情况下性能数据在线测试时可见,测试过后需要手动统计进行估算。

(2)每个container中1000个object,object大小100KB

测试结果2.png

(3)每个container中1000个object,object大小1MB

测试结果3.png

(4)每个container中100个object,object大小10MB

测试结果4.png

(5)每个container中100个object,object大小100MB

 测试结果5.png

 (6)每个container中10个object,object大小1GB

测试结果6.png

4.4.5.2.   两个客户端测试

使用客户端1和2同时测试对象存储,通过两个存储节点同时访问对象存储,每个客户端测试使用32线程,每个客户端操作64个container,测试总计结果如下:

(1)每个container中1000个object,object大小10KB

测试结果21.png

注:read操作的Succ-Ratio小于80%,同3.1节的(1)。

(2)每个container中1000个object,object大小100KB

测试结果22.png

(3)每个container中1000个object,object大小1MB

测试结果23.png

(4)每个container中100个object,object大小10MB

测试结果24.png

(5)每个container中20个object,object大小100MB

测试结果25.png

(6)每个container中10个object,object大小1GB

测试结果26.png

4.4.6.      测试总结

(1)对于带宽(MB/S)和每秒操作数(OP/S)指标来说,两个客户端的结果约为单个客户端的2倍;

(2)对于10KB的object大小,单个客户端和两个客户端的的操作成功率都没能超过80%,通过查看日志发现操作失败时返回的http状态码为503(服务不可用),说明在这种测试压力下,Gluster对象存储已经处理不过来客户端请求了,这个可能与对象存储代理节点数有关,本次测试单个客户端使用一个代理节点,两个客户端时使用两个代理节点,如果有更多的代理节点,并且支持负载均衡,应该能承受更大的压力;

(3)对于10MB及以上的object大小,测试出的带宽并不高(同样环境,使用单个客户端跑iozone测试,32线程,块大小1MB,写带宽510MB/S左右,读带宽230MB/S左右),这个问题原因同样可能与对象存储代理节点数有关,但并不会是一直线性增长,受限于底层Gluster卷的并发承受能力;

(4)由于时间限制,本次测试每个用例只测试了一次,可能存在误差,在条件允许的情况下,应该多测试几次,取平均值;

(5)对于多个客户端测试情况,由于文档与网上资料比较简略,对COSBench的多客户端配置可能并不一定完全正确;

(6)COSBench支持可视化、支持多种对象存储系统(如Swift、S3和Ceph等)、提供多种测试指标(如OPS、响应时间、带宽等)以及具有可扩展等功能,是一款不错的对象存储基准测试工具。

5.  总结

本文首先介绍了OpenStack Swift相关理论,然后主要讨论了基于开源社区项目gluster-swift的Gluster对象存储,包括其架构、技术实现方法、工作原理、支持的API、基本配置步骤、相关客户端命令使用方法、S3兼容性测试与性能基准测试等内容,希望为大家提供一个思路。由于本人水平有限,对于Gluster对象存储的一些技术细节,只是点到为止,并未做过多深入介绍,感兴趣的读者可以在网上搜索相关资料,或者查阅文末的参考资料,同时文中难免存在理解错误和不足的地方,也欢迎读者给出意见和建议。

6.  参考资料

[1] http://blog.sina.com.cn/s/blog_7194e5dd0102wme6.html

[2] https://www.ibm.com/developerworks/cn/cloud/library/1310_zhanghua_openstackswift/

[3] https://docs.openstack.org/swift/latest/admin/index.html

[4] https://developer.openstack.org/api-ref/object-store/index.html

[5] https://github.com/gluster/gluster-swift

[6]https://access.redhat.com/documentation/en-us/red_hat_gluster_storage/3.2/html/administration_guide/

[7] http://www.cnblogs.com/sammyliu/p/4955241.html

[8] http://www.aboutyun.com/thread-7107-1-1.html

[9]《OpenStack设计与实现》,英特尔开源技术中心编著,电子工业出版社。

 


发表评论

全部评论(0)