一次mfs恢复数据

今天web服务器发现挂载的分布式文件系统mfs无法访问,去mfsmaster检查发现服务器没有启动。
启动服务器,登陆,查看没有mfs进程,端口都没启动,手动启动服务,提示错误:
[root@centos-6.5-x64 ~]#/usr/local/mfs/sbin/mfsmaster start
working directory: /usr/local/mfs/var/mfs
lockfile created and locked
initializing mfsmaster modules …
loading sessions … ok
sessions file has been loaded
exports file has been loaded
loading metadata …
can’t open metadata file
if this is new instalation then rename metadata.mfs.empty as metadata.mfs
init: file system manager failed !!!
error occured during initialization – exiting
根据提示判断为mfs启动时认为这是一台新的mfsmaster,需要rename metadata.mfs.empty as metadata.mfs

这完全不是新服务器,赶紧恢复日志:                                                                     [root@centos-6.5-x64 var]#tar zcvf mfs.tar.gz mfs/  #防止意外,把整个数据日志信息目录备份
[root@centos-6.5-x64 mfs]#/usr/local/mfs/sbin/mfsmetarestore -m metadata.mfs.back -o metadata.mfs changelog.*.mfs
loading objects (files,directories,etc.) … loading node: read error: Success
error
can’t read metadata from file: metadata.mfs.back
看样子metadata.mfs.back文件损坏。
赶紧查资料:http://blog.ztrix.me/blog/2012/05/13/restore-mfs-metadata/
根据资料查看我本地linux文件系统确实是ext4,可以判断跟资料上的情况一样了,可是我不会像文章写的一样会编程寻找数据。

遂再次检查:
[root@centos-6.5-x64 mfs]#ll
总用量 1724
-rw-r—– 1 mfs mfs 8543 4月 26 11:09 changelog.0.mfs
-rw-r—– 1 mfs mfs 4246 4月 26 11:09 changelog.10.mfs
-rw-r—– 1 mfs mfs 3368 4月 26 11:09 changelog.11.mfs
-rw-r—– 1 mfs mfs 8543 4月 26 11:09 changelog.1.mfs
-rw-r—– 1 mfs mfs 51757 4月 26 11:09 changelog.2.mfs
-rw-r—– 1 mfs mfs 183976 4月 26 11:09 changelog.3.mfs
-rw-r—– 1 mfs mfs 4901 4月 26 11:09 changelog.4.mfs
-rw-r—– 1 mfs mfs 1796 4月 26 11:09 changelog.5.mfs
-rw-r—– 1 mfs mfs 1502 4月 26 11:09 changelog.6.mfs
-rw-r—– 1 mfs mfs 599839 4月 26 11:09 changelog.7.mfs
-rw-r—– 1 mfs mfs 4383 4月 26 11:09 changelog.8.mfs
-rw-r—– 1 mfs mfs 4988 4月 26 11:09 changelog.9.mfs
-rw-r—– 1 mfs mfs 81920 4月 26 11:09 metadata.mfs.back
-rw-r—– 1 mfs mfs 147081 4月 26 11:09 metadata.mfs.back.tmp
-rw-r–r– 1 root root 8 4月 26 11:09 metadata.mfs.empty
-rw-r—– 1 mfs mfs 10541 4月 26 11:09 sessions.mfs
-rw-r—– 1 mfs mfs 610016 4月 26 11:09 stats.mfs
[root@centos-6.5-x64 mfs]#rm -f metadata.mfs.back
[root@centos-6.5-x64 mfs]#mv metadata.mfs.back.tmp metadata.mfs.back
发现有个metadata.mfs.back.tmp文件,把之前的metadata.mfs.back删掉,metadata.mfs.back.tmp改名metadata.mfs.back
恢复日志:
[root@centos-6.5-x64 mfs]#/usr/local/mfs/sbin/mfsmetarestore -m metadata.mfs.back -o metadata.mfs changelog.*.mfs
loading objects (files,directories,etc.) … ok
loading names … ok
loading deletion timestamps … ok
checking filesystem consistency … ok
loading chunks data … ok
connecting files and chunks … ok
applying changes from file: changelog.0.mfs
meta data version: 22443
version after applying changelog: 22698
applying changes from file: changelog.10.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.11.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.1.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.2.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.3.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.4.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.5.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.6.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.7.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.8.mfs
meta data version: 22698
version after applying changelog: 22698
applying changes from file: changelog.9.mfs
meta data version: 22698
version after applying changelog: 22698
store metadata into file: metadata.mfs

