我们之前提到Lustre的所有元数据(除了文件大小)都存储在MDT上面,因此MDT的稳定性至关重要,因为一旦MDT失效,整个文件系统将不可用。因此,建议经常备份MDT,以作为容灾手段。同样,在对OST做修复等关键操作时,为防止数据不可恢复,应提前备份OST设备。备份MDT/OST可在设备级或文件系统级执行,本文将据介绍这两种备份和恢复的方法。
设备级备份
我们知道,Linux设备文件是可以直接读写的。对MDT/OST进行设备级备份,也就是直接将MDT/OST设备的数据读出,并存储为一个文件。在恢复时,则将备份数据直接写入到MDT的设备文件中。
通常,在做备份之前,需将MDT/OST离线,以避免备份数据的内部结构出现不一致。但倘若MDT/OST运行在LVM(Logical Volume Manager)上,则可利用LVM的快照功能,在MDT仍处于在线服务状态的情况下,将MDT的某一时刻的快照备份出来。为方便在线备份(同时为了方便拓展容量),MDT通常构建在LVM中,而且LVM设备需留足快照所需空闲空间。如果MDT未使用LVM,而又无法离线备份MDT,那么在线备份MDT也是有价值的,因为e2fsck
可以修复备份中的不一致。关于LVM的快照功能,这里不深入细节。
在前面的几章,我们构建了一个文件系统,并且在里面写了一些数据:
[root@lixi0000-el7-vm2 ~]# ls /mnt/global/1 12 15 18 20 23 26 5 8 file2_on_ost0 file5_on_ost0 first_file level0 stripe310 13 16 19 21 24 3 6 9 file3_on_ost0 file_on_all_OSTs first_file_link1 second_file11 14 17 2 22 25 4 7 file1_on_ost0 file4_on_ost0 file_on_ost0 first_file_link2 stripe1
我们要备份这个文件系统,所以首先将文件系统的所有客户端和服务器卸载:
[root@lixi0000-el7-vm2 ~]# umount /mnt/global[root@lixi0000-el7-vm2 ~]# lustre_rmmod[root@lixi0000-el7-vm1 ~]# umount /mnt/global[root@lixi0000-el7-vm1 ~]# umount /mnt/lustre_mdt0[root@lixi0000-el7-vm1 ~]# umount /mnt/lustre_ost0[root@lixi0000-el7-vm3 ~]# umount /mnt/lustre0_ost1[root@lixi0000-el7-vm3 ~]# umount /mnt/lustre0_ost2[root@lixi0000-el7-vm3 ~]# lustre_rmmod[root@lixi0000-el7-vm1 ~]# umount /mnt/mgs[root@lixi0000-el7-vm1 ~]# lustre_rmmod
我们既可以将MDT备份到一个文件系统的文件中,也可以将至备份至某设备文件中,只要文件系统和设备文件的访问性能足够,以及有足够空闲空间即可。下面,我们将MDT备份至一个文件中:
[root@lixi0000-el7-vm2 ~] dd if=/dev/mapper/lustre0_mdt0 of=/mdt_backup bs=4M1280+0 records in1280+0 records out5368709120 bytes (5.4 GB) copied, 85.5729 s, 62.7 MB/s
设备级恢复
接下来,我们假装是一个迷糊的管理员,错误地将这个MDT格式化为Ext4文件系统:
[root@lixi0000-el7-vm1 ~]# mkfs.ext4 /dev/mapper/lustre0_mdt0mke2fs 1.44.5.wc1 (15-Dec-2018)/dev/mapper/lustre0_mdt0 contains a ext4 file system labelled 'global-MDT0000'last mounted on / on Fri May 10 22:42:29 2019Proceed anyway? (y,N) ySuggestion: Use Linux kernel >= 3.18 for improved stability of the metadata and journal checksum features.Discarding device blocks: doneCreating filesystem with 1310720 4k blocks and 327680 inodesFilesystem UUID: f3073f73-1ad8-4a40-b78b-c8b7513351aaSuperblock backups stored on blocks:32768, 98304, 163840, 229376, 294912, 819200, 884736Allocating group tables: doneWriting inode tables: doneCreating journal (16384 blocks): doneWriting superblocks and filesystem accounting information: done
我们发现,其实mkfs.ext4
在发现设备上已有了一个文件系统之后,就警告说其中存在标签是global-MDT0000
的文件系统。只有糊涂的管理员才会忽视警告,继续将这个文件系统上面的数据毁坏殆尽。好在我们还有备份,可以进行恢复:
[root@lixi0000-el7-vm1 ~]# dd if=/mdt_backup of=/dev/mapper/lustre0_mdt0 bs=4M1280+0 records in1280+0 records out5368709120 bytes (5.4 GB) copied, 127.14 s, 42.2 MB/s
恢复之后,我们挂载Lustre文件系统,查看数据完整情况:
[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre_mgs /mnt/mgs[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre0_mdt0 /mnt/lustre_mdt0[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre0_ost0 /mnt/lustre_ost0[root@lixi0000-el7-vm3 ~]# mount -t lustre /dev/mapper/lustre0_ost1 /mnt/lustre0_ost1[root@lixi0000-el7-vm3 ~]# mount -t lustre /dev/mapper/lustre0_ost2 /mnt/lustre0_ost2[root@lixi0000-el7-vm2 ~]# mount -t lustre 10.0.1.148@tcp:/global /mnt/global/[root@lixi0000-el7-vm2 ~]# ls /mnt/global/1 12 15 18 20 23 26 5 8 file2_on_ost0 file5_on_ost0 first_file level0 stripe310 13 16 19 21 24 3 6 9 file3_on_ost0 file_on_all_OSTs first_file_link1 second_file11 14 17 2 22 25 4 7 file1_on_ost0 file4_on_ost0 file_on_ost0 first_file_link2 stripe1
MDT的恢复和文件系统的挂载都很顺畅地完成了,检查也未发现元数据存在问题。
文件系统级备份
设备级的MDT备份需要备份的数据量等于MDT的容量。对于容量较大的MDT/OST,该设备级备份将占用大量时间和存储容量。我们知道,在MDT/OST中,可能有大量空闲空间,因此在大多数情况下,设备级备份无论是在空间效率和时间效率上都不占优势,优点只在于操作简单。与此相比,只备份MDT/OST中有意义的文件数据,则效率更高,我们称之为文件系统级备份。
在《文件数据和元数据的内部组织方式》一章中,我们了解到,MDT/OST可以用后端文件系统的方式挂载起来,以供访问。Lustre文件系统绝大部分信息,不管是内部结构数据还是用户数据,都是按照后端文件系统文件的方式存储的。只要将这些后端文件系统的所有数据和元数据备份起来,就可以用它恢复Lustre设备。
与设备级备份类似,文件系统级备份也需要MDT/OST处于离线状态(同样,LVM快照可在线备份)。为此,我们同样按照已提到的流程,卸载所有Lustre客户端和服务器。这里不再重复粘贴命令。
这里同样以MDT为例,对之进行文件系统级备份:
[root@lixi0000-el7-vm1 ~]# mount -t ldiskfs /dev/mapper/lustre0_mdt0 /mnt/lustre_mdt0_ldiskfs/[root@lixi0000-el7-vm1 ~]# cd /mnt/lustre_mdt0_ldiskfs/[root@lixi0000-el7-vm1 ~]# tar czvf /mdt_backup.tgz --xattrs --xattrs-include="trusted.*" --sparse .[root@lixi0000-el7-vm1 lustre_mdt0_ldiskfs]# ls /mdt_backup.tgz -l-rw-r--r-- 1 root root 29950 May 16 03:04 /mdt_backup.tgz
我们可以发现,备份产生的文件数据很小。当然,这是因为元数据使用量较少。在元数据使用量较大的情况下,该文件会相应较大,但因为压缩,备份文件一般会小于MDT的使用量。
文件系统级恢复
接下来,我们假装再次回到迷糊状态,只是这次迷糊方式不同,我们错误地往MDT写上全零:
[root@lixi0000-el7-vm1 ~]# umount /mnt/lustre_mdt0_ldiskfs/[root@lixi0000-el7-vm1 ~]# dd if=/dev/zero of=/dev/mapper/lustre0_mdt0 bs=1048576dd: error writing '/dev/mapper/lustre0_mdt0': No space left on device5121+0 records in5120+0 records out[root@lixi0000-el7-vm1 ~]# mount -t ldiskfs /dev/mapper/lustre0_mdt0 /mnt/lustre0_ost0_ldiskfs/mount: wrong fs type, bad option, bad superblock on /dev/sdc, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so.
文件所有数据都被破坏了,连以Ldiskfs方式挂载都失败了。
残酷的现实使我们恢复清醒,开始用文件系统级备份进行恢复。首先,我们要重新格式化这个MDT。我们知道,在《快速搭建最简单的Lustre文件系统》一章,我们使用的格式化MDT的命令为:
[root@lixi0000-el7-vm1 ~]# mkfs.lustre --fsname global --mdt --index=0 --mgsnode=10.0.1.148@tcp /dev/mapper/lustre0_mdt0
这里,因为我们要需要在此基础上加上--replace
:
[root@lixi0000-el7-vm1 ~]# mkfs.lustre --replace --fsname global --mdt --index=0 --mgsnode=10.0.1.148@tcp /dev/mapper/lustre0_mdt0
然后将后端文件系统以ldiskfs
类型挂载,并将备份的数据恢复:
[root@lixi0000-el7-vm1 ~]# mount -t ldiskfs /dev/mapper/lustre0_mdt0 /mnt/lustre_mdt0_ldiskfs/
[root@lixi0000-el7-vm1 ~]# cd /mnt/lustre_mdt0_ldiskfs/
[root@lixi0000-el7-vm1 lustre_mdt0_ldiskfs]# tar xzvpf /mdt_backup.tgz --xattrs --xattrs-include="trusted.*" --sparse
在恢复完毕之后,我们需要把一些Lustre内部数据删掉。这些内部数据会在服务开始运行时,自动生成。老的数据可以删掉:
[root@lixi0000-el7-vm1 lustre_mdt0_ldiskfs]# rm -fr oi.16* lfsck_* LFSCK CATALOGS
[root@lixi0000-el7-vm1 lustre_mdt0_ldiskfs]# cd
[root@lixi0000-el7-vm1 ~]# umount /mnt/lustre_mdt0_ldiskfs
恢复之后,我们挂载Lustre文件系统,查看数据完整情况:
[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre_mgs /mnt/mgs
[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre0_mdt0 /mnt/lustre_mdt0
[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre0_ost0 /mnt/lustre_ost0
[root@lixi0000-el7-vm3 ~]# mount -t lustre /dev/mapper/lustre0_ost1 /mnt/lustre0_ost1
[root@lixi0000-el7-vm3 ~]# mount -t lustre /dev/mapper/lustre0_ost2 /mnt/lustre0_ost2
[root@lixi0000-el7-vm2 ~]# mount -t lustre 10.0.1.148@tcp:/global /mnt/global/
[root@lixi0000-el7-vm2 ~]# ls /mnt/global/
1 14 19 23 4 9 file5_on_ost0 first_file_link2
10 15 2 24 5 file1_on_ost0 file_on_all_OSTs level0
11 16 20 25 6 file2_on_ost0 file_on_ost0 second_file
12 17 21 26 7 file3_on_ost0 first_file stripe1
13 18 22 3 8 file4_on_ost0 first_file_link1 stripe3
MDT的恢复和文件系统的挂载都很顺畅地完成了,检查也未发现元数据存在问题。
使用e2image备份
我们知道,基于Ldiskfs的Lustre文件系统的MDT或OST实际上运行了一个打了补丁的Ext4文件系统,在这个文件系统上可以无缝运行e2fsck、debugfs等e2fsprogs的工具,只是所用e2fsprogs的版本需为Whamcloud提供的版本。在e2fsprgs工具链中,有一个可以用来将Ext4文件系统备份到文件中的工具——e2image。
这里我们用e2image来备份MDT,备份之前,同样要卸载所有客户端和服务器:
[root@lixi0000-el7-vm2 ~]# umount /mnt/global
[root@lixi0000-el7-vm2 ~]# lustre_rmmod
[root@lixi0000-el7-vm1 ~]# umount /mnt/global
[root@lixi0000-el7-vm1 ~]# umount /mnt/lustre_mdt0
[root@lixi0000-el7-vm1 ~]# umount /mnt/lustre_ost0
[root@lixi0000-el7-vm3 ~]# umount /mnt/lustre0_ost1
[root@lixi0000-el7-vm3 ~]# umount /mnt/lustre0_ost2
[root@lixi0000-el7-vm3 ~]# lustre_rmmod
[root@lixi0000-el7-vm1 ~]# umount /mnt/mgs
[root@lixi0000-el7-vm1 ~]# lustre_rmmod
然后使用e2image来备份MDT之上的所有数据:
[root@lixi0000-el7-vm1 ~]# e2image -r -a /dev/mapper/lustre0_mdt0 /mdt_e2image
e2image 1.44.5.wc1 (15-Dec-2018)
通过e2image的备份进行恢复
首先,我们对MDT进行破坏:
[root@lixi0000-el7-vm1 ~]# dd if=/dev/zero of=/dev/mapper/lustre0_mdt0 bs=4M
1280+0 records in
1280+0 records out
5368709120 bytes (5.4 GB) copied, 141.13 s, 38.0 MB/s
[root@lixi0000-el7-vm1 ~]# mount -t ldiskfs /dev/mapper/lustre0_mdt0 /mnt/
mount: wrong fs type, bad option, bad superblock on /dev/sdc,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so.
dd: error writing '/dev/mapper/lustre0_mdt0': No space left on device
1281+0 records in
1280+0 records out
5368709120 bytes (5.4 GB) copied, 141.416 s, 38.0 MB/s
破坏之后,我们通过备份的数据进行恢复:
[root@lixi0000-el7-vm1 ~]# dd if=/mdt_e2image of=/dev/mapper/lustre0_mdt0 bs=4M
1280+0 records in
1280+0 records out
5368709120 bytes (5.4 GB) copied, 140.762 s, 38.1 MB/s
[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre_mgs /mnt/mgs
[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre0_mdt0 /mnt/lustre_mdt0
[root@lixi0000-el7-vm1 ~]# mount -t lustre /dev/mapper/lustre0_ost0 /mnt/lustre_ost0
[root@lixi0000-el7-vm3 ~]# mount -t lustre /dev/mapper/lustre0_ost1 /mnt/lustre0_ost1
[root@lixi0000-el7-vm3 ~]# mount -t lustre /dev/mapper/lustre0_ost2 /mnt/lustre0_ost2
[root@lixi0000-el7-vm2 ~]# mount -t lustre 10.0.1.148@tcp:/global /mnt/global/
[root@lixi0000-el7-vm2 ~]# ls /mnt/global/
1 14 19 23 4 9 file5_on_ost0 first_file_link2
10 15 2 24 5 file1_on_ost0 file_on_all_OSTs level0
11 16 20 25 6 file2_on_ost0 file_on_ost0 second_file
12 17 21 26 7 file3_on_ost0 first_file stripe1
13 18 22 3 8 file4_on_ost0 first_file_link1 stripe3
可以发现MDT被正确恢复了。
各备份方式的空间效率对比
设备级备份是对原存储设备的完整备份,备份文件中存储了大量未在Ext4文件系统中使用的数据块,因此效率未可言高,但因为是原始备份,反而适合于一些特殊情况。比如,假若Ext4文件系统一些内部数据结构已遭破坏,设备级备份将将原始数据原原本本地备份下来,这样我们可以放心地对MDT/OST进行fsck等操作,而不必担心因此而出现数据永久丢失的情况。设备级备份需要用的空间等于原MDT/OST存储设备的空间:
[root@lixi0000-el7-vm1 ~]# ls -lh /mdt_backup
-rw-r--r-- 1 root root 5.0G May 16 00:37 /mdt_backup
[root@lixi0000-el7-vm1 ~]# du -sh /mdt_backup
5.1G /mdt_backup
相对于设备级备份,e2image
会解析Ext4文件系统的结构,避免复制不存储在Lustre中的文件系统,因此它复制和存储的数据量通常比文件系统存储设备的空间小的多:
[root@lixi0000-el7-vm1 ~]# ls -l /mdt_e2image -lh
-rw------- 1 root root 5.0G May 17 12:14 /mdt_e2image
[root@lixi0000-el7-vm1 ~]# du -sh /mdt_e2image
5.9M /mdt_e2image
但采用e2image
备份需保证Ext4文件系统是完整和一致的,否则可能发生备份失败。因此,通常基于LVM快照的在线备份中,通常在运行e2image
之前,需要对快照设备运行e2fsck
以修复其中的不一致问题。
而文件系统级备份由于避免了存储Ext4文件系统内部数据,加之压缩了文件的数据和元数据,所需要的存储空间则比其他两种方式更少:
[root@lixi0000-el7-vm1 ~]# ls -lh /mdt_backup.tgz
-rw-r--r-- 1 root root 30K May 16 03:04 /mdt_backup.tgz
[root@lixi0000-el7-vm1 ~]# du -sh /mdt_backup.tgz
32K /mdt_backup.tgz
各备份方式的时间效率对比
在备份时间上,设备级备份主要时间花在读出设备数据,并将之写入备份中。其中所有读写均为线性大块读写,因此备份时间仅与OST/MDT设备大小、OST/MDT设备的线性大块读性能、备份对象线性大块写性能有关,在各存储设备不变的情况下近似为常量,与OST/MDT上存储了多少文件/对象无关。
与此相比,e2image和文件系统级备份的时间则与OST/MDT上存储了多少文件和对象相关。在文件和对象数目较少时,它们所需备份时间较小。文件和对象数目越多,所需备份时间越多。
在恢复时间上,设备级备份和e2image的备份之恢复时间近似相同;而文件系统级备份的恢复时间则与所存储的文件/对象数量有关。
总结
本文介绍了备份基于Ldiskfs的MDT/OST的三种备份和恢复方法,并分析了它们的时间和空间效率。在对MDT/OST进行数据修复、扩展容量等维护工作时,时常首先需要进行备份,以保万全。因此,管理员需熟悉数据各种备份和恢复MDT/OST的方式,理解其原理,并据此选择合适的备份方法。
实验与思考
试设计实验,对比三种备份方式的时间效率,找出在何种情况下(如文件数量),设备级备份的时间相较其他两种方式开始变得较短。
试设计实验,找出最少往MDT写入多少数据,就能使得MDT不可用。
试分析,各备份方式所需时间分别由哪些因素决定,它们的恢复所需时间又分别由哪些因素决定。
试分析,为何采用LVM对MDT/OST进行在线备份,需保证LVM上有空间空间,并分析所需空间空间由哪些因素决定。
试分析,需要预留多少LVM的空闲空间,才能满足对MDT/OST进行在线备份。