记录cephfs 元数据灾难性恢复失败

概述
当cephfs中元数据池发生灾难性异常(例如双副本情况下,两个硬盘同时损坏,或者异常导致元数据osd无法正常启动),此时ceph文件系统因为元数据不完整,将不会对外提供服务。ceph官网中提供cephfs-data-scan等工具恢复元数据,本文按照官网步骤及网上提供相关步骤进行恢复,得到结果与预期不一致,特此记录,老铁遇到类似情况可指导下。测试ceph版本为12.2.11
参考https://www.it610.com/article/1275625924221485056.htm
https://docs.ceph.com/docs/luminous/cephfs/disaster-recovery/
创建文件系统初始化

ceph osd pool create metadata_pool 64  64 replicated cache_rule(cache_rule为ssd)
ceph osd pool create data_pool  256 256
ceph fs new cephfs metadata_pool data_pool
systemctl start ceph-mds.target

在这里插入图片描述
挂载客户端,注入测试数据

ceph-fuse -n client.admin -m 10.10.0.7 –key=AQDncgVfX4NDChAA4yAy6AmbK6YbfLha3zGA7w== /mnt/cephfs
mkdir -p /mnt/cephfs/a1/a2/a3/a4
echo hello1>/mnt/cephfs/1
echo hello2>/mnt/cephfs/a1/2
echo hello3>/mnt/cephfs/a1/a2/3
echo hello4>/mnt/cephfs/a1/a2/a3/4
umount -l /mnt/cephfs

模拟故障
将metadata_pool中所有obj删除,重启mds

for i in rados -p metadata_pool ls;do rados -p metadata_pool rm $i;done
systemctl restart ceph-mds.target

在这里插入图片描述
恢复步骤

设置允许多文件系统
ceph fs flag set enable_multiple true –yes-i-really-mean-it
创建一个新的元数据池,这里是为了不去动原来的metadata的数据,以免损坏原来的元数据
ceph osd pool create recovery 8
将老的存储池data和新的元数据池recovery关联起来并且创建一个新的recovery-fs
ceph fs new recovery-fs recovery data_pool –allow-dangerous-metadata-overlay
做下新的文件系统的初始化相关工作
cephfs-data-scan init –force-init –filesystem recovery-fs –alternate-pool recovery
reset下新的fs
ceph fs reset recovery-fs –yes-i-really-mean-it
cephfs-table-tool recovery-fs:all reset session
cephfs-table-tool recovery-fs:all reset snap
cephfs-table-tool recovery-fs:all reset inode
做相关的恢复
cephfs-data-scan scan_extents –force-pool –alternate-pool recovery –filesystem cephfs data_pool
cephfs-data-scan scan_inodes –alternate-pool recovery –filesystem cephfs –force-corrupt –force-init data_pool
cephfs-data-scan scan_links –filesystem recovery-fs
systemctl start ceph-mds.target
等待mds active 以后再继续下面操作
ceph daemon mds.mon0 scrub_path / recursive repair
ceph fs set-default recovery-fs

挂载客户端验证

ceph-fuse -n client.admin -m 10.10.0.7 --key=AQDncgVfX4NDChAA4yAy6AmbK6YbfLha3zGA7w==  /mnt/cephfs
ls -la /mnt/cephfs

在这里插入图片描述
实际测试中为出现所有lost+found文件夹
分析
通过查看cephfs-data-scan代码得知,cephfs-data-scan通过执行文件系统数据池,去扫描文件系统中对应保存文件内容的obj的backtrace,backtrace中保存该inode对应文件名以及对应目录结构,然后在新元数据池中构建各级目录对应的inode obj。对于在journal中还未flush到data池的数据,此时data池中无backtrace,此时无法确定该inode目录结构,会在根目录下建立lost+found文件夹,将没有flush值data池中的数据放入lost+found文件夹中。该文件夹对应元数据4.0000000 obj。
根目录先保存lost+found文件夹信息
在这里插入图片描述
lost+found obj中保存没backtrace ojb信息
在这里插入图片描述
此时recover池中根目录下已有对应元数据信息,启动mds时却没有加载1.0000000obj信息
通过查看mds相关代码,根目录信息通过MDCache.cc中open_root()函数进行加载

void MDCache::open_root()
{
  dout(10) << "open_root" << dendl;

  if (!root) {
    open_root_inode(new C_MDS_RetryOpenRoot(this));
    return;
  }
  if (mds->get_nodeid() == mds->mdsmap->get_root()) {
    assert(root->is_auth());  
    CDir *rootdir = root->get_or_open_dirfrag(this, frag_t());
    assert(rootdir);
    if (!rootdir->is_subtree_root())
      adjust_subtree_auth(rootdir, mds->get_nodeid());   
    if (!rootdir->is_complete()) {
      rootdir->fetch(new C_MDS_RetryOpenRoot(this));       //读取1.0000000 obj中omap信息
      return;
    }
  } else {
    assert(!root->is_auth());
    CDir *rootdir = root->get_dirfrag(frag_t());
    if (!rootdir) {
      open_remote_dirfrag(root, frag_t(), new C_MDS_RetryOpenRoot(this));
      return;
    }    
  }

  if (!myin) {
    CInode *in = create_system_inode(MDS_INO_MDSDIR(mds->get_nodeid()), S_IFDIR|0755);  // initially inaccurate!
    in->fetch(new C_MDS_RetryOpenRoot(this));
    return;
  }
  CDir *mydir = myin->get_or_open_dirfrag(this, frag_t());
  assert(mydir);
  adjust_subtree_auth(mydir, mds->get_nodeid());

  populate_mydir();
}

通过代码发现,只有rootdir->is_complete()不成立的时候会去读取1.0000000 obj的omap信息,rootdir->is_complete()代表此时根目录信息已经完全被加载至内存中。
因为新文件系统recovery-fs在启动时,直接由creating状态进入active状态,在creating过程中调用boot_create()函数创建mds初始化相关信息及内存结构,其中create_empty_hierarchy()会去构建根目录信息

void MDCache::create_empty_hierarchy(MDSGather *gather)
{
  // create root dir
  CInode *root = create_root_inode();

  // force empty root dir
  CDir *rootdir = root->get_or_open_dirfrag(this, frag_t());
  adjust_subtree_auth(rootdir, mds->get_nodeid());   
  rootdir->dir_rep = CDir::REP_ALL;   //NONE;

  assert(rootdir->fnode.accounted_fragstat == rootdir->fnode.fragstat);
  assert(rootdir->fnode.fragstat == root->inode.dirstat);
  assert(rootdir->fnode.accounted_rstat == rootdir->fnode.rstat);
  /* Do no update rootdir rstat information of the fragment, rstat upkeep magic
   * assume version 0 is stale/invalid.
   */

  rootdir->mark_complete();
  rootdir->mark_dirty(rootdir->pre_dirty(), mds->mdlog->get_current_segment());
  rootdir->commit(0, gather->new_sub());

  root->mark_clean();
  root->mark_dirty(root->pre_dirty(), mds->mdlog->get_current_segment());
  root->mark_dirty_parent(mds->mdlog->get_current_segment(), true);
  root->flush(gather->new_sub());
}

其中会将rootdir->mark_complete()标记为complete状态,进入active之后,将不会读取根目录信息。
结论
当cephfs元数据发生灾难性故障时,此时已经从journal中flush至disk的文件信息可以通过cephfs-data-scan重新构建至新文件系统元数据池中,journal中的文件信息将会丢失,丢失的文件的inode号存放于lost+found文件夹中。
新文件系统启动无法正常读取根目录obj 的omap信息(恢复时步骤出错????),待解决。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值