太好了,没报错,启动服务:
[root@centos-6.5-x64 mfs]#/usr/local/mfs/sbin/mfsmaster start

working directory: /usr/local/mfs/var/mfs
lockfile created and locked
initializing mfsmaster modules …
loading sessions … ok
sessions file has been loaded
exports file has been loaded
loading metadata …
loading objects (files,directories,etc.) … ok
loading names … ok
loading deletion timestamps … ok
checking filesystem consistency … ok
loading chunks data … ok
connecting files and chunks … ok
all inodes: 1622
directory inodes: 124
file inodes: 1498
chunks: 1485
metadata file has been loaded
stats file has been loaded
master <-> metaloggers module: listen on *:9419
master <-> chunkservers module: listen on *:9420
main master server module: listen on *:9421
mfsmaster daemon initialized properly
[root@centos-6.5-x64 mfs]#
[root@centos-6.5-x64 mfs]#ps aux | grep mfs
root 1556 0.0 0.4 170416 460 ? S 10:51 0:00 python /usr/local/mfs/sbin/mfscgiserv start
mfs 1946 6.2 43.1 82056 46196 ? S< 11:16 0:00 /usr/local/mfs/sbin/mfsmaster start
root 1948 2.0 0.7 103256 844 pts/0 S+ 11:17 0:00 grep mfs
服务启动,去web服务器查看,数据出来了。

转来的丢失原因:

ext4 文件系统的 delay allocation 导致的。moosefs 在持久化 metadata 信息的时候,会重写整个文件。他会首先把之前的 metadata.mfs.back 文件重命名成 metadaba.mfs.back.tmp,然后开始写 metadata.mfs.back 文件,写完了 fclose 之后,删除 metadata.mfs.back.tmp。如果断电的时候,正常在进行这么一个过程,那么有可能 fclose 之后,metadata.mfs.back.tmp 也删除了,但是 ext4 的 delay allocation 特性导致文件还没有真正写入到磁盘。(也有可能文件写入了磁盘 block,但是文件 inode 还没有更新)。我们在网上发现有不少人也遇到过同样的断电之后文件大小变成 0 的问题,如这个:http://www.symantec.com/connect/blogs/ext4-data-recovery-how-recovery-lost-files-ext4-file-system-linux
有可能是 moosefs 写 metadata 失败导致的。阅读了相关源代码之后,我们发现 moosefs 写文件和 fclose 的时候居然从来不判断返回值!有些地方有判断返回值,但是也仅仅打印一句 log,既不做相应错误处理,也不停止。于是就有可能是写文件失败,fclose 也失败,但是它不查返回值,所以又把之前的 metadata.mfs.back.tmp 删除了。
有可能是 ext4 修复导致的。断电造成文件系统出现不一致,然后自动修复之后造成了数据丢失。

这样一来,强烈建议将mfs的文件系统改为ext3上运行。

PS:

环境中有一台mfs slave机器做备份机,发现备份机也出问题,当我加电给master时,任务计划每个一分钟同步数据日志到备机,导致备机的日志也出错。

考虑到的方案:

在一台chunkserver中添加mfslog服务,每1小时获取一次master日志,定时备份数据日志目录。把损失降到最小。

关于mfs设置文件的副本数

首先,我这里有两台chunkserver,那么在mfs客户端设置文件副本数为 2
#设置副本数
[root@localhost ~]# /usr/local/mfs/bin/mfssetgoal 2 /mnt/mfs/
/mnt/mfs/: 2

