Как переместить корневой раздел на другой PV в LVM через SSH без Live-системы

Как переместить корневой раздел на другой PV в LVM через SSH без Live-системы

Как изменить корневой раздел, с которого будет загружаться Debian 10?

Я хотел бы уменьшить размер моей корневой файловой системы, которая находится на логическом томе LVM, удаленно, то есть только по SSH и без загрузки с Live CD.

Поскольку мы не можем уменьшить размер rootfs, пока она смонтирована, я решил просто клонировать существующую rootfs, загрузиться в нее и изменить размер оттуда, затем загрузиться в исходную rootfs и удалить временную.

Я попробовал в виртуальной машине с Ubuntu Server 18.04, поскольку, насколько мне известно, он использует ту же самую "boot-chain", что и Debian 10. Однако мне не удалось надежно установить клонированный раздел как root. После перезагрузки я проверил с помощью mountи оригинальный root все еще используется, хотя

  • /etc/fstabбыл обновлен
  • /boot/grub/grub.cfgбыл обновлен
  • initramfsбыл обновлен

Текущая конфигурация

  • 1ТБ RAID1md0
  • 4ТБ RAID1md1
  • PV наmd0
  • PV наmd1p1
  • VG vg0с обоими PV
  • LV rootкак исходная корневая файловая система (UUID xxx)
  • LV newrootкак временная корневая файловая система (UUID yyy)
  • ext4 на vg0-root(UUID aaa)
  • ext4 на vg0-newroot(UUID bbb)

/etc/fstabбыл соответствующим образом изменен (заменен путь к устройству-картографу).

На данный момент я выполнил rsync-синхронизацию всего старого корня aaaс новым корнем bbb, заменил все вхождения UUID aaaи xxxна bbbи yyyв /boot/grub/grub.cfg(Примечание: я не использую grub2загрузку UEFI).

initramfsбыл обновлен с помощью update-initramfs -u(после исправления /etc/initramfs-tools/conf.d/resume).

Именно в таком порядке. Но мои тесты в виртуальной машине либо загружались прямо в старый корень, либо перебрасывали меня в спасательную оболочку GRUB.

update-grubраспознал newrootтом и добавил соответствующие записи в grub.cfg, выбрав их вручную при загрузке моей тестовой виртуальной машины (невозможно через SSH...), также загрузил старый корень.

Я также видел, что есть ROOTвозможность /etc/initramfs-tools/initramfs.confжестко закодировать корневой раздел:

Позволяет использовать необязательный root bootarg в жестком коде, когда root bootarg не может быть передан. Корневой bootarg переопределяет эту специальную настройку.

Но поскольку в моем случае есть загрузчик root, grub.cfgэта настройка не должна вступить в силу.

Что еще нужно настроить, чтобы использовать другой UUID в качестве root при следующей загрузке?

решение1

Оказывается, я забыл заменить root= bootarg в /boot/grub/grub.cfg...

Для полноты картины:

Как переместить корневой раздел на другой PV в LVM через SSH без Live-системы

Примечание: Всегда делайте резервные копии важных данных! Этот метод является хаком и не должен использоваться в производственных системах. В любом случае данные, записанные в период между клонированием 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 = UUID старого PV
  • $pv1uuid = UUID нового PV
  • $vg{0,1}uuid = UUID {старой, новой} VG
  • $lv{0,1}UUID = UUID {старого,нового} LV
  • $root{0,1}UUID = UUID корневой файловой системы {old,new}
  • $vg{0,1} = Имя {старого,нового} VG
  • $lv{0,1} = Имя {старого,нового} LV

И /etc/grub/grub.cfgбудет представлен как $grubcfg. Для систем UEFI это, скорее всего /boot/grub2/grub.cfg, .

Я рекомендую установить их как переменные при bashиспользовании pv0uuid=xxxxxx-xxxx..., чтобы можно было копировать и вставлять приведенные ниже команды.

Установить новый root в конфигурации 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. Проверьте снимок.
  3. Измените размер снимка (уменьшите его) и убедитесь, что между верхней частью файловой системы и границей целевого размера логического тома есть некоторый буфер — просто чтобы перестраховаться.
  4. Обратно объедините снимок с вашим корневым томом rootfs.
  5. Перезагрузка. На этом этапе фактически происходит слияние (вероятно, во время загрузки).
  6. После перезагрузки уменьшите том rootfs и, возможно, снова измените размер rootfs, чтобы он заполнил все пространство до верха LV.

Есть один недостаток: вы потеряете часть данных между шагами 1 и 5, и у вас МОГУТ возникнуть некоторые несоответствия (в зависимости от используемой файловой системы) на шаге 1, поскольку вы делаете снимок в работающей файловой системе.

Удивительно, но мне это помогло.

В идеальном мире шаг 1 должен быть выполнен во время загрузки, до перемонтирования rootfs rw, чтобы снимок был чистым. Я не понял, как это сделать из dracut - инструменты, которые я пытался использовать, не работали у меня.

Связанный контент