使用 LVM2 中的快照归档数据
有时我们使用某项技术,即使我们不了解其全部特性和功能,以及它们如何能够使我们受益。数据快照就是这样一种特性。快照是存储卷在特定时间点的单个状态(即副本)。卷可以指磁盘设备或分区。快照主要是一种数据备份技术。针对更大的存储容量,使用这种技术具有优势。例如,完整备份整个卷可能需要很长时间,并且会占用大量存储空间,即使对于在相当长一段时间内保持不变的文件也是如此。此外,在对称多处理环境中执行整个卷或卷子集的数据备份时,写入操作仍可能继续修改该卷上的文件数据,从而阻止原子性,进而可能导致数据损坏。有一些方法可以解决后者,可以将卷脱机或标记为只读,然后再进行归档过程,但在高可用性生产环境中,这可能永远不是一种选择。这就是快照的用武之地。
快照用于避免停机时间并保持原子性,它提供指定卷在特定时间点的只读副本,通常通过写入时复制机制实现。已知一些供应商和软件实现支持通过称为分支快照的概念进行写入命令,其中通过极其复杂的指针系统创建数据的不同版本,所有这些都基于原始快照。当您写入快照或原始卷时,写入不会被另一方看到。其工作原理是,当标记为快照的卷被写入并且数据被修改时,原始和未更改的数据块或文件数据(在基于文件的快照的情况下)将被复制到为快照分配的空间。在所有原始和未修改的数据复制到快照后,原始卷将使用新数据进行更新。当需要挂载快照卷时,使用指针系统,快照将引用父卷以及保存在快照中的原始数据。通过这种技术,现在可以增量地归档有价值的数据,而不会损失生产力或遭受任何数据损坏的风险。
快照技术的使用可以在各种环境中看到,从外部存储控制器、文件系统、虚拟机(如 VMware、VirtualBox 等)、数据库,甚至卷管理器,这正是本文的重点。在这里,我将介绍 LVM2 中发现的快照功能以及如何从命令行对其进行管理。
第二代 Linux 逻辑卷管理器 (LVM2) 是一种逻辑卷管理器,能够将多个存储设备池化在一起,以表示单个卷或多个卷,可以是条带化或镜像方式。一切都是在逐层的基础上创建和管理的。首先是物理卷。其次是卷组,然后是可挂载的逻辑卷本身。大多数主流 Linux 发行版通常都预装了 LVM2 用户空间工具。如果您发现您的发行版上未安装,请通过您的发行版的软件包仓库下载并安装它。
这个想法在概念上几乎类似于独立磁盘冗余阵列 (RAID),尽管 LVM2 不支持任何奇偶校验驱动的条带化,但它仍然增加了额外的价值。例如,LVM2 允许不间断地添加、删除和更换存储设备。它可以轻松地动态调整卷组和逻辑卷的大小。最重要的是,它支持快照——本文的重点。从 LVM2 开始,快照卷支持写入操作。
如前所述,LVM2 卷使用分层结构——也就是说,必须从物理磁盘设备创建物理卷(或 PV)。这可以使用 pvcreate 命令,后跟要标记为 LVM2 使用的物理分区列表来完成
$ sudo pvcreate /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
对于新标记的物理卷,需要使用 vgcreate 命令创建卷组(或 VG),后跟卷组的名称,然后是要使用的所有物理卷的列表
$ sudo vgcreate vg0 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1 Volume group "vg0" successfully created
默认情况下,卷组位于 /dev 目录路径中。正是在这个卷组中,可以创建逻辑卷(或 LV),格式化文件系统,挂载,进而用于文件 I/O 操作。创建逻辑卷的最佳特性是您可以使用 VG 的部分或全部可用容量。例如,如果需要从 4GB VG 创建 1GB LV,则需要使用 lvcreate 命令,后跟 VG 的名称,然后是 LV 的大小。创建 LV 时,它将在 /dev 目录路径下的卷组名称下创建用于访问的节点名称
$ sudo lvcreate --name /dev/vg0/test_vg --size 1G Logical volume "test_vg" created
上面的示例展示了非冗余 LV 的创建。要创建具有镜像功能的 LV,请使用 -m 选项调用 lvcreate 命令。下面的示例创建了一个 500MB 的镜像 LV
$ sudo lvcreate --size 500M -m1 --name mirrorlv vg0 ↪/dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1 Logical volume "mirrorlv" created
您可以使用 lvremove、vgremove 和 pvremove 命令以及它们各自的卷名称轻松删除逻辑卷、卷组和物理卷
$ sudo lvremove /dev/vg0/test_vg Do you really want to remove active logical volume "test_vg"? [y/n]: y Logical volume "test_vg" successfully removed
请注意,可以使用 lvdisplay、vgdisplay 和 pvdisplay 命令显示所有逻辑卷、卷组和物理卷的列表以及详细的卷信息。
现在我已经简要介绍了 LVM2 的结构和管理方式,现在是时候关注快照功能了。值得注意的是,LVM2 快照功能只能在 LVM2 管理的逻辑卷上使用。假设已经存在 LV,可能是 / 目录路径的分区,则需要创建第二个 LV 用于原始逻辑卷的快照。关于大小,快照的另一个重要特性是快照卷的大小不必等于原始卷的大小。大小甚至可以是原始卷的一半或更小,仅允许备份那么多数据更改。默认情况下,如果快照 LV 被填满,LVM2 将自动禁用快照。所需的存储空间量取决于快照的使用情况。如果快照大小等于原始 LV 的大小,则永远不会溢出,并且快照服务不会中断。在最坏的情况下,如果发现快照上的空间即将耗尽,则始终可以动态地将 LV 调整为更大的容量。
定义要为快照分配的大小。通过使用 lvcreate 命令在所需的 VG 上创建快照,大小后跟快照开关、快照名称和 VG。在此示例中,仅为修改后的数据分配了 500MB。实际上,这不是一个理想的大小(太小了,但在这里可以达到目的)
$ sudo lvcreate -L500M -s -n rootsnapshot /dev/VolGroup/lv_root Logical volume "rootsnapshot" created
lvdisplay 命令显示与快照 LV 相关的所有详细信息。需要注意的一个细节是“已分配给快照”值。在本例中,它设置为 0.06%
$ sudo lvdisplay /dev/VolGroup/rootsnapshot --- Logical volume --- LV Name /dev/VolGroup/rootsnapshot VG Name VolGroup LV UUID kAc3Iq-Gn3e-pBWs-KC9V-bFi8-0fHr-SsdRLR LV Write Access read/write LV snapshot status active destination for /dev/VolGroup/lv_root LV Status available # open 0 LV Size 5.51 GiB Current LE 1410 COW-table size 500.00 MiB COW-table LE 125 Allocated to snapshot 0.06% Snapshot chunk size 4.00 KiB Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 253:3
如果原始 LV 被写入,使用写入时复制机制,快照会将原始卷中的所有原始数据写入快照卷,然后再用新数据替换原始卷。为了更好地理解快照背后的机制,请挂载快照卷,以便可以像访问任何其他挂载设备一样访问它。
列表 1. 挂载和列出启用快照的卷
$ sudo mkdir -p /mnt/VolGroup/rootsnapshot $ sudo mount /dev/VolGroup/rootsnapshot /mnt/VolGroup/rootsnapshot/ $ ls -l /mnt/VolGroup/rootsnapshot/ total 124 dr-xr-xr-x. 2 root root 4096 May 15 07:45 bin drwxr-xr-x. 2 root root 4096 May 15 06:59 boot drwxr-xr-x. 9 root root 4096 Sep 26 06:12 cgroup drwxr-xr-x. 2 root root 4096 May 15 06:59 dev drwxr-xr-x. 116 root root 12288 Sep 26 06:19 etc drwxr-xr-x. 3 root root 4096 May 15 08:10 home dr-xr-xr-x. 17 root root 12288 May 15 07:42 lib drwx------. 2 root root 16384 May 15 06:58 lost+found drwxr-xr-x. 3 root root 4096 Sep 26 06:15 media dr-xr-xr-x. 2 root root 4096 Sep 26 06:13 misc drwxr-xr-x. 3 root root 4096 Dec 4 2009 mnt dr-xr-xr-x. 2 root root 4096 Sep 26 06:13 net drwxr-xr-x. 2 root root 4096 Dec 4 2009 opt drwxr-xr-x. 2 root root 4096 May 15 06:59 proc dr-xr-x---. 4 root root 4096 Aug 31 15:54 root dr-xr-xr-x. 2 root root 12288 May 15 07:48 sbin drwxr-xr-x. 2 root root 4096 May 15 07:02 selinux drwxr-xr-x. 2 root root 4096 Dec 4 2009 srv drwxr-xr-x. 2 root root 4096 May 15 06:59 sys drwxrwxrwt. 15 root root 4096 Sep 26 06:27 tmp drwxr-xr-x. 14 root root 4096 May 15 07:14 usr drwxr-xr-x. 22 root root 4096 May 15 07:48 var
这是一个简单的练习,用于验证快照是否正常工作:写入原始卷——即,修改现有文件或添加/删除文件。这些文件的原始数据将存在于已挂载的快照上。如果从原始卷添加/删除了新文件,则它将不会存在于快照上。请注意,如果修改了快照数据,则应用相同的逻辑。原始卷将保持不变
$ dd if=/dev/zero of=/home/petros/test.file count=65536 65536+0 records in 65536+0 records out 33554432 bytes (34 MB) copied, 2.95349 s, 11.4 MB/s $ ls /home/petros/ Desktop Downloads Music Public test.file Documents drvadm Pictures Templates Videos $ ls /mnt/VolGroup/rootsnapshot/home/petros/ Desktop Downloads Music Public Videos Documents drvadm Pictures Templates
使用 lvdisplay 命令,您现在可以观察到为快照卷分配了更多空间。“已分配给快照”字段的值已增加到 0.24%
$ sudo lvdisplay /dev/VolGroup/rootsnapshot --- Logical volume --- LV Name /dev/VolGroup/rootsnapshot VG Name VolGroup LV UUID kAc3Iq-Gn3e-pBWs-KC9V-bFi8-0fHr-SsdRLR LV Write Access read/write LV snapshot status active destination for /dev/VolGroup/lv_root LV Status available # open 1 LV Size 5.51 GiB Current LE 1410 COW-table size 500.00 MiB COW-table LE 125 Allocated to snapshot 0.24% Snapshot chunk size 4.00 KiB Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 253:3
删除快照几乎与创建快照一样简单。首先,卸载快照,然后使用 lvremove 命令从 VG 中删除 LV
$ sudo umount /mnt/VolGroup/rootsnapshot/ $ sudo lvremove /dev/VolGroup/rootsnapshot
在包括红帽企业 Linux(也在 RHEL 6 的最新 beta 版本中)、CentOS 甚至 SUSE Linux 在内的各种 Linux 发行版的某些版本中,当尝试删除或停用逻辑卷时,存在一个已知问题。无法删除 LV,将返回以下错误消息无法删除打开的逻辑卷“rootsnapshot”。如果在命令行上调用 dmsetup info -c rootsnapshot,将返回 LV 的状态,并且它将确认错误消息。为了解决这个问题,请使用 dmsetup 命令,然后使用 lvremove 命令。使用 lvdisplay 命令确认 LV 已被删除
$ sudo dmsetup remove /dev/mapper/VolGroup-rootsnapshot-cow $ sudo dmsetup remove /dev/mapper/VolGroup-rootsnapshot $ sudo lvremove /dev/VolGroup/rootsnapshot Logical volume "rootsnapshot" successfully removed
在某些情况下,建议确保为快照分配足够的存储空间,或者(如下所述)将包含所有已归档快照数据的备份目录用于恢复目的。要扩展现有的卷组,需要标记一个新的 PV。为此,请识别物理存储设备,并使用 fdisk、sfdisk 或 parted 创建所需的分区大小。通过回读分区表来验证分区。然后,继续创建 PV
$ sudo sfdisk -l /dev/sde Disk /dev/sde: 261 cylinders, 255 heads, 63 sectors/track Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0 Device Boot Start End #cyls #blocks Id System /dev/sde1 0+ 260 261- 2096451 83 Linux /dev/sde2 0 - 0 0 0 Empty /dev/sde3 0 - 0 0 0 Empty /dev/sde4 0 - 0 0 0 Empty $ sudo pvcreate /dev/sde1 Physical volume "/dev/sde1" successfully created
使用 vgextend 命令将新标记的 PV 追加到现有的 VG
$ sudo vgextend VolGroup /dev/sde1 Volume group "VolGroup" successfully extended
如果在某个时候需要从 VG 中删除 PV,请使用 vgreduce 命令,后跟 VG 和 PV 的名称
$ sudo vgreduce VolGroup /dev/sde1
如果正在扩展 VG 以创建备份目录来归档例行快照,请按照正常的 lvcreate 步骤,定义所需 LV 的名称、大小和 VG。然后,使用文件系统格式化 LV,并为了文件 I/O 可访问性,将其挂载到目录路径
$ sudo lvcreate --name backups --size 1G VolGroup Logical volume "backups" created $ sudo mke2fs -j /dev/VolGroup/backups $ sudo mkdir -p /mnt/VolGroup/backups $ sudo mount /dev/VolGroup/backups /mnt/VolGroup/backups
创建快照后,可以使用 tar 命令在新建的备份目录中创建一个归档
$ sudo tar -pczf /mnt/VolGroup/backups/rootsnapshot.tar.gz ↪/mnt/VolGroup/rootsnapshot
在发生故障或需要检索旧版本文件的情况下,可以使用已归档的快照来恢复原始数据内容。当运行高可用性生产环境时,这是一种极其理想的备份策略。无需停机。虽然此备份不一定需要写入文件,但可以使用 tar 或 dd 命令将快照直接写入另一个物理存储设备,包括磁带驱动器
$ sudo tar -cf /dev/st0 /mnt/VolGroup/rootsnapshot
LVM2 预装在一些更常见的基于 Linux 的发行版中。在某些情况下,它甚至被用作默认文件系统布局的一部分。其快照功能是那些鲜为人知的宝藏之一,它可以真正地被用来发挥自己的优势,范围从个人环境到更大规模的环境。这一切只需要一点时间、一点知识和一个关于设计、部署和配置的计划。
资源
LVM HOWTO: tldp.org/HOWTO/LVM-HOWTO/snapshotintro.html
逻辑卷管理器 (维基百科): en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)
快照 (维基百科): en.wikipedia.org/wiki/Snapshot_(computer_storage)
LVM2 项目页面: sourceware.org/lvm2
LVM2 Wiki: sources.redhat.com/lvm2/wiki
已知的 lvremove 错误 (原始编号): https://bugzilla.redhat.com/show_bug.cgi?id=577798
RHEL 6 的已知 lvremove 错误: https://bugzilla.redhat.com/show_bug.cgi?id=638711
Petros Koutoupis 是一名全职 Linux 内核、设备驱动程序和应用程序开发人员,面向嵌入式和服务器平台。他已经在数据存储行业工作了六年多,并且喜欢讨论相同的技术。