别让bug跑了,通过问题理解ceph的克隆过程 荐

栏目: 服务器 · 发布时间: 6年前

内容简介:写在前面话题扯远了,回到这篇文章,文章的标题包含“复盘”,顾名思义,是对以前的发生的现象或问题进行回顾,学而不思则罔,目的第一是从问题中总结经验,最大化发掘它的价值;第二是不断锻炼自己分析问题的能力;最后是希望强化在某项知识上的运用能力,毕竟以今天分析昨天,有思维就ok了,但是以今天设想未来,需要长期深厚的积累才行。

写在前面

刚刚过去的9月,人工智能、云计算和物联网界热闹非凡,接连迎来了世界物联网博览会、世界人工智能大会和阿里云栖大会。2018世界物联网博览会就在家门口举行,抓了空去现场看展览,外行人看看热闹,有感于科技的日新月异给生活带来的便利。

话题扯远了,回到这篇文章,文章的标题包含“复盘”,顾名思义,是对以前的发生的现象或问题进行回顾,学而不思则罔,目的第一是从问题中总结经验,最大化发掘它的价值;第二是不断锻炼自己分析问题的能力;最后是希望强化在某项知识上的运用能力,毕竟以今天分析昨天,有思维就ok了,但是以今天设想未来,需要长期深厚的积累才行。

1 背景

云硬盘的快照、克隆,属于块存储RBD基本功能,在很多版本的openstack云平台中我们都使用过,之前我并没有太多关注这两块,保证功能能用、好用就过去了。

不过在最近的产品中,遇到几个与克隆或快照相关联的bug,涉及到rbd clone、rbd flatten等,正好是之前未遇到过,因此找了时间对产生的bug复盘,也是希望借bug观察ceph对克隆和快照的处理流程。

整篇文章分以下几小章节:

1 、背景

2 、bug回顾

3、 利用rbd_max_clone_depth触发flatten

4 、cinder和ceph层面对clone、flatten的实现

2 bug回顾

2.1  bug1 通过快照创建云硬盘,删除父快照失败

这个问题复现步骤很简单,如下流程图所示:

别让bug跑了,通过问题理解ceph的克隆过程 荐

遇到的问题就是在删除快照时发生失败,禁止该删除操作。

由快照创建出的云硬盘,一般情况与快照是父子关系,在ceph下通过rbd info或rbd children可以查询到链的关系。 如下图红色框中所示,在parent一项中,可以看到volume-8e81a7b0-4fdc-49b0-a9ed-4124c8e61f7d是volume-117078c1-c724-44b5-a271-e0f708e9d6b3下的快照克隆得来:

别让bug跑了,通过问题理解ceph的克隆过程 荐

图1

既然克隆盘与快照存在父子关系,要删除父快照的首要条件是斩断这种依赖关系,这个就需要通过 rbd_flatten_volume_from_snapshot配置项来实现,见/etc/cinder/cinder.conf配置文件,如下图中:

别让bug跑了,通过问题理解ceph的克隆过程 荐

在我们的云环境下, rbd_flatten_volume_from_snapshot=false,在false条件下volume和snapshot之间的关系是什么?

在解决bug之前,先来了解下 rbd_flatten_volume_from_snapshot在true、false下的不同作用,见下表:

别让bug跑了,通过问题理解ceph的克隆过程 荐

一目了然,在false条件下, volume和snapshot存在依赖,要想解决该bug,只要开启为true即可。

不过先别急着改/etc/cinder/cinder.conf,在此之前我们通过flatten手动解除依赖关系,再重复bug的步骤看是否能够成功,这个小实验分5个步骤复现,如下图3中:

别让bug跑了,通过问题理解ceph的克隆过程 荐

(1)创建volume和快照 PASS

(2)执行克隆 PASS

(3)删除父快照 FAILED

错误提示需要对快照先去除保护,unprotect后再执行删除快照,错误提示:cannot unprotect: at least 2 child(ren) [1a5e266b8b4567,1aa62d6b8b4567] in pool

(4)执行flatten操作,解除依赖 PASS

(5)再次删除父快照 PASS

小实验OK,证明了解除克隆盘与snapshot的依赖后再删除快照成功。如果在控制节点的cinder配置文件中,开启了rbd_flatten_volume_from_snapshot = true,则 由快照创建出的云硬盘,会自动合并,清除依赖关系,这样一来这个云硬盘就变为扁平的没有层级的volume。最后记得重启cinder服务,使其生效!

