分布式存储ceph:Qos

时间:2024-03-16 15:44:08

QoS最早起源于网络通信,是指一个通信网络能够利用各种基础技术,为特定应用提供更好的服务能力。简单来说就是如何设置规则,共享资源。随着Ceph的成熟,特别是在OpenStack将Ceph作为存储后端之后,Ceph的QoS就变得更加重要了。

 

前端QoS

前端QoS是指在客户端实现QoS,是最简单、最常用的,我们以OpenStack Cinder+ Ceph RBD为例进行说明。

虽然Ceph RBD目前还不支持QoS,但是OpenStack可以提供前端QoS,它提供如下参数。

· total_bytes_sec:虚拟机每秒允许读/写的总带宽。

· read_bytes_sec:顺序读带宽上限。

· write_bytes_sec:顺序写带宽上限。

· total_iops_sec:虚拟机每秒允许的总IOps。

· read_iops_sec:随机读IOps上限。

· write_iops_sec:随机写IOps上限。

这些参数可以简单地控制IOps和带宽,并根据读/写进行细分。但是在客户端实现QoS有以下问题。

· 不能最大化利用系统资源。对于目前的公有云,前端QoS可以很好满足需求,只要客户的QoS不超过存储系统提供的资源。即使一段时间内只有这个客户自己在使用,公有云服务商也不会将客户的QoS升级。但是在私有云情况下,在保证每个客户端QoS的前提下,要尽量使用所有系统资源。

· 存储系统除了客户端读/写操作,往往内部也有读/写操作,比如定期的Scrub、Repair、故障时的恢复等。如果QoS在前端,在异常情况下,往往不能满足需求。

 

后端QoS

2007年Sage等提出在ObjectStore这一层支持QoS。当时ObjectStore的文件系统是EBOFS——Ceph最早的本地文件系统。实现原理是在EBOFS的磁盘调度队列中引入客户端的信息。采用基于权重的轮询方式调度I/O。这种方式存在的问题在于,过于与EBOFS融合,无法做到迁移,比如XFS、Btrfs、BlueStore或KVStore。所以这个方案没有被采用。

正是考虑到QoS的实现要灵活,所以才会有基于OSD的dmClock。由于dmClock是基于mClock的,所以先简单了解一下mClock的原理。

 

mClock

mClock是基于时间标签的I/O调度算法,由VMware于2010年在OSDI的论文mClock: handling throughput variability for hypervisor IO scheduling中提出,是用于集中式管理的存储系统。mClock使用预留值或最小值(Reservation)、权重(客户端共享I/O资源的比重,满足所有客户端预留值或最小值之后按照这个分配系统剩余资源)、上限值(Limit,任何时候都不要超过该值)作为QoS Spec(Quality of Service Specifications)。客户端必须提供预留值或最小值、权重、上限值,服务器端根据输入参数进行调度。

算法的基本思路是:客户端提供QoS Spec给服务器端,服务器端根据QoS Spec选择合适的I/O进行处理。首先选择满足预留值或最小值的客户端,如果都满足则按照权重进行选择,但是保证不能超过上限值。

在论文中,给出了3个公式:

分布式存储ceph:Qos

其中,ri、wi、li表示客户端i的QoS Spec值。表示客户端i最近一次被服务器作为Reservation类执行I/O的时间戳,1/ ri表示步长(ri即IOps,只要满足在1/IOps执行一次I/O,就会满足IOps),t表示当前系统时间戳。如果>t,那么表示客户端i的预留值或最小值已经满足。将第一个I/O系统时间戳作为其时间戳。如果所有客户端的预留值或最小值满足,那么就会根据权重进行选择。

权重比较特殊,是相对时间值的。我们只关注I/O之间的W大小,而不关注与系统时间戳的关系。但是新的客户端加入时第一个W肯定是系统时间戳。这样客户端的W标准不一致会造成有些客户端达不到调度,所以需要进行调整。遍历所有客户端,找到最小的W值。当前所有W均减去最小值,然后选择最小的W(权重越大,分到的相应IOps也就越大,那么1/w就越小)。

