如何在沒有 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 相同的「引導鏈」。重新啟動後,我檢查了一下mount,儘管原始根仍然被使用

  • /etc/fstab已經升級
  • /boot/grub/grub.cfg已經升級
  • initramfs已經升級

目前配置

  • 1TB RAID1md0
  • 4TB RAID1md1
  • 光電開啟md0
  • 光電開啟md1p1
  • VGvg0與兩個 PV
  • LVroot作為原始根檔案系統(UUID xxx
  • LVnewroot作為臨時根檔案系統(UUID yyy
  • ext4 上vg0-root(UUID aaa)
  • ext4 上vg0-newroot(UUID bbb)

/etc/fstab進行了相應更改(替換了設備映射器路徑)。

到目前為止,我已將整個舊根同步aaa到 newroot ,我用and inbbb替換了每次出現的 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根分區進行硬編碼:

當無法傳遞根引導參數時,允許可選的根引導參數硬編碼。根 bootarg 會覆寫該特殊設定。

但由於我的這個設定中有一個 root 的 bootarg ,所以grub.cfg應該不會生效。

為了在下次啟動時使用另一個 UUID 作為 root,還需要設定什麼?

答案1

原來我忘了替換 root= bootarg /boot/grub/grub.cfg...

為了完整起見:

如何在沒有 Live 系統的情況下透過 SSH 將根分區移至 LVM 中的另一個 PV

注意:請務必備份重要資料!此方法是一種 hack,不應在生產系統上使用。無論如何,在 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將取代每一個匹配文字的出現,因此建議手動進行這些更改,因為替換rootGRUB 或 fstab 配置中其他地方使用的單字將使其無效!

我建議使用nano( CTRL+W) 搜尋 VG 和 LV 名稱並手動替換它們。也建議搜尋光伏設備名稱,以防萬一...

克隆根卷

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 中做到這一點 - 我嘗試使用的工具對我來說不起作用。

相關內容