2.2  bug2 大容量的空盘创建快照,再通过该快照创建云硬盘,耗时过长

这个bug提的比较优秀,功能本身属于正常流程,但之前遗漏了大容量云硬盘这个场景,比如1T、2T。

问题复现步骤同bug1,只是少了删除快照的步骤,如下流程图所示:

别让bug跑了,通过问题理解ceph的克隆过程 荐

通常,我们在云平台上对云硬盘创建快照后,会同时创建快照卷,由于精简配置的属性,只需分配相对少量的存储空间即可,当再通过该快照clone出云硬盘,快照处于只读保护, 在cow的机制下,克隆操作会很迅速。下面引用一张ceph官方的图来解释:

别让bug跑了,通过问题理解ceph的克隆过程 荐

上图4中,parent是指源云硬盘的快照,而child是从快照克隆出来的云硬盘。

这个bug 2与“2.1 bug 1”对比,相同点都是由 rbd_flatten_volume_from_snapshot 造成的bug,不同的地方在于true和false。

在bug 2 的云环境下, rbd_flatten_volume_from_snapshot =true,在上文的bug1中曾说过解除volume和snapshot的依赖关系,取消这种依赖关系叫做flatten,这个flatten花费的时间和源云硬盘(volume)的大小成正比。

回到bug本身,内部在做排查时,依照以下的顺序:

(1)检查volume qos

眼光先放在了volume qos上,在有数据条件下,qos速率大小(比如write=40MB/S)肯定是会影响到快照创建云硬盘的速度的。转念一想,云硬盘是空盘,并不存在任何object,因此克隆速度应该是很快的。

(2)检查父云硬盘、快照、子云硬盘的实际容量

我们环境中云硬盘是空盘,不存在任何数据,同样的由快照创建出的新盘也不会有任何数据。实际是否如此,通过下面的验证步骤来证实一下:

  • 创建云硬盘和快照,并获取真实存储空间

  • 别让bug跑了,通过问题理解ceph的克隆过程 荐

图5

图5中,新建1G的volume,并创建该盘的快照后,rados查询实际存在的object,找不到任何数据,这是正确的。

  • 由快照创建云硬盘,并获取真实存储空间

别让bug跑了,通过问题理解ceph的克隆过程 荐

图6

图6中,快照创建出新的云硬盘,叫volume-d7199f3d-ed96-446a-83c8-25083a752e23,可以看到在云硬盘创建过程中,新的云硬盘和快照时父子关系,创建成功后,新的云硬盘和快照时父子关系被解除。

别让bug跑了,通过问题理解ceph的克隆过程 荐

图7所示是获取新的云硬盘的实际数据对象,发现已经存在256个object(父云硬盘总容量为1GB,根据order 22 (4096 kB objects)来切分)

别让bug跑了,通过问题理解ceph的克隆过程 荐

图8中,随机抽查几个object,发现其实这些object的容量都是0,并不存在真实的数据。一般而言,从快照创建云硬盘,代码实现很简单,先克隆再flatten,Fill clone with parent data (make it independent),此时flatten会将所有块从父节点复制到child,但父云硬盘中没有数据,flatten操作是不应该产生object的。

这个bug问题就在于flatten会对新建云盘的每一个对象进行一个写操作,从而创建无数个大小为0的对象,又在qos的限制下,所以耗时较长。最终解决方法就是:根据快照的object_map,跳过不存在的对象,只发送有数据的对象即可。

3 利用rbd_max_clone_depth触发flatten

麦子迈在《解析Ceph: Librbd 的克隆问题》一文中提到 “Librbd 在卷的克隆时会形成子卷对父卷的依赖,在产生较长的克隆依赖链后会有严重的性能损耗”。这个理论其实和cow下多快照产生的性能衰减是一样的,对ceph的云硬盘做快照,每次做完快照后再对云硬盘进行写入时就会触发COW操作, 即1次读操作、2次写操作,volume→volume的克隆本质上就是将 volume 的某一个 Snapshot 的状态复制变成另一个volume。

