极限操作,力挽狂澜
写在前面
松鼠哥的ceph专业课程上线啦!
面向新手同学,从0实战,全面入门ceph安装部署与运维,有需要的同学赶紧扫码订购吧:
不知不觉,又到年底啦。
回顾今年,技术能力的增进和文章的产出均不达预期,太懒了,还有我那迟迟未能完成的书稿,哎,真是羞愧万分,来年一定要再接再厉,更加勤奋!
这两年大环境寒气逼人,但是我们天翼云科技这边继续热情如火地招聘!年底了,懂的都懂,有意向的老铁赶紧私聊,投投简历,不说别的,跟松鼠哥同坐17楼当同事这点就足够吸引了吧,come on ~
回到本篇,不管是各种搜索引擎还是官方,暂时没有找到对ceph删除存储池进行恢复的相关文章,官方是完全不支持的,但是,松鼠哥从不走寻常路!
本篇主要从操作的角度,讲解如何手动恢复一个被删除的存储池,由于仅使用默认配置和操作并不能保证100%恢复所有的数据,因而,松鼠哥准备了下篇,将深入代码,了解更多的细节,尝试实现100%恢复被删除存储池的数据
测试版本为ceph 14.2.22,目标存储池使用块存储,三副本模式(其实在rados都是一样的)
开始
首先,我们看下集群的状态
1 | data: |
PG都是正常的,rbd这个存储池是本次测试的池,pool id 是36
1 | [twj@test-cluster ~]$ sudo ceph df |
没有问题,接下来,我们开始前记录几个数据,一个是当前集群的osdmap版本,另外是rbd这个存储池的数据情况,方便我们后面恢复后进行比对
1 | [twj@test-clustern ~]$ sudo ceph osd dump|more |
OK,接下来我们将rbd这个存储池删除
1 | [twj@test-cluster ~]$ sudo ceph daemon /run/ceph/ceph-mon.`hostname`.asok config set mon_allow_pool_delete true |
删除成功后,我们快速将这个pool对应的所有osd都stop掉
1 | [twj@test-cluster ~]$ sudo systemctl stop ceph-osd.target |
将osd立刻stop,是为了尽可能保住rbd这个存储池的数据
接下来,不管是rados命令还是ceph命令,都已经无法查看到对应的pool,其所在的pg也都无法查询到,osdmap中也无法查看到,留意到集群的osdmap版本从22222增长到了22228
1 | [twj@test-cluster ~]$ sudo rados lspools |
开始恢复
首先,如果存储池及其pg在rados命令和ceph命令都无法查看的情况下,对该存储池是完全没有办法操作的,这就完全没有操作空间!
因此我们第一步,就是要让集群重新**”看到”**这个存储池及其pg!
那,已经删掉的存储池,集群又如何才能看到呢?
这就关系到,集群是如何知道当前有哪些存储池,也就是说,肯定有个地方,记录了存储池的信息!!!
这个地方,就是集群的osdmap!
细心的读者朋友肯定会发现,当我们使用ceph osd dump|more
的时候,是可以看到osdmap中记录了pool信息的
1 | [twj@test-cluster ~]$ sudo ceph osd dump|more |
显然从require_osd_release
字段开始,记录的就是存储池的信息
这样一来,让集群重新**”看到”被删掉的存储池,就变得简单了,我们将osdmap的版本看作是一个时间序列,每当集群发生一次变更,它就会记录一次,版本号增长一,那么我们要做的,就是让集群回到过去,这就用到了松鼠哥之前的骚操作:回滚集群的osdmap**
回滚集群的osdmap
回滚集群的osdmap,松鼠哥在之前的文章**”纸糊集群急救实录”**中首次使用,感兴趣的读者朋友可以再去看看,这里就直接开搞了
1 | [twj@test-cluster ~]$ sudo ceph-kvstore-tool rocksdb /var/lib/ceph/mon/ceph-test-cluster/store.db/ list|grep osdmap|more |
不多说,用脚本直接弄
1 |
|
三个mon都弄完后,启动起来,查看集群的osdmap,确认已经回滚成功,重要的是,此时集群已经可以在osdmap中看到被删除的rbd pool
1 | [twj@test-cluster ~]$ sudo ceph osd dump|more |
注意到,rados命令是可以看到rbd这个pool的,而ceph df命令则不行
1 | [twj@test-cluster ~]$ sudo rados lspools |
rbd命令则一直卡住,意料之中,因为ceph命令无法看到pool且pg也看不到,pool当然访问不了
1 | [twj@test-cluster ~]$ sudo rbd ls |
怎么办呢,osdmap看到了pool,但是完全没法操作,也没用,所以接下来我们要让集群可以看到这个rbd pool的pg
恢复存储池的pg
猜测,pg具体是分布到osd上面的,如果仅仅是集群看到pool,也是异常的,因为osd没法上报自己的pg情况,osd为什么不上报自己的pg情况呢?
当然是因为,当前集群的osdmap版本,大于所有osd的osdmap版本,这种情况下,mon与osd是无法交换信息的,因为osd接收到比自己版本更低的osdmap时,会直接丢弃!
所以接下来,我们要让集群的osdmap版本大于osd的osdmap版本,让集群恢复正常
老办法,使用out/in的方式
1 | [twj@test-cluster ~]$ for x in $( seq 1 10 );do sudo ceph osd in 1115;sudo ceph osd out 1115;done |
ok,osdmap版本拉高了,osd也可以正常与mon通信了,但是pg貌似还是看不到!
没道理啊,为啥不行呢。。。
很有可能,是可能啊,需要一个触发条件,这个条件,可以触发pg的重新检查,于是,我们手工操作一下,重新创建一个rbd pool的pg
1 | [twj@test-cluster ~]$ sudo ceph osd force-create-pg 36.5d --yes-i-really-mean-it |
啊哈哈!成了!能看到rbd池的所有的pg了!即便它,是incomplete状态的
1 | data: |
ceph df也能够看到pool了
1 | [twj@test-cluster ~]$ sudo ceph df |
那就直接获取到所有的pg,进行recreate,这一步是为了激活/找回所有的pg(因为存储池被删除后,pg就会开始被销毁,被销毁的pg如果不使用recreate,是没有办法找回来的,会一直都在unknown状态)
1 | [twj@test-cluster twj]$ sudo ceph pg dump|grep -E "^36" |awk '{print $1}' > rbd.pg |
重新创建完后,貌似没什么变化
转眼一想,如果要将一个所有pg状态都是incomplete状态的pool恢复正常,就要来点硬的,手工mark complete!
那么,对pg进行mark complete
1 | + allpgs=`cat rbd.pg` |
全部处理完后,我们重新启动该pool的所有osd,过了一会,集群完全恢复正常!
1 | data: |
此时,我们验证一下rbd这个pool的数据
1 | [twj@test-cluster ~]$ sudo ceph osd dump|more |
两个rbd块都还在,但是,rbd这个池里面的对象减少了很多!损失率是
(5119504-5086543)/5119504*100 = 0.643%
看起来,99%以上的数据还算是保住了!
总结
虽然不完美,有数据损失,但是恢复被删除的存储池,理论上、实际上都是行得通的!
一顿操作猛如虎,其实很多地方都是理论的推导和多次实验得出来的,当然,希望读者朋友们,都用不上~
本次操作,删掉rbd pool后,在几秒钟后立刻停掉了关联的osd,使得osd无法继续进行数据回收,这个是保住数据的关键!
由此可见,要想100%保住数据,操作上,几乎不可能,最关键的就是控制osd对被删数据的回收,即使立刻采取措施,也很难做到完全不丢数据,最好的办法,就是在代码中设置一个变量,然后通过控制变量来控制回收,甚至禁止回收,手动触发回收等等,这些内容,将在下篇讨论
封控在家不易,如果本篇所述对你有所帮助,就请给松鼠哥赏杯咖啡吧^_^
- 本文作者: 奋斗的松鼠
- 本文链接: http://www.strugglesquirrel.com/2023/01/17/重磅!独家!恢复已删除的存储池/
- 版权声明: 本博客所有文章除特别声明外,创作版权均为作者个人所有,未经允许禁止转载!