如何在没有 Live 系统的情况下通过 SSH 将根分区移动到 LVM 中的另一个 PV

如何在没有 Live 系统的情况下通过 SSH 将根分区移动到 LVM 中的另一个 PV

如何更改 Debian 10 的启动根分区?

我想从远程减小位于 LVM 逻辑卷上的根文件系统的大小,这仅通过 SSH 进行,而无需启动到 Live CD。

因为我们无法在安装时缩小 rootfs,所以我认为我只需克隆现有的 rootfs,启动到该 rootfs 并从那里进行调整大小,然后启动到原始 rootfs 并删除临时 rootfs。

我尝试在虚拟机中使用 Ubuntu Server 18.04,因为据我所知,它使用与 Debain 10 相同的“启动链”。但是,我无法可靠地将克隆的分区设置为 root。重新启动后,我检查了一下mount,发现原始 root 仍在使用,尽管

  • /etc/fstab已经升级
  • /boot/grub/grub.cfg已经升级
  • initramfs已经升级

当前配置

  • 1TB RAID1md0
  • 4TB RAID1md1
  • 光伏开启md0
  • 光伏开启md1p1
  • vg0具有两个 PV 的VG
  • LVroot作为原始根文件系统 (UUID xxx)
  • LVnewroot作为临时根文件系统 (UUID yyy)
  • ext4 开启vg0-root(UUID aaa)
  • ext4 开启vg0-newroot(UUID bbb)

/etc/fstab已相应更改(替换设备映射器路径)。

到目前为止,我已经将整个旧根 rsyncaaa到新根,我用和替换bbb了每个出现的 UUIDaaa和(注意:我没有使用或 UEFI 启动)。xxxbbbyyy/boot/grub/grub.cfggrub2

initramfs已使用 进行更新update-initramfs -u(修复后/etc/initramfs-tools/conf.d/resume)。

按照这个顺序。但我在虚拟机中的测试要么直接启动到旧根目录,要么让我进入 GRUB 救援 shell。

update-grub识别newroot卷并在中添加匹配的条目grub.cfg,在我的测试虚拟机启动时手动选择它们(无法通过 SSH 实现......)也启动了旧的根。

我还看到了ROOT/etc/initramfs-tools/initramfs.conf根分区进行硬编码的选项:

当无法传递任何 root bootarg 时,允许可选的 root bootarg 硬编码。root bootarg 会覆盖该特殊设置。

但是由于我的系统中有一个 root 的 bootarg,因此grub.cfg此设置不会生效。

为了在下次启动时使用另一个 UUID 作为 root,还需要配置什么?

答案1

原来我忘了替换 root= bootarg /boot/grub/grub.cfg...

为了完整起见:

如何在没有 Live 系统的情况下通过 SSH 将根分区移动到 LVM 中的另一个 PV

注意:务必备份重要数据!此方法是一种破解方法,不应在生产系统上使用。无论如何,在 LV 克隆和从新根分区启动之间写入的数据将始终丢失。

在其他磁盘上创建新的 LVM

fdisk /dev/sdb #Create new partition for PV (sdb1)
pvcreate /dev/sdb1
vgcreate vg1 /dev/sdb1
lvcreate -n newroot -L10G vg1 #Size has to be larger than effective usage on current root
mkfs.ext4 -L newroot /dev/mapper/vg1-newroot

收集有关新 LVM 的信息

lvdisplay
vgdisplay
pvdisplay
blkid

以下命令将引用此处提供的信息:

  • $pv0uuid = 旧 PV 的 UUID
  • $pv1uuid = 新 PV 的 UUID
  • $vg{0,1}uuid = {旧,新} VG 的 UUID
  • $lv{0,1}UUID = {旧,新} LV 的 UUID
  • $root{0,1}UUID = {old,new} 根文件系统的 UUID
  • $vg{0,1} = {旧,新} VG 的名称
  • $lv{0,1} = {旧,新} LV 的名称

并将/etc/grub/grub.cfg呈现为$grubcfg。对于 UEFI 系统,这很可能是/boot/grub2/grub.cfg

bash我建议在使用时将这些设置为变量pv0uuid=xxxxxx-xxxx...,以便可以复制粘贴下面的命令。

在 GRUB 配置中设置新根

这些命令将替换 GRUB 配置中的文本:

sed -i "s/$pv0uuid/$pv1uuid/g" $grubcfg
sed -i "s/$vg0uuid/$vg1uuid/g" $grubcfg
sed -i "s/$lv0uuid/$lv1uuid/g" $grubcfg
sed -i "s/$root0uuid/$root1uuid/g" $grubcfg
sed -i "s/$vg0/$vg1/g" $grubcfg #BEWARE COMMON NAMES
sed -i "s/$lv0/$lv1/g" $grubcfg #BEWARE COMMON NAMES
sed -i "s/\/dev\/mapper\/$vg0-$lv0/\/dev\/mapper\/$vg1-$lv1/g" /etc/fstab #BEWARE COMMON NAMES

小心常见名称sed将取代每一个匹配文本的出现,因此建议手动进行这些更改,因为替换root在 GRUB 或 fstab 配置的其他地方使用的单词将使其无效!

我建议使用nano并搜索(CTRL+W)VG 和 LV 名称并手动替换它们。还建议搜索 PV 设备名称,以防万一……

克隆根卷

mount /dev/mapper/$vg1-$lv1 /mnt
rsync -rAa --one-file-system / /mnt/
umount /mnt

重启

重启(并祈祷)。验证新的 LV 是否已安装到/

删除旧的 LVM

lvremove /dev/$vg0/*
vgremove $vg0
pvremove /dev/sda2 #Path to $pv0uuid

清理

可选,但建议

  • 最后删除旧的 VG /etc/lvm/archive,否则每次启动时都会搜索它并导致延迟
  • update-grub
  • update-initramfs -u

笔记

在 Ubuntu 18.04 上测试,其他发行版可能会以不同的方式处理 GRUB 配置(关于 UUID 与设备路径和更新命令)。

显然,请事先停止所有不必要的服务以尽量减少数据丢失。

可能有一种方法可以避免(大多数)数据丢失,即使用 systemd 目标、自定义脚本和 LVM 快照。在重启之前的最后一刻,必须再次同步数据$lv0。超出了本文的范围...$lv1

如果/boot不是单独的分区,请$grubcfg在重新启动之前仔细检查新的根目录。

答案2

不确定这是否会对您有帮助,但以下是我成功尝试缩小 LV 上的根分区的方法:

  1. 创建根分区快照。确保它已分配一些空间,因为您将对其进行更改。
  2. fsck 快照。
  3. 调整快照大小(缩小它)并确保在文件系统顶部和 LV 目标大小边界之间有一些缓冲区 - 只是为了安全起见。
  4. 将快照合并回你的 rootfs LV。
  5. 重启。此时合并实际上已经完成(可能是在启动期间)。
  6. 重新启动后 - 缩小 rootfs 卷并可能再次调整 rootfs 大小 - 这样它会填充 LV 顶部的任何空间。

有一个缺点:您将在步骤 1 和步骤 5 之间丢失一些数据,并且您可能会在步骤 1 中遇到一些不一致的情况(取决于正在使用的 FS)-因为您在实时文件系统上创建了快照。

对于我来说它的效果出奇的好。

在理想情况下,步骤 1 将在启动期间完成,在重新/安装 rootfs rw 之前完成,因此快照是干净的。我还没有弄清楚如何从 dracut 执行此操作 - 我尝试使用的工具在那里不起作用。

相关内容