为解决在产生较长的克隆依赖链后会有严重的性能损耗问题,在OpenStack Cinder 的/etc/cinder/cinder.conf中提供一个参数,可以解除父子依赖关系,在超过自定义设置的阀值后选择强制 flatten。

别让bug跑了,通过问题理解ceph的克隆过程 荐

在图9中,通过 rbd_max_clone_depth来控制最大可克隆的层级。

rbd_max_clone_depth = 5 这个参数控制卷克隆的最大层数,超过的话则使用 fallten。设为 0 的话,则禁止克隆。

为了验证这个过程,下面我们做个实验,创建1个volume,命名为01,依次复制下,即由01复制成02,02复制为03,03复制为04,04复制为05,05复制为06,06复制为07,如下图流程图:

别让bug跑了,通过问题理解ceph的克隆过程 荐

实验预期结果,就是当从06复制到07时,满足rbd_max_clone_depth > 5,此时触发flatten操作。

别让bug跑了,通过问题理解ceph的克隆过程 荐

图10

别让bug跑了,通过问题理解ceph的克隆过程 荐

图11

图10、图11是 复制云硬盘后的查询到克隆盘信息

别让bug跑了,通过问题理解ceph的克隆过程 荐

图12

图12中, 上面的log记录了复制07时,触发了flatten操作,对上级云硬盘06执行flatten操作,开始执行合并。

别让bug跑了,通过问题理解ceph的克隆过程 荐

图13

图13所示是Flatten成功后,可以看到云硬盘06 的parent一项消失,此时在页面上可以删除云硬盘06

4 cinder和ceph层面对clone、flatten的实现

现在市面上很多讲ceph的书(大多数翻译自ceph中国社区之手),在RBD块存储章节都会对快照、克隆等操作花很多篇幅去描述,基本都是在rbd层通过命令一步步分解rbd clone过程来讲原理。

对于类似我这样的刚接触ceph不久的人来说,知识点分散在各处,看了前面忘了后面,很难在脑子里建立完整的概念,当然主要原因还是自己太菜了,迷雾重重看不透!

别让bug跑了,通过问题理解ceph的克隆过程 荐

言归正传,我只是想大概的了解下对云硬盘执行操作在底层是如何实现的,因此还是由上文中提到的小处(bug)来入手,自顶向下先设计一个思考流程,带着目标按照这个从上到下的顺序去理解,如下图所示:

别让bug跑了,通过问题理解ceph的克隆过程 荐

4.1  从快照克隆卷的流程

(1)openstack cinder

自顶向下,先从cinder层入手,通过代码可以看到从快照克隆出volume的思路,从本质上讲,快照克隆出新的卷,也是volume create的性质,所以先来了解下volume create过程

cinder:/cinder/api/v2/volumes.py

别让bug跑了,通过问题理解ceph的克隆过程 荐

volumes.py中def create方法我省略了很多,主要就是通过req、body的参数来获取创建volume所需要的参数,根据不同参数来发送具体的创建volume请求,因为我是从快照来创建,snapshot id自然必不可少,在 volumes.py最后实际调用new_volume = self.volume_api.create()去实现。

cinder:/cinder/volume/api.py

经过volume_api.create(),在/cinder/volume/api.py来处理前端发来的卷相关的所有请求,通过create_what{}表示volume的实现参数,然后分别就调用cinder.scheduler的scheduler_rpcapi,cinder.volume的 volume_rpcapi建立创建volume的工作流:create_volume.get_flow

别让bug跑了,通过问题理解ceph的克隆过程 荐

注:关于create volume flow的流程及具体实现,见/cinder/volume/rpcapi.py:def create_volume(),/cinder/volume/flows/api/create_volume.py,本篇省略过程

cinder:/cinder/volume/manager.py

对于api来讲,只是做到处理前端发来的卷相关的所有请求,具体实现交由manager下的去完成,rpcapi调用inder/volume/manager.py:def create_volume()去操作

别让bug跑了,通过问题理解ceph的克隆过程 荐

执行中发现crate voluem 有snapshot id,然后调用/cinder/volume/flows/manager/create_volume.py下的私有方法_create_volume_from_snapshot()

别让bug跑了,通过问题理解ceph的克隆过程 荐

最后根据配置文件指定的RBD后端请求/cinder/volume/drivers/rbd.py的create_volume_from_snapshot()

cinder:/cinder/volume/drivers/rbd.py

