Клонирование ОС под шифрованным LVM на меньший по объему диск

В рабочих процессах клонирование Linux-хостов для меня стало обычным делом. Но однажды пришлось клонировать сервер с LVM и шифрованием LUKS на меньший по объему диск. И оказалось не все так просто.

Прошу заметить, у меня работал этот метод исключительно на железных серверах. На KVM с qcow2 дисками это сделать не получилось, система после разблокировки LUKS сваливалась в initframfs с ошибками, что отсутствует /bin и /sbin. Это последствия клонирования с ошибками, возможно надо использовать другие инструменты, например dd.

Ошибки, с которыми я столкнулся на виртуальных машинах

Дано:

  • Сервер Debian debian-src с шифрованным LVM на диске sda объемом 20GB, который занят на ~3GB.

  • Чистый диск sdb объемом 15GB, на который необходимо перенести debian-src

Что не так с шифрованным LVM?

В самом начале я даже и не думал, что что-то может пойти не так, посему просто загрузился с Clonezilla, через режим Expert указал флаг -icds, который пропускает проверку размера диска назначения. Что позволяет склонировать диск большого объема на диск меньшего объема при условии, что больший диск использует место, не превышающее объем меньшего диска.

Но под конец клонирования я столкнулся с ошибкой нехватки места на диске назначения:

3016a2eca6e2b43fb71b0d570341b855.png

И тут стало ясно: LVM не позволяет просто так склонировать диск, его нужно уменьшать, сложности добавило наличие шифрование LUKS.

Как уменьшить шифрованный LVM?

Для начала загружаемся с Live-CD на debian-src (У меня под рукой был Linux Mint)

  1. Расшифровываем LUKS /dev/sda5, даем тому название enc и выводим информацию по PV (физическим томам) и LV (логическим томам)

root@mint:~# cryptsetup open /dev/sda5 enc
Enter passphrase for /dev/sda5: 

root@mint:~# pvs
  PV              VG            Fmt  Attr PSize  PFree
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 44.00m

root@mint:~# lvs
  LV     VG            Attr       LSize
  root   debian-src-vg -wi-ao---- <18.51g
  swap_1 debian-src-vg -wi-a----- 976.00m

root@mint:~# df -h /dev/mapper/debian--src--vg-root
Filesystem                        Size  Used Avail Use%
/dev/mapper/debian--src--vg-root   19G  1.3G   16G   8%

Видим, что PV полностью заполнен, а в LV корня свободно 16GB, необходимо PV уменьшить.

  1. Начинаем уменьшать объем LV debian--src--vg-root. Уменьшать будем все на 10GB.

root@mint:~# lvresize --resize -y -L -10G /dev/debian-src-vg/root
Do you want to unmount "/media/mint/39551c0b-2da8-4303-8de5-65e7d6c552e9" ? [Y|n] y
fsck from util-linux 2.34
resize2fs 1.45.5 (07-Jan-2020)
Resizing the filesystem on /dev/mapper/debian--src--vg-root to 2230272 (4k) blocks.
The filesystem on /dev/mapper/debian--src--vg-root is now 2230272 (4k) blocks long.

  Size of logical volume debian-src-vg/root changed from <18.51 GiB (4738 extents) to <8.51 GiB (2178 extents).
  Logical volume debian-src-vg/root successfully resized.

Ключ -y разрешает размонтировать LV перед началом ресайза

  1. Если у вас есть swap, то после 2 шага у нас останется свободное пространство между LV root и swap. Давайте удалим его.

root@mint:~# pvs -v --segments
  PV              VG            Fmt  Attr PSize  PFree  Start SSize LV     Start Type   PE Ranges                
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 10.04g     0  2178 root       0 linear /dev/mapper/enc:0-2177   
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 10.04g  2178  2560            0 free                            
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 10.04g  4738   244 swap_1     0 linear /dev/mapper/enc:4738-4981
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 10.04g  4982    11            0 free                            

root@mint:~# pvmove --alloc anywhere /dev/mapper/enc:4738-4981
  /dev/mapper/enc: Moved: 2.87%
  /dev/mapper/enc: Moved: 100.00%

Обращаем внимание на PE Ranges и видим, что между LV root и swap_1 есть свободное пространство, перемещаем swap /dev/mapper/enc:4738-4981 поближе к root.

