2003年加州大学Santa Cruz分校的Sage Weil专为博士论文设计的新一代自由软件分布式文件系统,并于2012年4月,Sage Weil成立了Inktank公司node
2010年3月以后的linux内核中,嵌入了cephlinux
2014年4月30日,RedHat以$175million的价格收购了Inktank算法
在目前开源世界里多样的存储项目中,不一样的项目都有侧重点,而它们最终都是要为企业的IT基础设施服务。那么企业IT基础设施经理们到底须要怎么样的存储,它们的需求获得知足了吗?编程
从上图咱们能够了解到存储接口需求、扩展、运维和成本构成了企业级存储产品的四大中心。几乎全部的存储产品包括硬件(存储一体机,SAN)和软件都致力于在这个方面强调本身的优点,它们或者考虑成本,或者强调扩展性。那么咱们来看Ceph它是如何定位本身的。vim
Ceph是统一存储系统,支持三种接口:安全
Object:有原生的API,并且也兼容Swift和S3的APIbash
Block:支持精简配置、快照、克隆服务器
File:Posix接口,支持快照网络
Ceph也是分布式存储系统,它的特色以下:数据结构
高扩展性:使用普通x86服务器,支持10~1000台服务器,支持TP到PB级的扩展
高可靠性:没有单点故障,多数据副本,自动管理,自动修复
高性能:数据分布均衡,并行化高,对于objects storage和block storage,不须要元数据服务器
Ceph模块架构图:
底层是Rados,也是Ceph实现分布式存储的根本,全部存储接口都是基于Rados实现的。Rados自己就是一个对象存储接口,它自身维护了一个集群状态和实现了数据分发的要求,咱们一般也讲Rados称为Ceph Cluster,由于其上的存储接口如CephFS都是基于其上的接口实现而已
RADOS的组件(A reliable, autonomous, distributed object storage):
OSD: 每个disk、SSD或者RAID group或者其余一个物理存储设备都成为一个OSD,主要负责存储和查找对象,而且负责向该对象的复制节点分发和恢复。
Monitor: 维护集群的成员和状态,维护整个ceph集群的全局状态。提供强一致性的决策(相似于Zookeeper的做用)
RADOS具备很强的扩展性和可编程性,Ceph基于RADOS开发了Object Storage、Block Storage、FileSystem。Ceph另外两个组件是:
MDS:用于保存CephFS的元数据。
RADOS Gateway:对外提供REST接口,兼容S3和Swift的API。
在传统架构中,客户谈论到一个集中的组件(如网关,代理,API等),做为单点进入到一个复杂的子系统。这会带来性能和可扩展性的限制,同时引入单点故障(即,若是集中的组件出现故障,整个系统也出现故障)。
Ceph的消除了集中式网关,使客户可以直接与Ceph的OSD守护进程进行互动。Ceph的OSD守护进程建立对象的副本,在其余Ceph的节点上,以确保数据的安全性和的高可用性。Ceph的还采用了集群监视器,以确保高可用性。为了消除集中Ceph的使用这种算法叫作CRUSH。
RADOS分发策略–CRUSH算法:
Ceph的客户端和Ceph的OSD守护进程都使用CRUSH算法来高效地对数据容器的信息需求进行计算,而没必要依赖于一个查找表。CRUSH与旧方法相比,提供了更好的数据管理机制,使大规模清晰地将工做分配到集群中的全部客户端和OSD守护。CRUSH使用智能的数据复制,以确保弹性,这样能够更好的适合于超大规模存储。如下各节提供更多的细节CRUSH是如何工做的。
从上图的流程解读RADOS是如何将对象分发到不一样的OSD上(OSD),首先须要了解Ceph定义的几个存储区域概念。
Pool是一个命名空间,客户端向RADOS上存储对象时须要指定一个Pool,Pool经过配置文件定义并能够指定Pool的存储OSD节点范围和PG数量。
PG是Pool内部的概念,是对象和OSD的中间逻辑分层,对象首先会经过简单的Hash算法来获得其存储的PG,这个PG和对象是肯定的。而后每个PG都有一个primary OSD和几个Secondary OSD,对象会被分发都这些OSD上存储,而这个分发策略称为CRUSH—Ceph的数据均匀分布的核心。
须要注意的是整个CRUSH以上的流程实现都是在客户端计算,所以客户端自己须要保存一份Cluster Map,而这是从Monitor处得到。从这里咱们也能够了解到Monitor主要职责就是负责维护这份Cluster Map并保证强一致性。
CRUSH经过伪随机算法来确保均匀的数据分布,它的输入是PG,Cluster State和Policy,而且保证CRUSH的Object Name同样的状况下,即便后二者参数发生改变也会获得一致的读取(注意是读取)。而且这个CRUSH算法是可配置的,经过PG Number和Weight的指定能够获得不一样的分布策略。这个可配置的分布策略让Ceph的能力获得极大增强。
RADOS的逻辑结构:
在使用RADOS系统时,大量的客户端程序经过与OSD或者monitor的交互获取cluster map,而后直接在本地进行计算,得出对象的存储位置后,便直接与对应的OSD通讯,完成数据的各类操做。可见,在此过程当中,只要保证cluster map不频繁更新,则客户端显然能够不依赖于任何元数据服务器,不进行任何查表操做,便完成数据访问流程。在RADOS的运行过程当中,cluster map的更新彻底取决于系统的状态变化,而致使这一变化的常见事件只有两种:OSD出现故障,或者RADOS规模扩大。而正常应用场景下,这两种事件发生 的频率显然远远低于客户端对数据进行访问的频率。
群集映射:
Ceph的使用取决于Ceph的客户和Ceph的OSD守护集群拓扑知识,包括5类映射
1.监控映射:
包含集群FSID,位置,名称地址和每一个监视器的端口。这也代表如今的时期里,当建立映射时,而且它最后一被改变。要查看监控映射,执行以下命令
# ceph mon dump
2.OSD映射:
包含集群FSID,当建立和最后修改映射时间,池的列表,副本大小,PG数字的OSD的列表,他们的状态(例如,up,in)。要查看一个OSD映射,执行以下命令
# ceph osd dump
3.PG映射:
包含PG版本,其时间戳记,最后OSD映射时代,完整的比率,如PG ID,每一个配置组集,代理设置,在PG的状态(例如 active + clean)和每一个池数据使用统计数据。
4.CRUSH映射
包含存储设备,故障域层次结构(例如,设备,主机,机架,行,空间等),并遍历层次结构存储数据时的规则的列表。要查看CRUSH映射,执行命令: getcrushmap –o {filename},而后经过执行crushtool -D {comp-crushmap-filename} -O {decomp-crushmap-filename}反编译。你能够查看在文本编辑器或反编译的映射或使用命令cat查看。
5.MDS映射
包含了现有的MDS映射从它建立至最后一次修改的时期。它还包含池用于存储元数据,元数据服务器的列表,以及元数据服务器中。要查看MDS映射,执行以下命令
# ceph mds dump
每一个映射保持一个重复历史关于其运行状态的变化。Ceph的监视器保持集群的主副本映射,包括集群成员的状态,变化,和Ceph的存储集群的总体健康。
上图左侧的几个概念说明以下:
1. File —— 此处的file就是用户须要存储或者访问的文件。对于一个基于Ceph开发的对象存储应用而言,这个file也就对应于应用中的“对象”,也就是用户直接操做的“对象”。
2. Ojbect —— 此处的object是RADOS所看到的“对象”。Object与上面提到的file的区别是,object的最大size由RADOS限定(一般为2MB或4MB),以便实现底层存储的组织管理。所以,当上层应用向RADOS存入size很大的file时,须要将file切分红统一大小的一系列object(最后一个的大小能够不一样)进行存储。为避免混淆,在本文中将尽可能避免使用中文的“对象”这一名词,而直接使用file或object进行说明。
3. PG(Placement Group)—— 顾名思义,PG的用途是对object的存储进行组织和位置映射。具体而言,一个PG负责组织若干个object(能够为数千个甚至更多),但一个object只能被映射到一个PG中,即,PG和object之间是“一对多”映射关系。同时,一个PG会被映射到n个OSD上,而每一个OSD上都会承载大量的PG,即,PG和OSD之间是“多对多”映射关系。在实践当中,n至少为2,若是用于生产环境,则至少为3。一个OSD上的PG则可达到数百个。事实上,PG数量的设置牵扯到数据分布的均匀性问题。关于这一点,下文还将有所展开。
4. OSD —— 即object storage device,前文已经详细介绍,此处再也不展开。惟一须要说明的是,OSD的数量事实上也关系到系统的数据分布均匀性,所以其数量不该太少。在实践当中,至少也应该是数十上百个的量级才有助于Ceph系统的设计发挥其应有的优点。
基于上述定义,即可以对寻址流程进行解释了。具体而言, Ceph中的寻址至少要经历如下三次映射:
File -> Object映射:
ino(File的元数据,File的惟一id)
ono(File切分产生的某个object的序号)
oid(object id: ino + ono)
此次映射的目的是,将用户要操做的file,映射为RADOS可以处理的object。其映射十分简单,本质上就是按照object的最大size对file进行切分,至关于RAID中的条带化过程。这种切分的好处有二:一是让大小不限的file变成最大size一致、能够被RADOS高效管理的object;二是让对单一file实施的串行处理变为对多个object实施的并行化处理。
每个切分后产生的object将得到惟一的oid,即object id。其产生方式也是线性映射,极其简单。图中,ino是待操做file的元数据,能够简单理解为该file的惟一id。ono则是由该file切分产生的某个object的序号。而oid就是将这个序号简单连缀在该file id以后获得的。举例而言,若是一个id为filename的file被切分红了三个object,则其object序号依次为0、1和2,而最终获得的oid就依次为filename0、filename1和filename2。
这里隐含的问题是,ino的惟一性必须获得保证,不然后续映射没法正确进行。
Object -> PG映射:
hash(oid)&mask -> pgid
mask = PG总数m(m为2的整数幂)- 1
Ceph指定一个静态hash函数计算oid的值,将oid映射成一个近似均匀分布的伪随机值,而后和mask按位相与,获得pgid。
首先是使用Ceph系统指定的一个静态哈希函数计算oid的哈希值,将oid映射成为一个近似均匀分布的伪随机值。而后,将这个伪随机值和mask按位相与,获得最终的PG序号(pgid)。根据RADOS的设计,给定PG的总数为m(m应该为2的整数幂),则mask的值为m-1。所以,哈希值计算和按位与操做的总体结果事实上是从全部m个PG中近似均匀地随机选择一个。基于这一机制,当有大量object和大量PG时,RADOS可以保证object和PG之间的近似均匀映射。又由于object是由file切分而来,大部分object的size相同,于是,这一映射最终保证了,各个PG中存储的object的总数据量近似均匀。
从介绍不难看出,这里反复强调了“大量”。只有当object和PG的数量较多时,这种伪随机关系的近似均匀性才能成立,Ceph的数据存储均匀性才有保证。为保证“大量”的成立,一方面,object的最大size应该被合理配置,以使得一样数量的file可以被切分红更多的object;另外一方面,Ceph也推荐PG总数应该为OSD总数的数百倍,以保证有足够数量的PG可供映射。
PG -> OSD映射:
采用CRUSH算法,将pgid代入其中,而后获得一组共n个OSD(n由部署配置文件决定,通常3个)
第三次映射就是将做为object的逻辑组织单元的PG映射到数据的实际存储单元OSD。如图所示,RADOS采用一个名为CRUSH的算法,将pgid代入其中,而后获得一组共n个OSD。这n个OSD即共同负责存储和维护一个PG中的全部object。前已述及,n的数值能够根据实际应用中对于可靠性的需求而配置,在生产环境下一般为3。具体到每一个OSD,则由其上运行的OSD deamon负责执行映射到本地的object在本地文件系统中的存储、访问、元数据维护等操做。
和“object -> PG”映射中采用的哈希算法不一样,这个CRUSH算法的结果不是绝对不变的,而是受到其余因素的影响。其影响因素主要有二:
1、是当前系统状态,也就是上文逻辑结构中曾经说起的cluster map。当系统中的OSD状态、数量发生变化时,cluster map可能发生变化,而这种变化将会影响到PG与OSD之间的映射。
2、是存储策略配置。这里的策略主要与安全相关。利用策略配置,系统管理员能够指定承载同一个PG的3个OSD分别位于数据中心的不一样服务器乃至机架上,从而进一步改善存储的可靠性。
所以,只有在系统状态(cluster map)和存储策略都不发生变化的时候,PG和OSD之间的映射关系才是固定不变的。在实际使用当中,策略一经配置一般不会改变。而系统状态的改变或者是因为设备损坏,或者是由于存储集群规模扩大。好在Ceph自己提供了对于这种变化的自动化支持,于是,即使PG与OSD之间的映射关系发生了变化,也并不会对应用形成困扰。事实上,Ceph正是须要有目的的利用这种动态映射关系。正是利用了CRUSH的动态特性,Ceph能够将一个PG根据须要动态迁移到不一样的OSD组合上,从而自动化地实现高可靠性、数据分布re-blancing等特性。
之因此在这次映射中使用CRUSH算法,而不是其余哈希算法,缘由之一正是CRUSH具备上述可配置特性,能够根据管理员的配置参数决定OSD的物理位置映射策略;另外一方面是由于CRUSH具备特殊的“稳定性”,也即,当系统中加入新的OSD,致使系统规模增大时,大部分PG与OSD之间的映射关系不会发生改变,只有少部分PG的映射关系会发生变化并引起数据迁移。这种可配置性和稳定性都不是普通哈希算法所能提供的。所以,CRUSH算法的设计也是Ceph的核心内容之一。
Ceph经过三次映射,完成了从file到object、PG和OSD整个映射过程。通观整个过程,能够看到,这里没有任何的全局性查表操做需求。至于惟一的全局性数据结构cluster map,在后文中将加以介绍。能够在这里指明的是,cluster map的维护和操做都是轻量级的,不会对系统的可扩展性、性能等因素形成不良影响。
集群的维护:
若干个mintor共同负责ceph集群中全部osd状态的发现与记录,并共同造成cluster map的master版本,而后扩散至全体osd和client。Osd使用cluster map进行数据维护,而client使用cluster map进行数据寻址。
在集群中,各个monitor的功能整体上是同样的,其相互间的关系能够被简单理解为主从备份关系。所以,在下面的讨论中不对各个monitor加以区分。
monitor并不主动轮询各个OSD的当前状态。正相反,OSD须要向monitor上报状态信息。常见的上报有两种状况:一是新的OSD被加入集群,二是某个OSD发现自身或者其余OSD发生异常。在收到这些上报信息后,monitor将更新cluster map信息并加以扩散。
Cluster map实际内容:
一、Epoch版本号。Cluster map的epoch是一个单调递增序列。Epoch越大,则cluster map版本越新。所以,持有不一样版本cluster map的OSD或client能够简单地经过比较epoch决定应该听从谁手中的版本。而monitor手中一定有epoch最大、版本最新的cluster map。当任意两方在通讯时发现彼此epoch值不一样时,将默认先将cluster map同步至高版本一方的状态,再进行后续操做。
二、各个OSD的网络地址。
三、各个OSD的状态。OSD状态的描述分为两个维度:up或者down(代表OSD是否正常工做),in或者out(代表OSD是否在至少一个PG中)。所以,对于任意一个OSD,共有四种可能的状态:
—— Up且in:说明该OSD正常运行,且已经承载至少一个PG的数据。这是一个OSD的标准工做状态;
—— Up且out:说明该OSD正常运行,但并未承载任何PG,其中也没有数据。一个新的OSD刚刚被加入Ceph集群后,便会处于这一状态。而一个出现故障的OSD被修复后,从新加入Ceph集群时,也是处于这一状态;
—— Down且in:说明该OSD发生异常,但仍然承载着至少一个PG,其中仍然存储着数据。这种状态下的OSD刚刚被发现存在异常,可能仍能恢复正常,也可能会完全没法工做;
—— Down且out:说明该OSD已经完全发生故障,且已经再也不承载任何PG。
四、CRUSH算法配置参数。代表了Ceph集群的物理层级关系(cluster hierarchy),位置映射规则(placement rules)。
Client从Monitors中获得CRUSH MAP、OSD MAP、CRUSH Ruleset,而后使用CRUSH算法计算出Object所在的OSD set。因此Ceph不须要Name服务器,Client直接和OSD进行通讯。伪代码以下所示:
locator = object_name
obj_hash = hash(locator)
pg = obj_hash % num_pg
osds_for_pg = crush(pg) # returns a list of osds
primary = osds_for_pg[0]
replicas = osds_for_pg[1:]
这种数据映射的优势是:
把Object分红组,这下降了须要追踪和处理metadata的数量(在全局的层面上,咱们不须要追踪和处理每一个object的metadata和placement,只须要管理PG的metadata就能够了。PG的数量级远远低于object的数量级)。
增长PG的数量能够均衡每一个OSD的负载,提升并行度。
分隔故障域,提升数据的可靠性。
数据操做流程,强一致性:
当某个client须要向Ceph集群写入一个file时,首先须要在本地完成5.1节中所叙述的寻址流程,将file变为一个object,而后找出存储该object的一组三个OSD。这三个OSD具备各自不一样的序号,序号最靠前的那个OSD就是这一组中的Primary OSD,然后两个则依次是Secondary OSD和Tertiary OSD。
找出三个OSD后,client将直接和Primary OSD通讯,发起写入操做(步骤1)。Primary OSD收到请求后,分别向Secondary OSD和Tertiary OSD发起写入操做(步骤2、3)。当Secondary OSD和Tertiary OSD各自完成写入操做后,将分别向Primary OSD发送确认信息(步骤4、5)。当Primary OSD确信其余两个OSD的写入完成后,则本身也完成数据写入,并向client确认object写入操做完成(步骤6)。
之因此采用这样的写入流程,本质上是为了保证写入过程当中的可靠性,尽量避免形成数据丢失。同时,因为client只须要向Primary OSD发送数据,所以,在Internet使用场景下的外网带宽和总体访问延迟又获得了必定程度的优化。
高新能:
Client和Server直接通讯,不须要代理和转发
多个OSD带来的高并发度。objects是分布在全部OSD上。
负载均衡。每一个OSD都有权重值(如今以容量为权重)。
client不须要负责副本的复制(由primary负责),这下降了client的网络消耗。
高可靠性:
数据多副本。可配置的per-pool副本策略和故障域布局,支持强一致性。
没有单点故障。能够忍受许多种故障场景;防止脑裂;单个组件能够滚动升级并在线替换。
全部故障的检测和自动恢复。恢复不须要人工介入,在恢复期间,能够保持正常的数据访问。
并行恢复。并行的恢复机制极大的下降了数据恢复时间,提升数据的可靠性。
主机角色分配
192.168.31.80 admin(ceph-deploy,ntp服务器)
192.168.31.84 osd1(mon*1,osd*3)
192.168.31.85 osd2(mon*1,osd*3)
192.168.31.86 osd3(mon*1,osd*3)
安装配置前准备工做,在admin主机生成密钥和公钥并认证其余节点服务器
~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub osd1 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub osd2 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub osd3
admin服务器安装配置:
#安装配置ntp服务器 ~]# cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #修改时区 ~]# yum install ntp ~]# vim /etc/ntp.conf server 127.127.1.0 fudge 127.127.1.0 stratum 8 restrict default nomodify ~]# systemctl start ntpd #默认的源比较慢,这里使用阿里的源 ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo(下载阿里云的base源) ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo(下载阿里云的epel源) ~]# sed -i 's/$releasever/7.2.1511/g' /etc/yum.repos.d/CentOS-Base.repo ~]# vim /etc/yum.repos.d/ceph.repo [ceph] name=ceph baseurl=http://download.ceph.com/rpm-hammer/el7/x86_64/ gpgcheck=0 [ceph-noarch] name=cephnoarch baseurl=http://download.ceph.com/rpm-hammer/el7/noarch/ gpgcheck=0 ~]# yum makecache #在admin安装ceph-deploy ~]# yum install ceph-deploy #在osd1,osd2,osd3等上安装ceph包 ~]# yum install ceph #在远程主机上部署一个集群,并生成配置文件和集群内部认证密钥文件 ~]# ceph-deploy mon create-initial #在远程主机上部署一个ceph监控(mon) ~]# ceph-deploy mon add node3 #添加一个节点到现有的集群中,添加完成后须要在ceph.conf中添加上对应的节点,并同步 ~]# ceph-deploy --overwrite-conf config push node1 node2 node3 #强行将修改的配置文件同步到其余节点上 ~]# ceph-deploy disk list node1 #查看节点的磁盘状况 ~]# ceph-deploy osd prepare osd1:/dev/sdc1:/dev/sdb1 osd1:/dev/sdd1:/dev/sdb2 osd1:/dev/sde1:/dev/sdb3 #建立三个osd rbd create block-csdn --size=100 rbd map rbd/block-csdn rbd unmap /dev/rbd0