#获取设置的副本数
[root@localhost ~]# /usr/local/mfs/bin/mfsgetgoal /mnt/mfs/
/mnt/mfs/: 2
[root@localhost ~]# echo test > /mnt/mfs/test

#查看文件信息
[root@localhost ~]# /usr/local/mfs/bin/mfsfileinfo /mnt/mfs/test
/mnt/mfs/test:
chunk 0: 0000000000000014_00000001 / (id:20 ver:1)
copy 1: 192.168.0.6:9422
copy 2: 192.168.0.7:9422
[root@localhost ~]#

可以看到test 文件被copy到两台chunkserver中,停掉一台chunkserver,test文件的数据仍然可以读写。
如果是副本数为1的话,那么数据会分到其中一台chunkserver中,如果这台chunkserver停掉
文件信息虽然可以看到,但是已经无法读写了。

实际环境中,如果说chunkserver不挂存储,一般是双硬盘做raid1,或者是raid5之类,这样也保证了数据的安全性。
如果是存储那么安全性更高,只需要考虑因为系统或者是软件导致的chunkserver宕机问题。

个人建议chunkserver3台以上,副本数2以上。

/bin/mount:无法识别的选项“–no-canonicalize”

注意:

      我在redhat5下编译完新版本util-linux时,替换 了系统自带的mount命令,mfs可以成功挂载,但是在下次启动系统时发现系统起不来(停留在fsck: /lib64/libblkid.so.1: no version information available (required by fsck)),提示说可以进入修复模式检查文件系统,可是通过fsck检查重启还不行,进入单用户模式,开启网络,打开ssh服务,把另一台同版本的mount替换还是不行,接着替换libblkid.so.1模块,还是失败,最后在grub内核参数后加一句 fastboot ,启动,虽然报错,但是可以进入系统,一切正常,备份数据,重装系统!根本原因就是因为升级了util-linux-ng版本!

可参考下redhat官网bug报告:https://bugzilla.redhat.com/show_bug.cgi?id=568473