После перемещения видим, что свободное пространство переместилось в конец:

root@mint:~# pvs -v --segments
  PV              VG            Fmt  Attr PSize  PFree  Start SSize LV     Start Type   PE Ranges                
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 10.04g     0  2178 root       0 linear /dev/mapper/enc:0-2177   
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 10.04g  2178   244 swap_1     0 linear /dev/mapper/enc:2178-2421
  /dev/mapper/enc debian-src-vg lvm2 a--  19.50g 10.04g  2422  2571            0 free 
  1. Начинаем уменьшать LUKS партицию. В первую очередь посмотрим размер:

root@mint:~# cryptsetup status enc
/dev/mapper/enc is active and is in use.
  type:    LUKS2
  cipher:  aes-xts-plain64
  keysize: 512 bits
  key location: keyring
  device:  /dev/sda5
  sector size:  512
  offset:  32768 sectors
  size:    40906752 sectors
  mode:    read/write

Нужное нам значение — size: 40906752 sectors
Воспользуемся формулой вычитания объема LUKS-партиции:
LUKS_size_sectors - значение_уменьшения_в_гб * 1024 * 1024 * 2 = значение для cryptsetup resize

Я уменьшаю LUKS на 10GB, значения в моем случае: 40906752-10*1024*1024*2=19935232

root@mint:~# cryptsetup resize enc -b 19935232
Enter passphrase for /dev/sda5:

Выведем информацию о LUKS партиции, она нам пригодится позже. Нас интересует offset и size:

root@mint:~# cryptsetup status enc
/dev/mapper/enc is active and is in use.
  ...
  offset:  32768 sectors
  size:    19935232 sectors
  ...
  1. Деактивируем VG (Группу томов) и закрываем LUKS.

root@mint:~# vgchange -a n debian-src-vg
  WARNING: Device /dev/mapper/enc has size of 19935232 sectors which is smaller than corresponding PV size of 40906752 sectors. Was device resized?
  WARNING: One or more devices used as PVs in VG debian-src-vg have changed sizes.
  0 logical volume(s) in volume group "debian-src-vg" now active

root@mint:~# cryptsetup close enc

Учтите, все LV должны быть отмонтированы, иначе получите ошибку.
Если после этого шага вы примонтируете LUKS обратно, то будет необходимо повторить шаги 4 и 5.

Видим предупреждение о том, что LUKS партиция меньше, чем PV в VG debian-src-vg. Это мы починим чуть позже.

  1. Начинаем уменьшать саму партицию диска sda5, потому что там располагается корень системы.

root@mint:~# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0    7:0    0  1.9G  1 loop /rofs
sda      8:0    0   20G  0 disk 
├─sda1   8:1    0  487M  0 part 
├─sda2   8:2    0    1K  0 part 
└─sda5   8:5    0 19.5G  0 part

root@mint:~# parted /dev/sda
GNU Parted 3.3
Using /dev/sda
(parted) unit s                                                           
(parted) p                                                                
Model: ATA QEMU HARDDISK (scsi)
Disk /dev/sda: 41943040s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start     End        Size       Type      File system  Flags
 1      2048s     999423s    997376s    primary   ext2         boot
 2      1001470s  41940991s  40939522s  extended
 5      1001472s  41940991s  40939520s  logical

Воспользуемся формулой вычисления нового размера партиции: NEW_PARTITION_SECTOR_END = PARTITION_SECTOR_START + (LUKS_SIZE_SECTORS + LUKS_OFFSET_SECTORS) - 1

Значения в моем случае: 1001472+(19935232+32768)-1=20969471

(parted) resizepart 5 20969471
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? yes                                                               
(parted) q                                                                
Information: You may need to update /etc/fstab.
  1. Монтируем LUKS, активируем VG и видим, что у нас получилось сжать диски. Но ошибка, что LUKS партиция меньше, чем PV в debian-src-vg осталась, сейчас мы ее устраним.

root@mint:~# cryptsetup luksOpen /dev/sda5 enc
Enter passphrase for /dev/sda5: 
root@mint:~# vgchange -a y debian-src-vg
  WARNING: Device /dev/mapper/enc has size of 19935232 sectors which is smaller than corresponding PV size of 40906752 sectors. Was device resized?
  WARNING: One or more devices used as PVs in VG debian-src-vg have changed sizes.
  2 logical volume(s) in volume group "debian-src-vg" now active

