什么是 Ceph 分布式存储?

Ceph 项目最早起源于 Sage 就读博士期间的工作(最早的成果于 2004 年发表),并随后贡献给开源社区。在经过了数年的发展之后,目前已得到众多云计算厂商的支持并被广泛应用。RedHat 及 OpenStack 都可与 Ceph 整合以支持虚拟机镜像的后端存储。但是在 2014 年 OpenStack 火爆的时候、Ceph 并不被很多人所接受。当时 Ceph 并不稳定(Ceph 发布的第四个版本 Dumpling v0.67),而且架构新颖,复杂,当时人们对 Ceph 在生产落地如何保障数据的安全,数据的一致性存在怀疑。

随着 OpenStack 的快速发展,给 Ceph 的发展注入了强心剂,越来越多的人使用 Ceph 作为 OpenStack 的底层共享存储,Ceph 在中国的社区也蓬勃发展起来。近两年 OpenStack 火爆度不及当年,借助于云原生尤其是 Kubernetes 技术的发展,作为底层存储的基石,Ceph 再次发力,为 Kubernets 有状态化业务提供了存储机制的实现。

存储发展史

企业中使用存储按照其功能,使用场景,一直在持续发展和迭代,大体上可以分为四个阶段:

  • **DAS:**Direct Attached Storage,即直连存储,第一代存储系统,通过 SCSI 总线扩展至一个外部的存储,磁带整列,作为服务器扩展的一部分;
  • **NAS:**Network Attached Storage,即网络附加存储,通过网络协议如 NFS 远程获取后端文件服务器共享的存储空间,将文件存储单独分离出来;
  • **SAN:**Storage Area Network,即存储区域网络,分为 IP-SAN 和 FC-SAN,即通过 TCP/IP 协议和 FC(Fiber Channel) 光纤协议连接到存储服务器;
  • **Object Storage:** 即对象存储,随着大数据的发展,越来越多的图片,视频,音频静态文件存储需求,动仄 PB 以上的存储空间,需无限扩展。

存储的发展,根据不同的阶段诞生了不同的存储解决方案,每一种存储都有它当时的历史诞生的环境以及应用场景,解决的问题和优缺点。

区别如下:

DAS 直连存储服务器使用 SCSI 或 FC 协议连接到存储阵列、通过 SCSI 总线和 FC 光纤协议类型进行数据传输;例如一块有空间大小的裸磁盘:/dev/sdb。DAS 存储虽然组网简单、成本低廉但是可扩展性有限、无法多主机实现共享、目前已经很少使用了。

NAS 网络存储服务器使用 TCP 网络协议连接至文件共享存储、常见的有 NFS、CIFS 协议等;通过网络的方式映射存储中的一个目录到目标主机,如 /data。NAS 网络存储使用简单,通过 IP 协议实现互相访问,多台主机可以同时共享同一个存储。但是 NAS 网络存储的性能有限,可靠性不是很高。

SAN 存储区域网络服务器使用一个存储区域网络 IP 或 FC 连接到存储阵列、常见的 SAN 协议类型有 IP-SAN 和 FC-SAN。SAN 存储区域网络的性能非常好、可扩展性强;但是成本特别高、尤其是 FC 存储网络:因为需要用到 HBA 卡、FC 交换机和支持 FC 接口的存储。

Object Storage 对象存储通过网络使用 API 访问一个无限扩展的分布式存储系统、兼容于 S3 风格、原生 PUT/GET 等协议类型。表现形式就是可以无限使用存储空间,通过 PUT/GET 无限上传和下载。可扩展性极强、使用简单,但是只使用于静态不可编辑文件,无法为服务器提供块级别存储。

综上、企业中不同场景使用的存储,使用表现形式无非是这三种:磁盘(块存储设备),挂载至目录像本地文件一样使用(文件共享存储),通过 API 向存储系统中上传 PUT 和下载 GET 文件(对象存储)。

什么是 Ceph?

接下来我们要讲讲 Ceph,那么到底什么是 Ceph 呢?Ceph 能够提供企业中三种常见的存储需求:块存储、文件存储和对象存储,正如 Ceph 官方所定义的一样“Ceph uniquely delivers object, block, and file storage in one unified system.”,Ceph 在一个统一的存储系统中同时提供了对象存储、块存储和文件存储,即 Ceph 是一个统一存储,能够将企业企业中的三种存储需求统一汇总到一个存储系统中,并提供分布式、横向扩展,高度可靠性的存储系统,Ceph 存储提供的三大存储接口:

上图详见官方文档:http://docs.ceph.org.cn/