在redhat5下mfsmount元数据服务器时报错:
[root@localhost ~]# /usr/local/mfs/bin/mfsmount /mnt/mfs -H 192.168.1.56
mfsmaster accepted connection with parameters: read-write,restricted_ip ; root mapped to root:root
/bin/mount:无法识别的选项“–no-canonicalize”
Usage: mount -V : print version
mount -h : print this help
mount : list mounted filesystems
mount -l : idem, including volume labels
So far the informational part. Next the mounting.
The command is `mount [-t fstype] something somewhere’.
Details found in /etc/fstab may be omitted.
mount -a [-t|-O] … : mount all stuff from /etc/fstab
mount device : mount device at the known place
mount directory : mount known device here
mount -t type dev dir : ordinary mount command
Note that one does not really mount a device, one mounts
a filesystem (of the given type) found on the device.
One can also mount an already visible directory tree elsewhere:
mount –bind olddir newdir
or move a subtree:
mount –move olddir newdir
One can change the type of mount containing the directory dir:
mount –make-shared dir
mount –make-slave dir
mount –make-private dir
mount –make-unbindable dir
One can change the type of all the mounts in a mount subtree
containing the directory dir:
mount –make-rshared dir
mount –make-rslave dir
mount –make-rprivate dir
mount –make-runbindable dir
A device can be given by name, say /dev/hda1 or /dev/cdrom,
or by label, using -L label or by uuid, using -U uuid .
Other options: [-nfFrsvw] [-o options] [-p passwdfd].
For many more details, say man 8 mount .
error in fuse_mount

查资料说是mount的版本过低,在mfsmount的时候需要–no-canonicalize 参数支持。

解决方法:
从 https://www.kernel.org/pub/linux/utils/util-linux/ 下载新版本,我这里对应centos6下的版本util-linux-ng-2.17进行安装。

[root@localhost ~]# yum install -y ncurses ncurses-devel
[root@localhost ~]# wget -c https://www.kernel.org/pub/linux/utils/util-linux/v2.17/util-linux-ng-2.17.tar.gz --no-check-certificate
[root@localhost ~]# tar zxvf util-linux-ng-2.17.tar.gz
[root@localhost ~]# cd util-linux-ng-2.17
[root@localhost util-linux-ng-2.17]# ./configure --prefix=/usr/local/util-linux-ng-2.17
[root@localhost util-linux-ng-2.17]# make && make install
[root@localhost util-linux-ng-2.17]# mv /bin/mount /bin/mount.old
[root@localhost util-linux-ng-2.17]# mv /bin/umount /bin/umount.old
[root@localhost util-linux-ng-2.17]# ln -s /usr/local/util-linux-ng-2.17/bin/mount /bin/mount
[root@localhost util-linux-ng-2.17]# ln -s /usr/local/util-linux-ng-2.17/bin/umount /bin/umount
[root@localhost util-linux-ng-2.17]# /usr/local/mfs/bin/mfsmount /var/www/html/ -H 192.168.1.56
mfsmaster accepted connection with parameters: read-write,restricted_ip ; root mapped to root:root
[root@localhost util-linux-ng-2.17]#

解决!

mfs分布式集群安装及解决mfs单点故障

mfs中mfsmaster存在单点故障,这里通过keepalived+shell脚本解决。

思路:
利用keepalived进行vip切换,mfschunkserver包括客户端挂载全部用vip挂载。
当master当掉时,vip漂移到slave,通过任务计划,每分钟执行一下shell脚本,脚本检测是否发现vip。
如果发现,表明master当掉,slave执行日志恢复数据。
并启动slave中的mfsmaster服务,slave身份变为master。其中,数据变化日志部分通过scp+密钥认证定时推送
(或者是通过inotify+rsync实时同步。)

系统环境信息:
mfsmaster               centos6_x64   ip:192.168.0.8
mfsslave                   centos6_x64  ip:192.168.0.9
mfschunkserver_1 centos6_x64  ip:192.168.0.7
mfschunkserver_2 centos6_x64  ip:192.168.0.6
mfsclient                   centos6_x64  ip:192.168.0.127
keepalived VIP                                 ip:192.168.0.10

selinux关闭,iptables关闭

第一部分:配置keepalived

安装keepalived参考:https://www.rootop.org/pages/2102.html
配置keepalived参考:https://www.rootop.org/pages/2108.html
关于keepalived的配置一提而过,不需要太多配置,只要能实现vip漂移即可。
现在我的环境中已经实现keepalived正常运行,vip现漂移到mfsmaster。

第二部分:安装mfs

安装mfsmaster、chunkserver、mfsclient 日志服务器可用可不用,或者直接在某台chunkserver中运行即可。
至于mfsslave,其实就是mfsmaster,只是安装以后不需要启动服务(下面出现的脚本安装完成后会启动,并加入到/etc/rc.local自己去修改即可。)
安装过程可参考:https://www.rootop.org/pages/2227.html
这里的安装步骤如下:

从 https://www.rootop.org/rs/shell_scripts/install_mfs_v1.6.sh 下载写好的mfs安装脚本。
此脚本包含了安装mfsmaster、mfslog、mfschunkserver、mfsclient
有些地方需要修改为自己的实际配置,主要为变量部分:

tgz_name=mfs-1.6.11.tar.gz             #mfs版本源码包,如果是新版本需要修改
mfs_name=mfs-1.6.11                       #mfs解压后文件夹名称,如果是新版本需要修改
fuse=fuse-2.9.3.tar.gz                        #fuse版本源码包,如果是新版本需要修改
fuse_name=fuse-2.9.3                       #fuse解压后文件夹名称,如果是新版本需要修改

mfs_user=mfs                                    #mfs运行的用户
mfs_group=mfs                                  #mfs运行的用户组

mfs_path=/usr/local/mfs                  #mfs安装路径
mfs_sbin_path=$mfs_path/sbin     #mfs相关命令路径
mfs_data_path=$mfs_path/var/mfs     #元服务器数据日志路径,默认即可
allow_access=”192.168.0.0/24 / rw,maproot=0″    #允许访问mfsmaster的网段,需要修改为实际信息。
master_host=192.168.0.10       #vip的地址,用来mfschunkserver的连接和mfsclient的挂载
mfs_data=/mnt/mfs                #chunkserver的数据存储路径,根据实际情况修改。
mount_dir=/mnt/mfs             #mfsclient客户端挂载路径,根据实际情况修改。
其它无需修改。

执行 sh install_mfs_v1.6.sh 时,有4个安装选项。
——————Press 1 To install mfsmaster ———
——————Press 2 To install mfslog ———
——————Press 3 To install mfschunkserver ———
——————Press 4 To install mfsclient ———

1安装mfsmaster,2安装日志服务器,3安装chunkserver,4安装客户端


mfsmaster(192.168.0.8)选择1开始安装。
mfsslave(192.168.0.9)选择1开始安装。
mfschunkserver_1(192.168.0.7)选择3开始安装。
mfschunkserver_2(192.168.0.6)选择3开始安装。
mfsclient(192.168.0.127)选择4开始安装。

安装完成后去mfsclient查看是否写入数据。
安装完成!

第三部分:配置master->slave推送
之前想采用inotify+rsync,但是担心在传输过程中意外停止的话,会导致mfsmaster到slave的数据不完整。
采用了scp定时拷贝。因为scp拷贝数据会要求输入密码,这里采用密钥认证,略过密码输入。

在master中生成密钥:
[root@localhost ~]# ssh-keygen -t rsa
“`信息略过
[root@localhost ~]# cd .ssh/
[root@localhost .ssh]# ll
总用量 8
-rw——-. 1 root root 1675 4月 17 00:59 id_rsa
-rw-r–r–. 1 root root 408 4月 17 00:59 id_rsa.pub
[root@localhost .ssh]# scp id_rsa.pub root@192.168.0.9:/root/.ssh/authorized_keys #把master的公钥复制到slave的/root/.ssh/下并改为为authorized_keys