root@mint:~# lsblk
NAME                         MAJ:MIN RM  SIZE RO TYPE
sda                            8:0    0   20G  0 disk  
├─sda1                         8:1    0  487M  0 part  
├─sda2                         8:2    0    1K  0 part  
└─sda5                         8:5    0  9.5G  0 part  
  └─enc                      253:0    0  9.5G  0 crypt 
    ├─debian--src--vg-root   253:1    0  8.5G  0 lvm
    └─debian--src--vg-swap_1 253:2    0  976M  0 lvm   
  1. Уменьшаем размер PV, а также максимально расширим LV root в пределах уменьшенного PV.

root@mint:~# pvresize /dev/mapper/enc
  WARNING: Device /dev/mapper/enc has size of 19935232 sectors which is smaller than corresponding PV size of 40906752 sectors. Was device resized?
  WARNING: One or more devices used as PVs in VG debian-src-vg have changed sizes.
  Physical volume "/dev/mapper/enc" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized              
                                 
root@mint:~# lvresize -l +100%FREE /dev/debian-src-vg/root 
  Size of logical volume debian-src-vg/root changed from <8.51 GiB (2178 extents) to 8.55 GiB (2189 extents).
  Logical volume debian-src-vg/root successfully resized.
  
root@mint:~# e2fsck -f /dev/debian-src-vg/root
e2fsck 1.45.5 (07-Jan-2020)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/debian-src-vg/root: 37219/561936 files (1.4% non-contiguous), 408261/2230272 blocks

root@mint:~# resize2fs /dev/debian-src-vg/root
resize2fs 1.45.5 (07-Jan-2020)
Resizing the filesystem on /dev/debian-src-vg/root to 2241536 (4k) blocks.
The filesystem on /dev/debian-src-vg/root is now 2241536 (4k) blocks long.
  1. Посмотрим как изменился размер наших дисков, PV и LV. С 19.5G мы уменьшили диск до 9.5G, ровно на 10 гигабайт.

root@mint:~# lsblk
NAME                         MAJ:MIN RM   SIZE RO TYPE
sda                            8:0    0    20G  0 disk  
├─sda1                         8:1    0   487M  0 part  
├─sda2                         8:2    0     1K  0 part  
└─sda5                         8:5    0   9.5G  0 part  
  └─enc                      253:0    0   9.5G  0 crypt 
    ├─debian--src--vg-root   253:1    0   8.6G  0 lvm   
    └─debian--src--vg-swap_1 253:2    0   976M  0 lvm   

root@mint:~# pvs
  PV              VG            Fmt  Attr PSize PFree
  /dev/mapper/enc debian-src-vg lvm2 a--  9.50g    0 

root@mint:~# lvs
  LV     VG            Attr       LSize   
  root   debian-src-vg -wi-a-----   8.55g
  swap_1 debian-src-vg -wi-a----- 976.00m
  1. На этом мы закончили все манипуляции с размерностью дисков. Осталось дело за малым — взять Live CD Clonezilla и, как обычно, склонировать диск в экспертном режиме со флагом -icds

Процесс клонирования

  1. Загружаемся в Clonezilla, выбираем клонирование device-device, режим Expert, disk_to_local_disk

  2. Выбираем наш уменьшенный sda как Source disk.

  1. Ставим флаг -icds

Позволяет склонировать диск большого объема на диск меньшего объема при условии, что больший диск использует место, не превышающее  объем меньшего диска.

Позволяет склонировать диск большого объема на диск меньшего объема при условии, что больший диск использует место, не превышающее объем меньшего диска.

  1. На этапе клонирования таблицы разметки, выбирайте флаг -k0, чтобы таблица склонировалась с Source диска.

  2. Подтверждаем, что хотим склонировать на выбранный нам sdb диск и ждем окончания клонирования.

Увеличиваем размер диска

После клонирования необходимо расширить второй диск, на который мы склонировали ОС (в моем случае это sdb)

  1. Загружаемся в Live CD, разблокируем LUKS и проверяем диски. Видим, что скопировалась таблица разделов и система.

root@mint:~# cryptsetup open /dev/sdb5 enc
Enter passphrase for /dev/sdb5:

