##前言 我使用xfs比较二一点,我是在ceph的rbd上直接格式化的xfs,因此ceph上的数据通常不会丢失,不过个人xfs是在docker内部进行的挂载,使用也是docker容器内使用,这里不得不说docker stop容器的时候仍是至关的暴力,暴力到什么程度呢?xfs大多会在硬盘忽然断电的状况下致使日志文件的写入损坏,故障每每就在这时发生,而docker stop容器和忽然断电能够画上等号。最为悲催的是,我刚开始对xfs一无所知。ceph的rbd也是只知其一;不知其二。而数据是万万不能丢失的,因此中间折腾了好长时间。html
###故障现象 marathon上是没法中止或者没法启动容器的,容器进程实际已经卡死,登陆到后台,kill进程已经没有意义了,压根就不起做用。 message报错以下:linux
Sep 19 10:05:44 [localhost] kernel: XFS: Internal error XFS_WANT_CORRUPTED_GOTO at line 1590 of file /builddir/build/BUILD/kernel-tlinux2-3.10.101/kernel-tlinux2-3.10.101/fs/xfs/xfs_alloc.c. Caller 0xffffffff8130fadd Sep 19 10:05:44 [localhost] kernel: CPU: 1 PID: 5826 Comm: mount Tainted: G W O 3.10.101-1-tlinux2-0037.tl2 #1 Sep 19 10:05:44 [localhost] kernel: Hardware name: Huawei XH310 V3/BC21DUSA0, BIOS 1.13 09/19/2015 Sep 19 10:05:44 [localhost] kernel: ffff8803f5aa4000 000000006315a611 ffff8803fc2f5b00 ffffffff81b2a080 Sep 19 10:05:44 [localhost] kernel: ffff8803fc2f5b18 ffffffff812f563b ffffffff8130fadd ffff8803fc2f5bc0 Sep 19 10:05:44 [localhost] kernel: ffffffff8130e008 ffff8803fa40c000 ffff8803fe56b000 ffff8803fe508480 Sep 19 10:05:44 [localhost] kernel: Call Trace: Sep 19 10:05:44 [localhost] kernel: [<ffffffff81b2a080>] dump_stack+0x19/0x1b Sep 19 10:05:44 [localhost] kernel: [<ffffffff812f563b>] xfs_error_report+0x3b/0x40 Sep 19 10:05:44 [localhost] kernel: [<ffffffff8130fadd>] ? xfs_free_extent+0x12d/0x170 Sep 19 10:05:44 [localhost] kernel: [<ffffffff8130e008>] xfs_free_ag_extent+0x458/0x970 Sep 19 10:05:44 [localhost] kernel: [<ffffffff8130fadd>] xfs_free_extent+0x12d/0x170 Sep 19 10:05:44 [localhost] kernel: [<ffffffff813508c0>] xlog_recover_process_efi+0x1a0/0x1e0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81367154>] ? xfs_trans_ail_cursor_init+0x24/0x30 Sep 19 10:05:44 [localhost] kernel: [<ffffffff813525b2>] xlog_recover_process_efis.isra.18+0x72/0xd0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81356471>] xlog_recover_finish+0x21/0xb0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81360704>] xfs_log_mount_finish+0x54/0x70 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81359924>] xfs_mountfs+0x474/0x740 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81307479>] xfs_fs_fill_super+0x299/0x320 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81173908>] mount_bdev+0x1b8/0x1f0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff813071e0>] ? xfs_parseargs+0xc40/0xc40 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81305595>] xfs_fs_mount+0x15/0x20 Sep 19 10:05:44 [localhost] kernel: [<ffffffff811741e5>] mount_fs+0x15/0xc0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff8118da1f>] vfs_kern_mount+0x5f/0xf0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff8118fe6d>] do_mount+0x21d/0xab0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff8111003e>] ? __get_free_pages+0xe/0x50 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81190796>] SyS_mount+0x96/0xf0 Sep 19 10:05:44 [localhost] kernel: [<ffffffff81c0cce2>] system_call_fastpath+0x16/0x1b Sep 19 10:05:44 [localhost] kernel: XFS (rbd0): Failed to recover EFIs Sep 19 10:05:44 [localhost] kernel: XFS (rbd0): log mount finish failed
一开始没想到会是文件系统损坏,由于没有理太清楚ceph的rbd和xfs之间的关系,其实也没有查到会是xfs出了问题。仍是在怀疑ceph的rbd可能什么资源没有释放。 ###怀疑rbd资源未释放 ceph的rbd是有锁的,他要保证数据的一致性,当有一个客户端挂载以后会当即加锁记录到ceph当中。查看锁的方法docker
[root@localhost /data]# rbd lock ls data/test There is 1 exclusive lock on this image. Locker ID Address client.514151 test 192.168.1.3:0/1002880
若是发现列表中有不正常的锁,能够运行下面的命令进行清理:网络
##命令格式 lock remove <image-name> <id> <locker> [root@localhost /data]# rbd lock remove data/test test client.514151
我也这么干了,可是发现问题依旧,rbd仍是挂载不上,容器一启动就卡死,docker连ps都运行不出来,只得带外重启系统才能释放资源、清理进程。为了缩小问题的范围,我开始尝试手动直接挂载rbd,就在作好本地映射准备挂载的时候,提示文件系统报错,没法挂载。这也就是说docker没有问题,应用也正常,ceph -s以后一切也ok,惟一出问题就是在rbd之上的xfs文件系统。 ###恍惚之间的艰难选择 xfs我是一窍不通,我开始压根没太以为这玩意会每天出问题。网上找了一通以后,开始尝试先恢复数据。 尝试dump rbd的数据:ui
xfs_metadump -o /dev/rbd0 /data/rbd0.metadump (加-o参数,否则元数据会显示乱码)
还原:this
xfs_mdrestore rbd0.metadump rbd0.img
这个时候尝试进行挂载rbd0.img,发现问题依旧,仍是不行,因而开始修复url
xfs_repair -L rbd0.img
而后挂载,又报错,提示dmesg|tail查问题,其实就是uuid重复的问题,这样挂载就行了:rest
mount -t xfs -o nouuid rbd0.img /data1/
挂载检查以后发现,文件目录和文件名称正常,数据大小也没有问题,可是每一个文件中都是空的,根本读不出来具体的数据。 思索再三以后才恍然大悟,原来这玩意仅仅是在dump xfs的元数据,每一个文件真实的数据都不包含,你从rbd0.img的大小就能看出来,绝对不是全量的xfs数据。其实xfs全量的dump真正用的命令是xfsdump,一样对应的是xfsrestore,不过挺遗憾的,没有实验这组命令:日志
xfsdump -l 0 -f /dev/rbd0 /data/dump/
具体的使用要看这里 若是你要用xfsdump恢复数据,建议用管道的方式(xfsdump -J -s people/fred - /usr | xfsrestore - /usr2)进行恢复,由于xfsdump须要准备一个额外的同等大小的分区来进行数据还原,而不是仅仅是数据的大小。 其实xfsdump并不适合解决个人问题,百度谷歌一通以后,仍是倾向于直接xfs_repair -L,可是-L说会丢失部分日志数据,这个怕是我背不起的。因此在作这个以前,我想先备份一下现有数据。省的我最后的救命稻草没了,就死翘翘了。 ###数据备份 备份有两个办法:code
rbd export test test.img
xfs_copy /dev/rbd0 /dev/rbd1
这个速度要比第一个能高一半,可是目标块设备的大小要大于源块设备,并且文件系统也必须是xfs,不过遗憾的是,这个方式无法用,由于到最后90%的时候它是不管如何也到不了100%的,缘由很简单源块设备的文件系统是坏的,xfs_copy只能在两个正常的xfs文件系统中复制数据。因此费了咱们好多时间。 ###临终 最终仍是直接xfs_repair -L 直接在ceph的源故障块上进行操做修复的。这里附上疑似华为的解决文档做为参考,之后再遇到此故障,放心大胆的搞,传送门 最后,生死由命,富贵在天,你在dump的时候多拜拜春哥: