一、Ceph介绍
1.大规模存储系统的动态特性
存储系统规模的变化
存储系统中设备的变化
存储系统中数据的变化
2.技术特性
高可靠性:尽可能保证数据不会丢失
高度自动化:自动复制、自动再平衡、自动故障检测和自动故障恢复
高可扩展性:系统规模和存储容量的可扩展,聚合数据访问带宽的线性扩展,底层API支持多种功能、多种应用的功能性可扩展
3.设计思路
充分发挥存储设备自身的计算能力
去除所有的中心点
4.解决的问题
我应该把数据写到什么地方
我之前把数据写到什么地方了
二、Ceph体系结构
1.层次
Ceph存储集群
基础库librados
高层应用接口RADOS GW、RBD和Ceph FS
应用层
2.对象存储
采用Key/Value方式的RESTful数据读写接口
扁平的数据组织结构,往往是两层或三层
3.RADOS
OSD:负责完成数据存储和维护
Monitor:负责完成系统状态检测和维护
Ceph客户端、Monitor和OSD可以直接交互,意味着OSD可以利用本地节点的CPU和内存执行那些传统集群架构中有可能拖垮中央服务器的任务
4.OSD
OSD的状态
up或down(OSD Daemon与Monitor连接是否正常)
in或out(OSD是否含有PG)
OSD状态检测
OSD之间的心跳包,Peer OSD是指该OSD上所有PG的副本所在的OSD
OSD与Monitor之间的心跳包,可以堪称Peer OSD之间心跳包的补充
5.数据寻址
概念
File:用户需要存储或访问的文件,对应于应用中的“对象”,也就是用户直接操作的“对象”
Object:最大尺寸由RADOS限定,通常为2MB或4MB,File会统一切分成统一大小的一系列Object
PG:对Object的存储进行组织和位置映射,PG和Object之间是“一对多”的映射管理,PG和OSD之间是“多对多”的映射管理,实践中,一个PG存放在3个OSD中,一个OSD上的PG可达数百个
OSD:OSD的数量事实上也关系到系统的数据分布均匀性,因此不应该太少
File->Object映射
按照Object的最大尺寸对File进行切分,每个切分后产生的Object将获得唯一的oid,如果1个ID为filename的File被切分成三个对象,序号分别为0,1,2,则oid依次为filename0,filename1,filename2
Object->PG映射
使用Ceph系统指定的一个静态哈希算法计算oid的哈希值,将oid映射为一个近似均匀分布的伪随机值
将这个伪随机值和mask按位相与,得到最终的PG序号(pgid)
PG->OSD映射
采用CRUSH算法,将pgid代入其中,得到一组共n个OSD,n一般为3,这n个OSD共同负责存储和维护一个PG中的所有Object
只有在系统状态和存储策略都不发生变化的时候,PG和OSD之间的映射关系才是固定不变的
Ceph正是利用了CRUSH算法的动态特性,可以将一个PG根据需要动态迁移到不同的OSD组合上,从而自动化地实现高可靠性、数据分布再均衡等特性
6.CRUSH算法优势
可以根据管理员的配置参数决定OSD的物理位置映射策略
系统中OSD数量变化时,大部分PG与OSD之间的映射关系不会发生改变,只有少部分PG的映射关系会发生变化并引发数据迁移
为什么需要引入PG并在Object与OSD之间增加一层映射
实现了Object和OSD之间的动态映射,从而为Ceph的可靠性、自动化等特性的实现留下了空间
有效简化了数据的存储组织,大大降低了系统的维护与管理成本
7.存储池
设置数据存储的方法属于多副本模式还是纠删码模式
设置PG的数目
设置PGP的数目,通常情况下与PG数目一致,当需要增加PG数目时,用户数据不会发生迁移,只有进一步增加PGP数目时,用户数据才会开始迁移
针对不同的存储池设置不同的CRUSH存储规则
提供针对存储池的功能,如存储快照
设置对象的所有者或访问权限
8.Monitor
集群运行图
Monitor Map
OSDMap
PG Map
CRUSH Map
MDS Map
Monitor与客户端的通信
命令行操作
获取OSDMap
客户端初始化时
OSDMap设置了CEPH_OSDMAP_PAUSEWR/PAUSERD
OSDMap设置了Cluster空间已满或存储池空间已满
找不到相应的存储池或通过哈希算法得到PG,但是在OSDMap中查不到相关PG分布信息
Monitor与OSD的通信
Monitor需要知道OSD的状态,并根据状态生成新的OSDMap
OSD和Monitor之间存在心跳机制,通过这种方式来判断OSD的状态
OSD定时将PG信息发送给Monitor
OSD的操作命令是客户端通过Monitor传递给OSD的
OSD初始化成client/primary OSD所包含的OSDMap的版本高于当前的OSDMap
9.数据操作流程
流程
客户端只向Object所对应OSD set的Primary发起读写请求
当Primary收到Object的写请求时,它负责把数据发送给其他副本
只有这个数据被保存在所有的OSD上时,Primary才应答Object的写请求
确认
当各个OSD都将数据写入内存缓冲区后,就先向客户端发送一次确认,此时客户端即可以向下执行
待各个OSD都将数据写入磁盘后,会向客户端发送一个最终确认信号,此时客户端可以根据需要删除本地数据
优化
客户端可以独立完成OSD寻址操作
同一个OSD在不同的PG中的角色不同,从而避免单个OSD变成性能瓶颈
被读取的数据默认由Primary OSD提供,但也可以设置允许从其他OSD中获取,以分散读取压力从而提高性能
10.Cache Tiering
缓存层使用多副本模式,Storage层可以使用多副本或纠删码模式
模式
写回模式
forward模式:所有的请求都重定向到Storage层访问
readonly模式:写请求直接重定向到Storage层访问
readforward模式:读请求都重定向到Storage层中,写请求采用写回模式
readproxy模式
proxy模式:对于读写请求都采用代理的方式
操作的含义
重定向:缓存层告诉客户端应该去请求Storage层
代理:缓存层会自己发送请求给Storage层,并不会把object保存在缓存层
提升:缓存层会自己发送请求给Storage层,同时会把object保存在缓存层
11.块存储
条带化
stripe-unit
stripe-count
使用Ceph块设备的两种路径
通过Kernel Module
通过librbd
12.Ceph FS
1)两种客户端
Ceph FS FUSE
Ceph FS Kernel
2)MDS
Ceph FS要求Ceph存储集群内至少有一个元数据服务,负责提供文件系统元数据的存储与操作
Ceph FS从数据中分离出元数据,并存储于MDS,从而简单的操作如ls,cd可以不用扰动OSD,把元数据从数据里分离出来意味着Ceph文件系统既能提供高性能服务,又能减轻存储集群负载
3)Multi Active MDS
将目录分割,放在不同的MDS上,可以减轻MDS的压力,防止单个MDS瓶颈
可以根据目录长度和访问频率两个维度来进行分割或合并
配额
允许给系统内的任意目录以大小或文件数目的形式设置配额
4)局限性
Ceph FS的配额功能依赖于挂载它的客户端的合作,在达到上限时要停止写入
配额是不准确的
内核客户端还没有实现配额功能,目前用户空间客户端(libcephfs,ceph-fuse)已经支持配额
基于路径限制挂载时必须谨慎地配置配额
三、后端存储ObjectStore
1.FileStore
目前支持的文件系统有XFS/ext4/Btrfs,推荐使用XFS
1)写操作
Touch:对应系统调用create
Setattrs:对应系统调用setattrs
Write:对应系统调用write
Omap_setkeys:对应RocksDB的transaction
2)journal
底层文件系统不支持事务的原子性,上面4个操作在Ceph里合在一起称为事务
先将事务作为一个entry存放在journal上,然后事务操作在文件系统上执行,最后就通知journal删除,否则OSD重启之后读取journal进行重做
建议journal使用固态硬盘、NVMe或者Optane
3)缺点
优点是通过journal保证事务的原子性,缺点是XFS也带有journal,写放大严重,而且XFS/Btrfs是通用的文件系统,满足所有可移植操作系统系统的要求,因此在某些操作上性能没有那么高
针对机械盘进行设计,没有对固态硬盘的情况进行优化
2.BlueStore
去掉了journal,通过直接管理裸设备的方式减少文件系统的部分开销,并且对固态硬盘进行了单独的优化
1)数据管理
BlockDevice:在使用BlueFS+RocksDB的情况下最多有3个块设备,Data存放BlueStore数据,WAL存放RocksDB内部journal,DB存放RocksDB SST(sorted sequence table)
2)驱动
系统调用读写
使用Linux系统调用读写或aio_submit来访问块设备
SPDK
专门为NVMe开发的用户空间驱动,放弃原有系统调用方式
PMDK
专门为英特尔AEP设备开发的驱动,AEP可以看成带电的DRAM,按照字节寻址,使用DAX技术,mmap可以绕过Page Cache
3)元数据管理
RocksDB:默认的KVDB,后端存储必须基于一个文件系统,所以对于RocksDB有两种选择,使用标准Linux文件系统,或者实现一套简单的用户空间文件系统,基于性能的考虑,Ceph实现了BlueFS
BlueStore实现了BlueRocksEnv,来为RocksDB提供底层BlueFS文件系统的封装
BlueFS:专门为RocksDB开发的文件系统,自己管理裸设备,BlueFS的元数据是作为一个内部特殊的文件进行管理的,因为它的文件和目录都不是很大,不同于BlueStore元数据是存放在RocksDB中
4)空间管理
Allocator:按照最小单元进行格式化,使用Bitmap进行分配
3.SeaStore
下一代的ObjectStore
目标
专门为NVMe设备设计,而不是PMEM和硬盘驱动器
使用SPDK访问NVMe而不再使用Linux AIO
使用SeaStar Future编程模型进行优化,以及使用share-nothing机制避免锁竞争
网络驱动使用DPDK来实现零拷贝
设计思路
SeaStore的逻辑段应该与硬件segment(Flash擦除单位)对齐
SeaStar是每个线程一个CPU核,所以将底层按照CPU核进行分段
当空间使用率达到设定上限时,就会进行回收,当segment完全回收后,就会调用discard线程通知硬件进行擦除,尽可能保证逻辑段与物理段对其,尽量平滑处理回收工作,减少对正常读写的影响
四、Ceph可靠性
1.架构的可靠性
分布式算法:Ceph消除了中心化的组件使客户端可以和OSD的守护进程直接打交道,客户端和OSD守护进程都使用CRUSH算法来有效地计算出对象存储的位置,而不是基于一个中心化的查找表格,节点的加入和退出,CRUSH算法会重新在OSD上分布数据
集群:Ceph还利用Monitor集群来保证集群结构的高可靠性,Ceph客户端在读写数据之前,必须与Monitor通信来获得最新的集群运行图的副本,Ceph支持Monitor集群来消除该单点故障,当一个Monitor失效时,由其他Monitor来接管
2.数据的可靠性
1)数据冗余备份
RBD的冗余备份
RBD mirror
为集群间的异地容灾和高可用性提供了较为可靠的解决方案
集群间的镜像基于日志实现了最终一致性模型,写操作会首先以日志形式保存在RADOS对象中,再根据CRUSH算法将数据真正保存到本地集群,远端集群可以读取主集群的写日志,再按顺序将修改重放到备份集群中
rbd-mirror服务来管理、同步镜像数据和连接镜像集群,负责从远端集群拉取日志更新,并应用到当前集群中
最成熟的备份模式是active/standby,还支持active/active模式,通过现有的exclusive-lock机制来保证同一时刻只有获得锁的Image能够产生写操作
局限性:性能开销比较高,不支持多于两个集群的镜像功能,以及集群间镜像数据传输的带宽限制
RBD Snapshot
快照模式
Pool Snapshot:存储池级别的快照,一旦创建了快照,就不能创建RBD Image,反之亦然
Self Managed Snapshot:由用户管理的快照,即存储池中受影响的对象是受用户控制的
RBD快照的导出和恢复
在时间点v1和v2对Image分别做快照
导出从Image创建到当前时间的差异数据到本地文件
基于快照的恢复过程,或者说回滚,使用的就是刚刚创建或导出的那些备份文件
写时复制
这种方式又称为第一次写时复制,即在数据第一次写入某个存储位置时,先将原有的内容复制到另一个位置,再将数据写入存储设备中,而下次针对同一位置的写操作将不再触发写时复制
这种实现方式在第一次写入某个存储位置时需要完成一个读操作,两个写操作,适合I/O以读操作为主的场景
克隆
快照是只读备份,克隆是可写的数据备份
克隆只能基于快照创建
从克隆读数据,本质上是从克隆出来的RBD Image中读数据,对于不是它自己的数据对象,Ceph会从它的Parent上读
向克隆写数据,Ceph会首先检查该克隆上的数据对象是否存在,不存在的话,则从Parent上复制该数据对象,再执行数据写入操作
OSD的备份
Ceph提供的是强一致性副本策略,只有当数据的多个副本都写入之后,OSD才告知客户端写入成功
客户端使用CRUSH算法计算对象应该存储在哪里,映射对象到一个存储池和PG中,然后查找CRUSH Map来确定该PG的主OSD
客户端把对象写入相应的主OSD的PG后,主OSD通过自身带有的CRUSH Map来确定副本所在的第二和第三OSD,分别写入完成后再返回客户端
2)OSD纠删码
Ceph纠删码常用的编码是RS(k,m),默认的纠删码库是Jerasure,是第三方提供的中间件
优缺点:可以极大的减少存储开销,但带来了计算量和网络负载等额外的负担,重建和修复数据代价太大,整体来看,若采用纠删码,需要在容错能力、存储资源利用率和数据重建所需的代价之间做一个平衡
场景:热数据往往通过副本策略保存,冷数据则通过纠删码保存,纠删码适合一次写多次读的场景
Ceph数据恢复
感知集群状态
OSD集群节点的状态信息存放在OSDMap中,OSD节点定期向MON和对等OSD发送心跳信息
MON集群判定某个OSD节点离线后,会将最新的OSDMap通过消息机制随机分发给一个OSD
客户端和对等OSD处理I/O请求的时候,发现自身的OSDMap版本过低,会向MON请求最新的OSDMap
确定受故障影响的数据
Ceph OSD的任何操作都会写一条记录,每个OSD管理一定数量的PG,PG中维护了一份pglog,用来记录对该PG中数据对象的操作
Ceph使用版本控制的方式标记一个PG内的每一次更新,每个版本包括一个epoch和version,epoch是OSDMap的版本号,version是PG内每次更新操作的版本号
pglog里最重要的两个指针是last_complete和last_update,正常情况下每个副本这两个指针指向同一个位置,集群故障副本指针就会有所区别
数据恢复
故障恢复时要进行peering,以PG为单位,PG会根据pglog检查多个副本的一致性,根据差异构造缺失记录数目,最后得到一份完整的对象缺失列表
peering过程中,IO请求会挂起,peering完成后,IO操作可以继续进行,当IO请求命中了缺失列表的时候,对应的对象会优先进行恢复
peering完成后,PG进入激活状态,可以开始接收IO请求,对于Replica PG缺失的数据主PG会push,对于主PG缺失的数据会通过pull,对于无法依靠pglog恢复的,PG将进行backfill操作,进行数据的全量复制
五、Ceph一致性
Ceph使用pglog来保证多副本之间的数据一致性,由于Ceph客户端的IO操作都是发给主OSD,所以保证同一PG内的读写顺序性也就保证了多副本之间的一致性
1.不同对象的并发控制
对同一个PG里的不同对象,是通过PG锁来进行并发控制的
同一个对象的并发顺序控制
网络顺序的保证
消息层的顺序保证
PG层的顺序保证
读写锁
ObjectStore层的顺序保证
副本顺序的保证
2.Ceph Scrub机制
Ceph需要提供一种机制去检查各个副本之间的数据是否一致,如果不一致就必须恢复,这种机制就是Scrub
普通Scrub只比较元数据信息,Deep Scrub会真正地读取文件内容进行比较
Ceph是以PG为粒度来管理数据一致性的,Scrub也是以PG为粒度进行触发的,并且是由PG内主OSD启动的
为了避免一次产生大量的信息,Scrub流程会把一个PG内的所有对象文件划分为块,即一次值比较一个块的对象,这些对象称为chunky scrub
发起者主OSD会要求所有节点都开始计算这个对象集合中对象文件的校验信息并反馈,汇总为ScrubMap,如果有不一致的对象,会发送给MON,用户可以手动执行命令来启动修复进程
六、Ceph缓存机制
1.块存储
基于内核模块(KRBD),通过用户态的rbd命令行工具,将RBD块设备映射为本地的一个块设备文件
以librdb库的形式为Qemu虚拟机增加虚拟块设备
2.RBDCache
该缓存位于librbd库,当用户通过librbd库访问RBD Image时,可设置打开缓存
librbd支持预读或预取功能,以此优化小块的顺序读操作
librbd提供两种缓存模式:写透和写回
Qemu直接调用librbd的接口来对RBD Image进行读写和控制操作
RBDCache只是RBD层在客户端的缓存,只支持块设备,作为客户端的缓存,RBDCache可能会出现引入数据不一致的问题,目前只能使用内存作为缓存
3.缓存模式
1)内核缓存与块设备缓存
对于RBDCache的实现来说,flush的支持是关键
librbd提供flush接口同样能将缓存中的脏数据全部写回
一旦系统非正常宕机,如果来不及下刷数据,这些缓存中的脏数据仍然会丢失
2)KVM write barrier
对于写操作,它相当于每写一次缓存,就调用fsync将数据持久化
新的KVM版本中,启用了“barrier-passing”功能,能够将Guest操作系统上同步写入的数据100%写入持久存储
barrier-passing具体的工作原理是根据每个事务来进行数据持久化,这样可以保证持久化的数据是一致的,可用的
3)基本流程
在一个会话中写入数据
发出barrier request
会话中的所有数据被刷新到物理磁盘
继续下一个会话
写透相当于每次写都会发fsync,而barrier-passing是以事务为单位来发fsync的,一个事务经常会包含若干个写操作,因此效率更高
4.固态硬盘用作缓存
1)RBDCache几点不足
ObjectCacher的实现是单线程模式
同一主机上的多个客户端之间数据不能共享,缓存是存在于每个读写进程内部的
不支持顺序写回操作,数据写入缓存是有顺序的,但是数据从缓存下刷到远端OSD没有顺序
2)Intel的Hyper Converge Cache方案
只读缓存
所有缓存固态硬盘上的数据可以被多个客户端共享,同时新的后台进程也会解决现有缓存单线程的问题
写回缓存
基于Master/Slave框架结构,多个客户端组成一个集群,分成Master和Slave角色
七、Ceph加密和压缩
1.加密
客户端加密和存储端加密
1)对象网关加密
指客户端将数据传递到对象网关,网关将数据加密存储到Ceph集群;反之,密文数据从Ceph集群读取到对象网关,进行解密,然后传送到客户端
密钥管理
用户提供密钥
客户端将在每次IO操作时将密钥一起传递给Ceph
密钥管理服务
Barbican是OpenStack的一个子项目,为存储安全提供密钥密码及证书管理
Ceph对象网关首先向Keystone请求token,拿到之后向Barbican请求密钥
自动加密
在ceph.conf中设置默认的加密密钥
2)OSD端加密
对硬盘进行加密,通过linux内核dmcrypt模块进行数据的加密和解密
ceph-deploy osd create --dmcrypt vm02:vdb,在硬盘驱动的上层加入dmcrypt模块
2.压缩
有损压缩和无损压缩,Ceph提供基于服务器端的无损压缩
1)对象网关
Zone用来表示一个独立的对象存储区域,Zone包含了桶,桶里依次存放了对象,Placement Target用于指定桶和对象的存储池,Ceph基于一个Zone的Placement Target来提供压缩功能
2)BlueStore
支持在线的压缩方式
压缩参数
压缩算法:lz4,snappy,zlib与zstd
压缩模式:None,Passive,Aggressive,Force
压缩比例:数据块压缩后的大小和原始数据大小的比例
最小blob大小:如果需要压缩的数据块小于该值,则不进行压缩,原文存储
最大blob大小:如果需要压缩的数据块大于该值,则会分成若干个数据块进行压缩
3)FileStore
依靠文件系统本身的压缩功能来提供压缩功能
例如可以使用Btrfs来作为存储后端
3.加密和压缩的加速
基于硬件的加速QAT
基于软件的加速ISA-L
八、QoS
1.前端QoS
虽然Ceph RBD目前还不支持QoS,但是OpenStack可以提供前端QoS
1)QoS参数
total_bytes_sec
read_bytes_sec
write_bytes_sec
total_iops_sec
read_iops_sec
write_iops_sec
2)问题
不能最大化利用系统资源,私有云情况下,在保证每个客户端QoS的前提下,要尽量使用所有系统资源
存储系统除了客户端读写操作,往往内部也有读写操作,比如定期的Scrub,在异常的情况下,往往不能满足前端QoS的需求
2.后端QoS
1)mClock
使用预留值或最小值、权重、上限值作为QoS Spec
基本思路:客户端提供QoS Spec给服务器端,服务器端根据QoS Spec选择合适的IO进行处理。首先选择满足预留值或最小值的客户端,如果都满足则按照权重进行选择,但是保证不能超过上限值
客户端是一个抽象的概念,可以是真实的客户端也可以是后端服务,如Scrub、Repair
前后端QoS在某些情况下不能充分使用存储系统而导致资源浪费,而mClock中的权重可以在满足预留值或最小值之后,充分利用存储系统的剩余资源
2)dmClock
是mClock的分布式版本,需要在每个服务器都运行一个mClock服务端
dmClock在OSD的实现
基于dmClock设计了新的队列,仅仅根据配置文件需要基于优先级、权重、dmClock选择相应的队列
dmClock客户端
分成两大类:客户端IO和OSD内部IO
保证内部OSD操作不影响正常IO操作,对于单用户的Ceph集群而言很重要
对于多用户或多应用不友好
以存储池或RBD Image为粒度,设置QoS Spec
需要基本来自RBD,基于存储池粒度可以将CephFS也考虑进去
粒度太大,由于Ceph没有中心节点的概念,如何做到精确控制也是一个需要考虑的问题
为每一个Ceph的用户设置QoS Spec
来自公有云,花多少钱买多少资源
不太适合私有云
3.问题
合理的参数:如何控制客户端IO和OSD内部IO,目前而言Ceph做的都不是太好,虽然有很多参数可以选择
IO大小:QoS是从IOPS角度考虑的,IO数据大小基本是16KB以下,对于大数据IO,比如64KB的数据用IOPS就不太友好
九、Ceph与OpenStack
Ceph块存储:Glance,Cinder,Nova
Ceph对象存储:Keystone,Swift
Ceph文件系统:Manila
十、Ceph性能测试和分析
1.集群性能测试
块存储性能测试:dd,fio,rbd bench
文件存储性能测试:Blogbench,Bonnie++,Dbench
对象存储性能测试:swift-bench
集群性能数据
2.Ceph组件性能
1)Ceph Perf Counters
ceph daemon <admin-socket> perf dump
ceph daemon <admin-socket> perf reset <name>
2)系统资源占用
组件内部
ceph daemon <osd-socket> dump_memtools
tcmalloc heap profiler
操作系统
oprofile
htop,iotop,iftop
3.Ceph集群性能
Ceph manager
Promethus
Zabbix
iostat
ceph osd perf
ceph osd pool stats
4.综合测试分析工具
1)CBT(Ceph Benchmark Tool)
集成radobench,fio-librbd,fio-kvmrbd,fio-krbd,COSBench,collectl
对Ceph集群的配置、部署、还原进行管理,还负责对测试数据结果的收集与归档
2)CeTune(Intel)
是一个基于网页的Ceph集群测试工具,对Ceph集群进行集中管理
集成了COSBench,vdbench,fio
5.高级话题
1)分层分析
LIBRADOS层
rados bench主要用于RADOS层的性能测试
rados load-gen可以更精细地控制读写对象的大小和读写比例
OSD层
ceph tell osd.0 bench
ObjectStore层
社区单独提供了fio测试引擎实现
设备层
netcat/nc,dd,iperf,fio
2)追踪
op-tracker,LTTng,blkin,OpenTracing API