nova、cinder的snapshot与ceph相关交互




其实这两块代码已经看过很多遍了,但是经常忘记,而且经常有同事问起来,每次都要翻一遍代码,因此决定整理下相关交互流程,后续备查。(注:仍然是基于Mitaka版本分析源码,Queens版本粗略看了下改动不大)

先说nova部分,nova的snapshot主要是针对系统盘的(root disk),相关命令行是:

从nova源码来看,backup和image(snapshot)的区别只是多了个rotation的概念,多出的这个概念主要是用来限制备份数量的(超过这个数量的backup会被滚动删除,肯定是先删除最老的),你如果把rotation设置的很大,那它就跟image没什么区别了,nova后端的代码也是一套(api入口不一样,但是到了nova compute manager那层就没什么区别了)

从上面源码可见二者调用的具体实现没有区别。

_snapshot_instance调用了libvirt driver的snapshot方法,这里面区分了live和cold的snapshot类型,并且还区分了direct snapshot和外部快照,ceph后端是用的direct snapshot,也即通过ceph的rbd image相关api来做快照。

可以看出经过了创建临时snapshot(还在nova系统盘的pool)、在glance pool中clone snapshot出新rbd卷(跨pool clone卷)、flatten(clone的新卷与snapshot解除关联)、删除临时快照(清理临时资源)、glance pool中的rbd image创建snapshot,此snapshot就是生成的云主机(虚拟机)系统盘的快照(新的镜像,或者叫自定义镜像、捕获镜像、镜像模板等,总之就是nova image-create生成的东西,可以用glance image-list看到),也就是说glance中的image(不管是管理员上传的image还是nova image-create制作的image,都是snap)对应的是rbd里面的一个snap而不是实际的卷,这样创建新的云主机(虚拟机)的时候,系统盘直接从snap clone一个rbd卷就好了,由于支持COW,因此实际clone过程中数据copy量极少、创建系统盘卷速度特别快(这也是glance镜像在有云主机使用的情况下不能删除的原因)。

rbd snapshot的原理可以参考前同事的一篇文章:http://www.sysnote.org/2016/02/28/ceph-rbd-snap/

direct+live snapshot场景下,创建临时snapshot过程中,由于云主机一直运行中,因此可能有部分数据还在内存的磁盘缓存中,没有刷新到磁盘,所以还是有一定概率导致制作的系统盘快照是损坏的。

上面是ceph后端的流程,本地存储后端的snapshot流程可参考之前的文章:Mitaka Nova在线快照数据丢失问题及解决方法

nova这边其实还有一种需要跟cinder(ceph)交互的功能,boot-from-volume,从卷启动云主机(虚拟机),这种情况下cinder list里面看到的volume是bootable的,不过这种功能在ceph后端场景下不常用,就不介绍了。

接下来是cinder部分,涉及的命令行应该有create、backup-create、snapshot-create这几个(还有没有其它的不确定,估计应该没了):

先看create,创建卷,支持多种参数,比如创建裸卷、从snapshot创建卷、从已有的volume创建卷等。

上面忽略了很多taskflow,直接到了cinder.volume.flows.manager.create_volume.CreateVolumeFromSpecTask#execute,cinder里面用到的taskflow一般都是linear类型的,顺序执行,只要一个一个看过去就行了,一般都包含一个参数解析的task,如cinder.volume.flows.manager.create_volume.ExtractVolumeSpecTask,解析出来的参数传递给下一个task使用,最后run起来,正常执行execute,有异常的话就执行revert方法。关于OpenStack的taskflow介绍:https://docs.openstack.org/taskflow/latest/

创建卷的api文档(v2版本,v3也类似):https://developer.openstack.org/api-ref/block-storage/v2/index.html#create-volume

跟snapshot相关的主要是_create_from_snapshot和_create_from_source_volume,先看第一个:

共3步,从snapshot clone新卷、flatten、resize,后面两步不是必须步骤。配置项rbd_flatten_volume_from_snapshot,

从snapshot创建卷的时候是否flatten,默认是False,不flatten。

再看_create_from_source_volume,它调用的是create_cloned_volume,

这个流程比较多,毕竟要先做一个snapshot,然后再clone新卷,相当于包含了从snapshot创建卷的流程。配置项rbd_max_clone_depth,

默认最大clone深度是5层,达到5层就flatten。

再看下backup操作(其实这个操作跟rbd snapshot没啥大关系),cinder.backup.drivers.ceph.CephBackupDriver#_backup_rbd这里是最终执行的方法,就不具体分析了,主要是有个增量备份过程:

先用’rbd export-diff’导出增量部分,再用’rbd import-diff’导入。参考:https://ceph.com/geen-categorie/incremental-snapshots-with-rbd/

第一次备份的话是走全量备份过程:

 

最后看下snapshot create,这个流程跟create创建卷流程类似,直接看最终rbd调用就行了:

非常简单,就创建snap,然后protect。