resharding
工作中存储集群使用了 Ceph 技术,所用的是版本是 Luminous 12.2.4,因为刚刚上手 Ceph,不少概念和问题也都是头一次听说,比如这次的自动分片(auto resharding)。不得不说,Ceph 对象存储目前还是不够完善,Luminous 对于 bucket 中存储大量数据的支持还是不够理想,这造成了不小的使用不便。虽然 Ceph 在着手解决,但还没有达到足够理想的状态。
1. 自动分片的影响
这个问题也是由于同事无法继续上传文件才发现的,具体的现象是上传文件超时,不过下载文件还是正常的。
[put object] ----> object=xxxx file=xxxx Traceback (most recent call last): File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 387, in _make_request six.raise_from(e, None) File "<string>", line 3, in raise_from File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 383, in _make_request httplib_response = conn.getresponse() File "/usr/lib/python3.6/http/client.py", line 1331, in getresponse response.begin() File "/usr/lib/python3.6/http/client.py", line 297, in begin version, status, reason = self._read_status() File "/usr/lib/python3.6/http/client.py", line 258, in _read_status line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") File "/usr/lib/python3.6/socket.py", line 586, in readinto return self._sock.recv_into(b) socket.timeout: timed out
在 ceph 的日志文件中反复出现如下提示:
0 block_while_resharding ERROR: bucket is still resharding, please retry0 NOTICE: resharding operation on bucket index detected, blocking
这里的提示就很清楚了,bucket 正在进行分片,所以阻塞了写入操作。但这一阻塞就是好几天,实在是不能接受啊,还是要进一步了解一下,为什么要进行分片,以及为什么会出现长时间不能写入的问题。
2. 自动分片简介
在网上查找了一下 Ceph 对象存储 bucket 自动分片,Ceph 的官方文档(New in Luminous: RGW dynamic bucket sharding)解释的很清楚,我没有找到对应的中文文档,为了节省大家的时间我把这篇文章翻过来,贴在这里。
2.1 Luminous 中新增功能:RGW 动态 bucket 分片
RGW 在 Luminous 版本中新增了自动管理 bucket 索引分片的功能,完全自动化了 RGW 内部索引对象的管理,在此之前,为了避免用户在一个 bucket 里存储大量数据而造成性能和可靠性的问题,这可是 Ceph 管理员们要花费大量精力来规避的。
2.2 背景
在开发 Ceph 新功能时,我们考虑的最重要的设计需求就是可扩展性。Ceph 从最开始就是支持水平扩展的,所有的新功能也必须都符合这个特性。在设计所有 Ceph 模块(包括 mon,osd,mds,rgw 等)时,我们都秉承着该哲学。当资源耗尽时,Ceph 应当允许新增资源,并提升整个集群的性能。
RADOS(Ceph 底层的对象仓库)的一个特性是不保存系统的全部对象的索引,而是使用 CRUSH 算法,通过对象的名字、集群的配置和状态来计算存储位置。这大大提高了 Ceph 的扩展性,总的 IO 能力会随着系统中 OSD 的数量增加而增加,原因是在进行 IO 操作时,不需要查询全局的元数据。
然而,RGW 还是为每个 bucket 维护了一份索引,里面保存了 bucket 中全部对象的元数据。RGW 本身并没有足够有效的遍历对象的能力,所以在处理请求时,这些索引数据非常重要,比如遍历 bucket 中全部对象时。bucket 索引信息还有其他用处,比如为版本控制的对象维护日志、bucket 配额元数据和跨区同步的日志。bucket 索引不会影响对象的读操作,但确实写和修改确实会增加一些而外的操作。
这隐含了两层意思:其一,在单个 bucket 索引对象上能存储的数据总量有限,默认情况下,每个 bucket 是只有一个索引对象的,所以每个 bucket 中能存储的对象数量就是有限的了。超大的索引对象会造成性能和可靠性的问题,极端情况下,可能因为缓慢的恢复操作,造成 OSD 进程挂掉。其二,这成了性能瓶颈,因为所有对同一 bucket 的写操作,都会对一个索引对象做修改和序列化操作。
在Hammer 版本中,新增了 bucket 分片功能来解决 bucket 中存储大量数据的问题,bucket 的索引数据可以存储在多个 RADOS 对象上了,这样 bucket 中存储对象的数量就可以随着索引数据的分片数量的增加而增加了。但这只对新建的 bucket 有效,而且需要有提前的规划,要提前知道 bucket 最终会存储多少数据。后来我们增加了 bucket 分片管理命令(最早是在 Kraken 版本里,后来移植到了 Jewel 和 Hammer),允许修改 bucket 索引分片数量来缓解这个问题。但分片还是出现问题后的补救措施,而且在分片时无法进行写操作(这可能并不方便,甚至不可行)。
2.3 动态 bucket 分片
Luminous 最终引入了动态 bucket 分片,现在随着存储对象的增加,bucket 可以自动分片了。而且,还不会影响 bucket 的 IO 操作(不过在有些并发操作会有延迟)。RADOSGW 进程会自动发现需要进行分片的 bucket,并安排进行分片。有个专门的进程来负责处理这些分片操作。
2.4 配置
这项功能是默认打开的,无需操作,管理人员不再需要考虑实现细节。
将变量 rgw dynamic resharding 设置为 false(默认为 true),关闭自动分片;每个分片可存储的对象数量由该变量控制,rgw max objs per shard,默认是十万;自动分片线程扫描的间隔可以通过 rgw reshard thread interval 选项配置,默认为十分钟。
以下是几个新命令,用于监控或控制正在进行的分片操作。
手动进行分片:
$ radosgw-admin reshard add --bucket=<bucket> --num-shards=<num_shards>
查找全部规划中的分片操作:
$ radosgw-admin reshard list
手动执行规划的分片操作:
$ radosgw-admin reshard process
取消规划中且未开始的分片操作:
$ radosgw-admin reshard cancel --bucket=<bucket>
2.5 结论
用户是不应当考虑内部分片索引的,终于,在 Luminous 实现了这点。这是诸多 Ceph 改善简易性、易用性和自动化努力的结果。
3. 自动分片的 bug
读过官方文档后,感觉这真是一个很赞的功能,不过新功能往往也意味着 bug 多,这次似乎也没有例外。我司的 Ceph 集群里,一个 bucket 存储的对象已经达到十二万了,触发了自动分片,这没有问题,不过分片操作已经进行了快三十六个小时,还没有结束,而且 bucket 的写操作完全被阻塞了,就像第一节中描述的那样。这和官方文档描述的很不一致啊。实在没有办法,只能建议使用的同事新建一个 bucket 了。
搜了一下 ceph 的相关问题,确实其他人也有遇到,而且目前尚未解决,所以建议正在使用 Ceph 各位小伙伴,谨慎使用该功能,同时要手动监控和维护 Ceph bucket 中存储的对象数量。也许在 Mimic 版本就可以真正的实现 Ceph 无需人为干预的愿景了。
作者:blackpiglet
链接:https://www.jianshu.com/p/583d880b8a15