root@mint:~# lsblk
NAME    MAJ:MIN RM   SIZE RO TYPE 
sda       8:0    0    20G  0 disk  
├─sda1    8:1    0   487M  0 part  
├─sda2    8:2    0     1K  0 part  
└─sda5    8:5    0   9.5G  0 part  
sdb       8:16   0    15G  0 disk  
├─sdb1    8:17   0   487M  0 part  
├─sdb2    8:18   0     1K  0 part  
└─sdb5    8:21   0   9.5G  0 part  
  └─enc 253:0    0   9.5G  0 crypt
  1. Попробуем расширить LUKS на максимум.

root@mint:~# cryptsetup -v resize 'enc'
Enter passphrase for /dev/sdb5: 
Key slot 0 unlocked.
Command successful.

root@mint:~# lsblk
NAME    MAJ:MIN RM   SIZE RO TYPE
...
sdb       8:16   0    15G  0 disk  
├─sdb1    8:17   0 365.3M  0 part  
├─sdb2    8:18   0     1K  0 part  
└─sdb5    8:21   0  14.7G  0 part  
  └─enc 253:0    0  14.6G  0 crypt 

Теперь мы видим как sdb5 и enc расширены насколько это возможно

Спойлер: через GParted у вас расширить не получится — выдает ошибку на команде cryptsetup -v resize

  1. Посмотрим информацию о PV и замечаем, что PV enc все еще остался размером в 9.5GiB. Нужно это исправить.

root@mint:~# pvdisplay -m
  --- Physical volume ---
  PV Name               /dev/mapper/enc
  VG Name               debian-src-vg
  PV Size               9.50 GiB / not usable 0
...
  1. Изменяем размер PV.

root@mint:~# pvresize /dev/mapper/enc 
  Physical volume "/dev/mapper/enc" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized
  1. Проверяем размер LV, видим что корень тоже еще не расширен. Изменяем размер LV.

root@mint:~# lvs
  LV     VG            Attr       LSize   
  root   debian-src-vg -wi-------   8.55g                                                    
  swap_1 debian-src-vg -wi------- 976.00m

root@mint:~# lvresize -l +100%FREE /dev/debian-src-vg/root
  Size of logical volume debian-src-vg/root changed from 8.55 GiB (2189 extents) to 13.67 GiB (3500 extents).
  Logical volume debian-src-vg/root successfully resized.
  1. Проверяем файловую систему и изменяем размер корня

root@mint:~# e2fsck -y /dev/debian-src-vg/root
...
/dev/debian-src-vg/root: ***** FILE SYSTEM WAS MODIFIED *****
/dev/debian-src-vg/root: 24777/561936 files (1.5% non-contiguous), 293922/2241536 blocks

root@mint:~# resize2fs /dev/debian-src-vg/root
resize2fs 1.45.5 (07-Jan-2020)
Resizing the filesystem on /dev/debian-src-vg/root to 3584000 (4k) blocks.
The filesystem on /dev/debian-src-vg/root is now 3584000 (4k) blocks long.
  1. Проверяем размер диска, PV и LV

root@mint:~# lsblk
NAME                         MAJ:MIN RM   SIZE RO TYPE
...
sdb                            8:16   0    15G  0 disk  
├─sdb1                         8:17   0 365.3M  0 part  
├─sdb2                         8:18   0     1K  0 part  
└─sdb5                         8:21   0  14.7G  0 part  
  └─enc                      253:0    0  14.6G  0 crypt 
    ├─debian--src--vg-root   253:1    0  13.7G  0 lvm   
    └─debian--src--vg-swap_1 253:2    0   976M  0 lvm   

root@mint:~# pvs
  PV              VG            Fmt  Attr PSize  PFree
  /dev/mapper/enc debian-src-vg lvm2 a--  14.62g    0 

root@mint:~# lvs
  LV     VG            Attr       LSize
  root   debian-src-vg -wi-a-----  13.67g
  swap_1 debian-src-vg -wi-a----- 976.00m

Все! Теперь мы можем запускаться с нового диска. У меня есть пару серверов, которые я копировал таким образом и они стабильно работают больше полугода.
Эту статью я решил выложить на хабр из-за большого объема, более мелкие заметки я оставляю в своем тг-канале https://t.me/sdnv_funkhole.

Ссылки на ресурсы, которые помогли мне с этой задачей:

© Habrahabr.ru