1、CEPH OBJECT STORE 对象存储,包含功能,特性如下:

  • RESTful Interface RESTful 风格接口;
  • S3- and Swift-compliant APIs 提供兼容于 S3 和 Swfit 风格 API;
  • S3-style subdomains S3 风格的目录风格;
  • Unified S3/Swift namespace 统一扁平的 S3/Swift 命名空间,即所有的对象存放在同一个平面上;
  • User management 提供用户管理认证接入;
  • Usage tracking 使用情况追踪;
  • Striped objects 对象切割,将一个大文件切割为多个小文件(objects);
  • Cloud solution integration 云计算解决方案即成,可以与 Swfit 对象存储即成;
  • Multi-site deployment 多站点部署,保障可靠性;
  • Multi-site replication 多站点复制,提供容灾方案。

2、CEPH BLOCK DEVICE 块存储,包含功能,特性如下:

  • Thin-provisioned 瘦分配,即先分配特定存储大小,随着使用实际使用空间的增长而占用存储空间,避免空间占用;
  • Images up to 16 exabytes 耽搁景象最大能支持 16EB;
  • Configurable striping 可配置的切片,默认是 4M;
  • In-memory caching 内存缓存;
  • Snapshots 支持快照,将当时某个状态记录下载;
  • Copy-on-write cloning Copy-on-write 克隆复制功能,即制作某个镜像实现快速克隆,子镜像依赖于母镜像;
  • Kernel driver support 内核驱动支持,即 rbd 内核模块;
  • KVM/libvirt support 支持 KVM/libvirt,实现与云平台如 openstack,cloudstack 集成的基础;
  • Back-end for cloud solutions 云计算多后端解决方案,即为 openstack,kubernetes 提供后端存储;
  • Incremental backup 增量备份;
  • Disaster recovery (multisite asynchronous replication) 灾难恢复,通过多站点异步复制,实现数据镜像拷贝。

3、CEPH FILE SYSTEM 文件存储,包含功能,特性如下:

  • POSIX-compliant semantics POSIX 风格接口;
  • Separates metadata from data 元数据 metadata 和数据 data 分开存储;
  • Dynamic rebalancing 动态数据均衡;
  • Subdirectory snapshots 子目录快照;
  • Configurable striping 可配置切割大小;
  • Kernel driver support 内核驱动支持,即 CephFS;
  • FUSE support 支持 FUSE 风格;
  • NFS/CIFS deployable 支持 NFS/CIFS 形式部署;
  • Use with Hadoop (replace HDFS) 可支持与 Hadoop 继承,替换 HDFS 存储。

通俗点讲:Ceph 提供了三种存储接口:块存储 RBD,对象存储 RGW 和文件存储 CephFS,每种存储都有其相应的功能和特性。

Ceph 存储架构

Ceph 独一无二地用统一的系统提供了对象、块、和文件存储功能,它可靠性高、管理简便、并且是自由软件。 Ceph 的强大足以改变贵公司的 IT 基础架构、和管理海量数据的能力。Ceph 可提供极大的伸缩性——供成千用户访问 PB 乃至 EB 级的数据。 Ceph 节点以普通硬件和智能守护进程作为支撑点, Ceph 存储集群组织起了大量节点,它们之间靠相互通讯来复制数据、并动态地重分布数据。

接下来,我们先来看一下 Ceph 的存储架构,了解 Ceph 的分布式架构,功能组件和涉及相关概念。Ceph 分布式集群是建立在 RADOS 算法之上的,RADOS 是一个可扩展性,高可靠的存储服务算法,是 Ceph 的实现的基础。Ceph 有两个重要的组件组成:Ceph Monitors(Ceph 监视器)和 Ceph OSDs(Ceph OSD 守护进程)

其中 Ceph Monitor 作为集群中的控制中心,拥有整个集群的状态信息,各个组件如 OSDs 将自己的状态信息报告给 Ceph Monitor 这个总司令,由此可以可知,Ceph Monitor 这个总司令肩负起整个集群协调工作;同时 Ceph Monitor 还负责将集群的指挥工作,将集群的状态同步给客户端,客户端根据 Ceph Monitor 发送的集群状态信息可以获取到集群的状态,当集群状态有变化如 OSD 增加或故障时,Ceph Monitor 会负责更新集群状态并下发给客户端。Ceph Monitor 的重要不言而喻,为了保障集群的可用性,需要部署高可用,一般需要部署 2n+1 个节点,如 3 个或 5 个 Ceph Monitor 节点。

什么是集群的状态呢? Ceph Monitor 中保存的集群状态根据其功能角色的不同,分为以下几个 map 状态表:

  • Monitor Maps,集群 Ceph Monitor 集群的节点状态,通过 ceph mon dump 可以获取;
  • OSD Maps,集群数据存储节点的状态表,记录集群中 OSD 状态变化,通过 ceph osd dump 可以获取;
  • PGs Maps,PGs 即 placement group,表示在 OSD 中的分布式方式,通过 ceph pg dump 可以获取;
  • Crush Maps,Crush 包含资源池 pool 在存储中的映射路径方式,即数据是如何分布的;
  • MDS Maps,CephFS 依赖的 MDS 管理组件,可通过 ceph mds dump 获取,用于追踪 MDS 状态。