到slave中,更改公钥权限:
[root@localhost ~]# chmod 400 .ssh/authorized_keys
master通过scp再复制数据到slave时就不再提示密码。

在master中添加任务计划,每分钟复制一次数据变化日志到slave中:
*/1 * * * * scp /usr/local/mfs/var/mfs/* root@192.168.0.9:/usr/local/mfs/var/mfs/
重启任务计划。

第四部分:日志恢复
下面实现mfs的主从切换及数据恢复:
将下面脚本放到任务计划,每分钟执行一次。(不完美,想做到一秒一执行)

#!/bin/bash
VIP=192.168.0.10

if [ "$(ip a | grep $VIP | awk {'print $2'} | cut -d/ -f1)" == "$VIP" ];then
 if [ -a /tmp/mfs.lock ];then
 exit
 else
 touch /tmp/mfs.lock
 cd /usr/local/mfs/var/mfs
 /usr/local/mfs/sbin/mfsmetarestore -m metadata.mfs.back -o metadata.mfs changelog.*.mfs
 /usr/local/mfs/sbin/mfsmaster start

 fi

else
 exit
fi

脚本思想就是检测本机是否获取到vip,如果检测到表明master宕机,slave接管vip,然后需要恢复数据日志,继续提供服务。

至此,完成。

ps:
如果修复master后要把服务切换到master,首先需要把keepalived中的vip切换到master,然后停止slave的mfsmaster服务
删除/tmp/mfs.lock ,要将slave的数据变化日志拷贝到master,执行恢复。
以此保证宕机期间数据变化带来的数据不完整问题。

暂时能想到这么多,有什么问题可以email给我: venus@rootop.org