众所周知,一般cinder使用RBD驱动来对接底层的后端存储(比如ceph、xsky),在openstack cinder层面最终交由create_volume_from_snapshot()实现,因为是通过快照来创建volume,还需要调用私有方法_clone(),满足条件的话,还要调用_flatten()和_resize()。

别让bug跑了,通过问题理解ceph的克隆过程 荐

(2)librbd

经历多方接力才结束在cinder层面的流程,这还不算完,真正要实现create volume from snapshot的创建,核心在调用ceph执行。

ceph:/src/pybind/rbd/rbd.pyx

别让bug跑了,通过问题理解ceph的克隆过程 荐

/ceph/blob/v10.2.3/src/librbd/librbd.cc

别让bug跑了,通过问题理解ceph的克隆过程 荐

在librbd中对外提供api在class RBD中,从librbd.cc函数中看到有多个clone()、clone2()、clone3()函数,区别在于根据传入的不同参数来调用对应的函数,但这些函数都不像是具体的功能实现,只是一些相关参数传值。

再看看/ceph/blob/v10.2.3/src/librbd/internal.cc函数,同librbd.cc一样,对应的clone()也是3种,因为篇幅如下展示的是clone3()函数(实际命名并不如此,通过参数来区分得知是clone2):

别让bug跑了,通过问题理解ceph的克隆过程 荐

将librbd.cc、internal.cc两个函数联系起来看,librbd.cc只是定义了对外的各种函数接口,接口的具体实现,调用的还是internal.cc中定义的函数内容。

总结一下,根据自己的理解将整个流程绘成图,如下图所示中,需要一提的是,我没有涉及到librados的实现过程,因为clone等volume的操作,librbd可以说就是rbd的完整实现,rados只是作为后端的存储

别让bug跑了,通过问题理解ceph的克隆过程 荐

4.2  flatten的流程

在前文“ 利用rbd_max_clone_depth触发flatten”小节中,我们描述了一个volume clone的过程,通过cinder.conf的一个参数,当满足rbd_max_clone_depth最大层数后,触发flatten操作,下面我们通过代码去看一看具体实现的流程。

(1)openstack cinder

对于上层云平台而言,从云硬盘1克隆出云硬盘2,或者从快照创建云硬盘,一般是能够触发flatten操作的主要场景,其实两者实现原理基本一致。

因此,和之前的由snapshot来实现创建新的云硬盘一样,首要都是从create()开始,只是参数不同,克隆盘在create过程先要获取parent volume id

别让bug跑了,通过问题理解ceph的克隆过程 荐

之后也是一样经历api→manager→driver的过程,这里省掉重复的过程,直接看cinder调用rbd驱动对克隆云硬盘的实现代码,如下图中/cinder/volume/drivers/rbd.py:

别让bug跑了,通过问题理解ceph的克隆过程 荐

调用了私有方法_get_clone_depth()来判断depth,调用_flatten()来实现flatten操作,当然flatten过程经历一系列过程,在parent volume上创建snapshot,对snapshot加保护、再执行clone,然后flatten,这个过程一样可以通过rbd 命令来完成。

(2)librbd

创建RADOSClient,连接到ceph rados,这里也是先调用clone()去执行,再触发flatten()操作,和我预期不同,flatten的过程比想象中还要复杂,才疏学浅,对整个过程的了解还需要更多的时间,只能先用根据自己的理解画出一张流程图表示一下:

别让bug跑了,通过问题理解ceph的克隆过程 荐


以上所述就是小编给大家介绍的《别让bug跑了,通过问题理解ceph的克隆过程 荐》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Perl入门经典

Perl入门经典

[美]Curtis "Ovid" Poe / 朱允刚、韩雷、叶斌 / 清华大学出版社 / 2013-9-20 / 78.00

作为最有影响力的编程语言之一,Perl被广泛用在Web开发、数据处理和系统管理中。无论是Perl新手,还是想要加强自己实战技能的Perl程序员,《Perl入门经典》都提供了处理日常情况所需的各种技术。凭借十多年的Perl经验,作者Curtis“Ovid”Poe一开始先简单回顾了Perl的基础知识,然后以此为出发点,举例说明了Perl在工作场所中的各种真实用法。此外,书中还包含了一些动手练习、宝贵建......一起来看看 《Perl入门经典》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具