用快照回滚、扩容 XFS、缩小 ext4
目标
在变更之前创建 LVM 快照,通过合并回滚错误的变更,在线扩容 XFS,在保住数据的前提下离线缩小 ext4,并用精简池制造过量分配。
为什么重要
变更作业是以“出错就回滚”为前提获得批准的。快照能在几秒钟内造出这个前提,但如果大小定得不对,它会在作业过程中悄悄失效;如果不知道回滚的流程(卸载 → 合并 → 重新挂载),凌晨就会手忙脚乱。选择文件系统也是如此——XFS 可以扩容,却按不能缩小来设计,所以给有可能缩小的卷选了什么,决定了以后还有哪些选择。
本实验在 Ubuntu 24.04 VM 中以 root 身份运行。没有空闲磁盘,所以把 3GiB 稀疏文件挂成回环设备来代替磁盘。会话从 60 分钟开始,最多可延长到 180 分钟,会话结束后 VM 会消失。
步骤
- 把
/var/lib/sto/lvm.img创建为 3GiB,挂成回环设备,初始化为 PV,并创建卷组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。 - 创建 200MiB 的快照
lv_app_snap,并把lvs -o lv_name,origin,lv_attr,lv_size vg_sto的输出保存到/root/sto/snap/snap.txt。 - 错误变更:把
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。 - 合并快照进行回滚。
lv_app_snap必须消失,/srv/app已重新挂载,且满足version=1、orders.csv校验和一致、junk.bin不存在。 - 把
lv_app扩大到 900MiB,并在保持挂载的状态下同时扩容 XFS。 - 把 500MiB 的 LV
lv_logs以 ext4 挂载到/srv/logs,向/srv/logs/keep.log写入 5MiB 后,把sha256sum /srv/logs/keep.log的输出保存到/root/sto/snap/keep.sha256。 - 把
lv_logs缩小到 300MiB。文件系统也要一起缩小,已重新挂载,且keep.log与校验和一致。 - 在 400MiB 的精简池
pool上创建虚拟大小为 1GiB 的精简卷lv_thin,并把lvs -o lv_name,lv_size,pool_lv,data_percent vg_sto的输出保存到/root/sto/snap/thin.txt。
参考
- 快照:
lvcreate -s -L 200M -n lv_app_snap vg_sto/lv_app,回滚:lvconvert --merge。 - 扩容:
lvextend -r -L 900M vg_sto/lv_app。缩小:e2fsck -f→resize2fs <작게>(占位符为比目标更小的大小)→lvreduce→resize2fs。 - 精简:
lvcreate --type thin-pool、lvcreate -V 1G -T vg_sto/pool -n lv_thin。 - 常见错误 1:挂载状态下执行
lvconvert --merge,然后纳闷“怎么没有回滚”——这是合并被推迟到下一次激活了。 - 常见错误 2:先
lvreduce再resize2fs——文件系统的末尾会被截掉。
在回环设备上建立 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 <名称> 创建精简卷。创建比池更大的卷时会出现过量分配警告,这正是本步要看的东西。