TT Lab
开始
学习 学习路径 课程

存储实务 — RAID、快照、iSCSI、fio

用快照回滚、扩容 XFS、缩小 ext4

在 TT Lab 中继续学习

目标

在变更之前创建 LVM 快照,通过合并回滚错误的变更,在线扩容 XFS,在保住数据的前提下离线缩小 ext4,并用精简池制造过量分配。

为什么重要

变更作业是以“出错就回滚”为前提获得批准的。快照能在几秒钟内造出这个前提,但如果大小定得不对,它会在作业过程中悄悄失效;如果不知道回滚的流程(卸载 → 合并 → 重新挂载),凌晨就会手忙脚乱。选择文件系统也是如此——XFS 可以扩容,却按不能缩小来设计,所以给有可能缩小的卷选了什么,决定了以后还有哪些选择。

本实验在 Ubuntu 24.04 VM 中以 root 身份运行。没有空闲磁盘,所以把 3GiB 稀疏文件挂成回环设备来代替磁盘。会话从 60 分钟开始,最多可延长到 180 分钟,会话结束后 VM 会消失。

步骤

  1. 把 /var/lib/sto/lvm.img 创建为 3GiB,挂成回环设备,初始化为 PV,并创建卷组 vg_sto。
  2. 把 600MiB 的 LV lv_app 格式化为 XFS 并挂载到 /srv/app。在 /srv/app/app.conf 中写入 version=1,在 /srv/app/orders.csv 中写入三行以上的 CSV,并把 sha256sum /srv/app/orders.csv 的输出保存到 /root/sto/snap/orders.sha256。
  3. 创建 200MiB 的快照 lv_app_snap,并把 lvs -o lv_name,origin,lv_attr,lv_size vg_sto 的输出保存到 /root/sto/snap/snap.txt。
  4. 错误变更:把 app.conf 改为 version=2,删除 orders.csv,向 /srv/app/junk.bin 写入 60MiB。之后把 lvs -o lv_name,origin,data_percent vg_sto 的输出保存到 /root/sto/snap/usage.txt。
  5. 合并快照进行回滚。lv_app_snap 必须消失,/srv/app 已重新挂载,且满足 version=1、orders.csv 校验和一致、junk.bin 不存在。
  6. 把 lv_app 扩大到 900MiB,并在保持挂载的状态下同时扩容 XFS。
  7. 把 500MiB 的 LV lv_logs 以 ext4 挂载到 /srv/logs,向 /srv/logs/keep.log 写入 5MiB 后,把 sha256sum /srv/logs/keep.log 的输出保存到 /root/sto/snap/keep.sha256。
  8. 把 lv_logs 缩小到 300MiB。文件系统也要一起缩小,已重新挂载,且 keep.log 与校验和一致。
  9. 在 400MiB 的精简池 pool 上创建虚拟大小为 1GiB 的精简卷 lv_thin,并把 lvs -o lv_name,lv_size,pool_lv,data_percent vg_sto 的输出保存到 /root/sto/snap/thin.txt。

参考

在回环设备上建立 VG

把 /var/lib/sto/lvm.img 创建为 3GiB 稀疏文件并挂成回环设备,初始化为 PV 后,仅用这一个 PV 创建卷组 vg_sto。

顺序是 truncate → losetup -f --show → pvcreate → vgcreate。回环编号用 losetup -j <文件> 找回。

XFS 卷和需要保住的数据

在 vg_sto 中创建 600MiB 的 LV lv_app,格式化为 XFS 并挂载到 /srv/app。在 /srv/app/app.conf 中写入一行 version=1,在 /srv/app/orders.csv 中写入三行以上的任意 CSV,并把 sha256sum /srv/app/orders.csv 的输出保存到 /root/sto/snap/orders.sha256。

顺序是 lvcreate -L 600M -n lv_app vg_sto、mkfs.xfs、mount。校验和文件中必须写绝对路径,以后才能用 sha256sum -c 检查。

变更之前的快照

为 lv_app 创建 200MiB 的快照 lv_app_snap。然后把 lvs -o lv_name,origin,lv_attr,lv_size vg_sto 的输出保存到 /root/sto/snap/snap.txt。

lvcreate -s -L <大小> -n <名称> vg_sto/lv_app。快照的 lv_attr 以 s 开头,Origin 列中能看到原卷名称。

错误变更与快照使用率

模拟一次错误变更:把 /srv/app/app.conf 改为 version=2,删除 /srv/app/orders.csv,向 /srv/app/junk.bin 写入 60MiB。之后把 lvs -o lv_name,origin,data_percent vg_sto 的输出保存到 /root/sto/snap/usage.txt。

可以用 dd if=/dev/urandom of=... bs=1M count=60 来写入。写完要执行 sync,快照使用率(Data%)才会反映出来。写入量超过快照大小会使快照失效,所以要守住大小。

用合并回滚

把快照合并到原卷,回到错误变更之前。结束后 lv_app_snap 必须不存在,/srv/app 已重新挂载,app.conf 是 version=1,orders.csv 与校验和一致,junk.bin 不存在。

原卷处于挂载状态时,lvconvert --merge 会推迟到下一次激活。请先卸载,合并之后再重新挂载。

保持挂载状态扩容 XFS

把 lv_app 扩大到 900MiB,并在不卸载的情况下同时扩容 XFS。用 df 看到的 /srv/app 必须变大。

lvextend -r 会在扩大 LV 后调用适合该文件系统的工具(XFS 则是 xfs_growfs)。xfs_growfs 只能在挂载状态下工作。

创建可以缩小的卷

在 vg_sto 中创建 500MiB 的 LV lv_logs,格式化为 ext4 并挂载到 /srv/logs。向 /srv/logs/keep.log 写入 5MiB 随机数据,并把 sha256sum /srv/logs/keep.log 的输出保存到 /root/sto/snap/keep.sha256。

流程与第 2 步相同,只是文件系统换成 ext4。下一步要缩小这个卷。

在保住数据的前提下缩小 ext4

把 lv_logs 缩小到 300MiB。文件系统也必须一起缩小,结束后 /srv/logs 已重新挂载,且 keep.log 与校验和一致。

ext4 只能在卸载状态下缩小。顺序很重要——先把文件系统缩到比目标更小(需要先执行 e2fsck -f),然后缩小 LV,最后再把文件系统调整到与 LV 相同的大小。

精简池与过量分配

在 vg_sto 中创建 400MiB 的精简池 pool,并在该池上创建虚拟大小为 1GiB 的精简卷 lv_thin。把 lvs -o lv_name,lv_size,pool_lv,data_percent vg_sto 的输出保存到 /root/sto/snap/thin.txt。

用 lvcreate --type thin-pool -L 创建池,用 lvcreate -V <虚拟大小> -T vg_sto/pool -n <名称> 创建精简卷。创建比池更大的卷时会出现过量分配警告,这正是本步要看的东西。