除了 Ceph Monitor 之外,还有一个重要的组件是 OSD,集群中通常有多个 OSD 组成,OSD 即 Object Storage Daemon,负责 Ceph 集群中真正数据存储的功能,也就是我们的数据最终都会写入到 OSD 中。除了 Monitor 之外,根据 Ceph 提供的不同功能,还有其他组件,包括:

  • Ceph Monitors(ceph-mon);
  • Ceph OSDs(ceph-osd);
  • Ceph MDS(ceph-mds),用于提供 CephFS 文件存储,提供文件存储所需元数据管理;
  • Ceph RGW(ceph-rgw),用于提供 Ceph 对象存储网关,提供存储网关接入;
  • Ceph Manager(ceph-mgr),提供集群状态监控和性能监控。

注:Ceph Monitor 监视器维护着集群运行图的主副本。一个监视器集群确保了当某个监视器失效时的高可用性。存储集群客户端向 Ceph Monitor 监视器索取集群运行图的最新副本。而 Ceph OSD 守护进程检查自身状态、以及其它 OSD 的状态,并报告给监视器们。存储集群的客户端和各个 Ceph OSD 守护进程使用 CRUSH 算法高效地计算数据位置,而不是依赖于一个中心化的查询表。它的高级功能包括:基于 librados 的原生存储接口、和多种基于 librados 的服务接口。

Ceph 数据的存储

了解完 Ceph 的架构后,我们先来了解一下 Ceph 的读写流程,期间会涉及到 CRUSH,PGs 等这些概念,我们从一个最基本的的概念入手:Ceph 中一切皆对象,不管是 RBD 块存储接口,RGW 对象存储接口还是文件存储 CephFS 接口,其存储如到 Ceph 中的数据均可以看作是一个对象,一个文件需要切割为多个对象(object),然后将 object 存储到 OSD 中,如下图:

注:Ceph 存储集群从 Ceph 客户端接收数据——不管是来自 Ceph 块设备、 Ceph 对象存储、 Ceph 文件系统、还是基于librados的自定义实现——并存储为对象。每个对象是文件系统中的一个文件,它们存储在对象存储设备上。由 Ceph OSD 守护进程处理存储设备上的读 / 写操作。

那么,这些切割后的 object 怎么选择到对应的 OSD 存储节点呢,这需要依赖于 Ceph 的智能调度算法 CRUSH,通过 CRUSH 算法将 object 调度到合适的 OSD 节点上,不管是客户端还是 OSD,均使用 CRUSH 算法来计算 object 在集群中 OSD 的位置信息,同时保障 object 的副本能落到合适的 OSD 节点上,关于 CRUSH 算法的实现比较复杂,详情可以参考:CRUSH: Controlled, Scalable, Decentralized Placement of Replicated Data

Ceph OSD 在扁平的命名空间内把所有数据存储为对象(也就是没有目录层次)。对象包含一个标识符、二进制数据、和由名字 / 值对组成的元数据,元数据语义完全取决于 Ceph 客户端。例如, CephFS 用元数据存储文件属性,如文件所有者、创建日期、最后修改日期等等。

object 调度到 OSD 节点上,如果一个文件发生了变动或 OSD 出现了异常,以一个 100G 的文件为例,每个 object 默认为 4M,将会切割为 25600 个 object,如果 Ceph 集群需要正对每个 object 都进行调度的话,可想而知,在一个大规模集群中,crush 的调度将会变得异常的繁重。因此,Ceph 引入了另外一个概念 PG,PG 是 Place Group 即放置组,可以简单理解为一个装载 object 的容器,object 将映射到 PG 中,PG 最终会调度到某个具体的 OSD 上,因此 CRUSH 由 object 调度转为 PG 的调度,而 PG 的数量是相对固定的,因此集群分布时调度相对没有那么繁重,同时,当某个 OSD 异常时,CRUSH 调度算法只需将其上的 PG 调度至其他 OSD 上(而不是将其上的 object 进行调度)。Ceph 的整个数据调度写入流程如下图:

  • 一个文件将会切割为多个 object(如 1G 文件每个 object 为 4M 将切割为 256 个),每个 object 会由一个由 innode(ino)和 object 编号 (ono) 组成 oid,即 object id,oid 是真个集群唯一,唯一标识 object 对象;
  • 针对 object id 做 hash 并做取模运算,从而获取到 pgid,即 place group id,通过 hash+mask 获取到 PGs ID,PG 是存储 object 的容器;
  • Ceph 通过 CRUSH 算法,将 pgid 进行运算,找到当前集群最适合存储 PG 的 OSD 节点,如 osd1 和 osd2(假设为 2 个副本);
  • PG 的数据最终写入到 OSD 节点,完成数据的写入过程,当然这里会涉及到多副本,一份数据写多副本。