相比较前后端QoS,mClock考虑的因素就更充分了。

· 客户端是一个抽象的概念,可以是真实的客户端也可以是后端服务,如Scrub、Repair等。

· 前后端QoS在某些情况下不能充分使用存储系统而导致资源浪费,而mClock中的权重可以在满足预留值或最小值之后,充分利用存储系统的剩余资源。

 

dmClock

dmClock是mClock的分布式版本,需要在每个服务器都运行一个mClock服务端,将QoS Spec分到不同的服务器共同完成。其公式为

分布式存储ceph:Qos

 

上面的公式是针对某个服务器的。其中,pi和qi是包含在I/O命令中的信息。因为分布式系统中存在多个服务器,发往同一个服务器的两次I/O之间其他服务器可能已经完成了预留值或最小值,所以需要服务器将每次I/O完成调度信息后基于预留值或最小值,以及权重返还给客户端,客户端分别叠加(pi和qi),包含在I/O命令中发送给服务器。服务器根据这些信息和上面的dmClock公式选择预留值或最小值和权重模式,以及是否已经达到上限值。

 

dmClock在OSD的实现

QoS后端的实现应该与Ceph代码松耦合,做成插件的形式。dmClock的本质是在I/O队列中选择符合条件的I/O,所以最简单的方式就是设计新的I/O队列。由于OSD内部已经存在这样的I/O队列(基于优先级和权重),所以就基于dmClock设计了新的队列,仅仅根据配置文件需要基于优先级、权重、dmClock选择相应的队列。

OSD的I/O队列在内部也是进行分组的(根据PG进行分组),并没有存在一个统一的I/O队列。所以在同一个OSD内部mClock也可能是dmClock。

 

dmClock客户端

如前所述,mClock是C/S架构,需要客户端提供QoS Spec。对于dmClock的客户端,其客户端不仅要提供静态的QoS Spec,而且还要根据服务器的返回结果,实时生成动态的QoS Spec传递到服务器。目前客户端的设计还没有最终定稿,但是有以下3种方案可供选择。

· 分成两大类:客户端I/O和OSD内部I/O(或继续分类,如replicated OP、Scrub、Recovery等)。

· 以存储池或RBD Image为粒度,设置QoS Spec。

· 为每一个Ceph的用户设置QoS Spec。

3种方案有利有弊。第一种方案的优点是保证内部OSD操作不影响正常I/O操作,对于单用户的Ceph集群而言这是很重要的。因为社区很多人都提到过Recovery或Backfill会影响正常I/O操作,从而导致延时严重变长。缺点是对于多用户或多应用不友好。

第二种方案可能考虑到QoS的需求目前基本来自RBD,基于存储池的粒度可以将Ceph FS也考虑进去。缺点是粒度太大,而且如果是基于存储池,由于Ceph没有中心节点的概念,那么如何做到精确控制也是一个需要考虑的问题。对于RBD来说这个问题基本没有,因为目前基本只有一个客户端读/写,这个客户端类似于中心控制节点。

第三种方案是来自公有云的,花多少钱买多少资源。缺点是不太适合私有云。

至于选择哪一种方案(或全部实现,然后采用参数来选择具体的方案),目前还没有结论。

总结来说,对于Ceph的QoS来说,主要存在以下两个问题。

1)合理的参数

dmClock前提就是提供预留值或最小值、权重、上限值的,无论哪种客户端,给出合理的QoS Spec都是很难的,特别是私有云项目,既要考虑不同应用的需求,又要充分使用系统。举一个最简单的例子,如何控制客户端I/O和OSD内部I/O,目前而言Ceph做的都不是太好,虽要考虑不同应用的需求,又要充分使用系统。举一个最简单的例子,如何控制客户端I/O和OSD内部I/O,目前而言Ceph做的都不是太好,虽然有很多参数可供选择。

2)I/O大小

QoS是从IOps角度来考虑的,I/O数据大小基本是16KB以下。那么对于大数据I/O,比如64KB的数据用IOps就不太友好,所以需要考虑I/O数据大小的因素。