Cài đặt OS trên Logical volume

Sau khi dùng Raspberry Pi Imager ghi file ảnh của OS vào đĩa như bình thường, chúng ta sẽ chuyển OS trên partition rootfs vào LV.

Việc chuyển phần cài đặt thì đơn giản nhưng các driver của LVM ngay khi khởi động phải được nạp để có thể làm việc với rootfs trên LV. Khi khởi động Raspberry Pi nạp một ramdisk cho initrd, vì vậy chúng ta chỉ phải bổ sung initram chứa các driver cho LVM.

Chuẩn bị

  • RPi 4
  • 2 đĩa khởi động PiOS, trong đó 1 đĩa sẽ được chuyển PiOS sang logical volume
  • Wifi

Ghi file ảnh vào đĩa

Sau khi chọn OS và đĩa (SD card), chúng ta chọn thêm phần Options bằng cách bấm vào nút hình bánh xe. Sau khi ghi file ảnh vào đĩa, Raspberry Pi Imager sẽ làm thêm vài cài đặt đã được chỉ định, bao gồm: đặt hostname, cho phép ssh, mật khẩu của pi, cài đặt wifi… Chú ý là Raspberry Pi 4 hỗ trợ wifi 5G nên nhanh hơn mạng LAN 100Mps.

Thay đổi phần khởi động của RPi

Khởi động từ đĩa mới tạo, ta gọi theo hostname là đĩa mail.example.net, cập nhật hệ thống, sau đó cài thêm LVM

sudo apt update && sudo apt -y upgrade
sudo apt install lvm2

initramfs-tools đã có sẵn trong hệ thống, tuy nhiên nếu chưa có thì cài thêm

sudo apt install initramfs-tools

Tiếp theo xem phiên bản của drivers

ls /lib/modules/
5.15.32+  5.15.32-v7+  5.15.32-v7l+  5.15.32-v8+

Sửa file /boot/config.txt, ghi ở đầu file để yêu cầu nạp initramfs khi khởi động

[pi4]
initramfs initrd.img-5.15.32-v8+ followkernel

Script thực hiện các bước trên:

sudo apt update && sudo apt -y upgrade
sudo apt -y install lvm2
m=($(tr ' ' '\n' <<<"$(ls /lib/modules/)" | sort -n -r))
v=${m[0]}
sudo sed -i '/\[pi4\]/,$ d
1 i\
[pi4]\
initramfs initrd.img-'"$v"' followkernel\
' /boot/config.txt

Cuối cùng tạo initrd.img và ghi vào /boot. Tên file có thêm version để sau này dễ nhận biết và cập nhật.

sudo sed -i 's/^MODULES=most/MODULES=list/' /etc/initramfs-tools/initramfs.conf
sudo mkinitramfs -o /boot/initrd.img-5.15.32-v8+ 5.15.32-v8+
sudo apt clean

Có thể có vài thông báo lỗi do hệ thống fat trên partition boot không hỗ trợ, bỏ qua.

Trước khi khởi động lại có thể đặt IP tĩnh.

Cài đặt ip tĩnh, nếu cần

# Đặt static_ip và static_router. Thí dụ:
# static_ip=192.168.100.100
# static_router=192.168.100.1

sudo sed -i '/slaac private/,${/slaac private/!d}
/slaac private/a\
\
# static IP\
interface wlan0\
static ip_address='"$static_ip"'/24\
# static ip6_address=fd51:42f8:caae:d92e::ff/64\
static routers='"$static_router"'\
static domain_name_servers='"$static_router"' 8.8.8.8
' /etc/dhcpcd.conf

Test: Khởi động lại đĩa như bình thường nhưng bây giờ RPi dùng initram.

sudo journalctl -b | grep initr
Jun 10 22:21:29 mail.example.net kernel: Trying to unpack rootfs image as initramfs...
Jun 10 22:21:29 mail.example.net kernel: Freeing initrd memory: 13656K

Backup đĩa mail.example.net

Bây giờ chúng ta cần một đĩa thứ 2 cũng chạy Raspbian, và cũng cài lvm2 trên đây để tạo logical volume trên đĩa mail.example.net

Khởi động RPi bằng đĩa thứ 2, sau đó gắn đĩa mail.example.net vào hệ thống.

# sudo lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    1 59.5G  0 disk
├─sda1        8:1    1  256M  0 part
└─sda2        8:2    1 59.3G  0 part
mmcblk0     179:0    0 29.4G  0 disk
├─mmcblk0p1 179:1    0  256M  0 part /boot
└─mmcblk0p2 179:3    0 29.2G  0 part /

Đĩa mail.example.net gắn vào cổng USB phía trước, có tên trong hệ thống là sda

# Kiểm tra đĩa
sudo fsck.vfat /dev/sda1
sudo fsck.ext4 -f /dev/sda2

# Mount các partition của sda
sudo mkdir /mnt/rootfs
sudo mount /dev/sda2 /mnt/rootfs
# sudo mkdir /mnt/sda2/boot
sudo mount /dev/sda1 /mnt/rootfs/boot

# Backup đĩa sda để chuẩn bị xóa partition rootfs.
# Tên file backup là raspbian-bullseye.tar.gz

sudo tar -cvzf raspbian-bullseye.tar.gz -C /mnt/rootfs --exclude=tmp --exclude=var/log ./
sudo umount /mnt/rootfs/boot /mnt/rootfs

# Kiểm tra file backup, nếu cần
sudo tar -tvf raspbian-bullseye.tar.gz

Phân chia lại đĩa sda

Dùng parted xóa cấu trúc đĩa và tạo lại partition boot và partition lvm

# Hệ thống file kiểu DOS (MBR)
sudo parted /dev/sda mktable msdos

# Partition #1 FAT32 256M
sudo parted /dev/sda mkpart primary fat32 2048s 256MiB

# Partition #2 EXT4 phần còn lại của đĩa
sudo parted /dev/sda mkpart primary ext4 256MiB 100%

# Partition #2 kiểu LVM
sudo parted /dev/sda set 2 lvm on

Tạo logical volume

Chúng ta chỉ tạo một LV kích thước vừa đủ để chứa OS, phần còn lại trên partition 2 sẽ dùng sau.

# Tạo physical volume trước
sudo pvcreate /dev/sda2

# Tạo volume group trên physical volume
sudo vgcreate rpi.vg /dev/sda2

# Tạo logical volume
sudo lvcreate rpi.vg --name rootfs.lv --size 6G

Hệ thống đĩa của sda hiện nay như sau

# sudo vgs
  VG     #PV #LV #SN Attr   VSize   VFree
  rpi.vg   1   1   0 wz--n- <59.27g <53.27g

# sudo lvs
  LV        VG     Attr       LSize
  rootfs.lv rpi.vg -wi-a----- 6.00g

# sudo lsblk
NAME                 MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                    8:0    1 59.5G  0 disk
├─sda1                 8:1    1  255M  0 part
└─sda2                 8:2    1 59.3G  0 part
  └─rpi.vg-rootfs.lv 254:0    0    6G  0 lvm

Format và mount các volume

sudo mkfs.vfat -F 32 -n BOOT /dev/sda1
sudo mkfs.ext4 -L rootfs /dev/mapper/rpi.vg-rootfs.lv
sudo mkdir /mnt/rootfs
sudo mount /dev/mapper/rpi.vg-rootfs.lv /mnt/rootfs
sudo mkdir /mnt/rootfs/boot ## thư mục con trong rootfs.lv
sudo mount /dev/sda1 /mnt/rootfs/boot

Restore Raspbian từ file backup

# phục hồi dữ liệu từ file backup
sudo tar -xvf raspbian-bullseye.tar.gz -C /mnt/rootfs

Sửa đổi các điểm mount

Sửa đổi các điểm mount trong /mnt/rootfs/boot/cmdline.txt/mnt/rootfs/etc/fstab để có thể khởi động vào logical volume

  • PARTUUID=xxxxxxxx-02 => /dev/mapper/rpi.vg-rootfs.lv
  • PARTUUID=xxxxxxxx-01 => partuuid mới của /dev/sda1
# rootfs giờ là /dev/mapper/rpi.vg-rootfs.lv
sudo sed -i 's/root=PARTUUID=[a-z0-9]*-02/root=\/dev\/mapper\/rpi.vg-rootfs.lv/' /mnt/rootfs/boot/cmdline.txt

# Lấy PARTUUID của /dev/sda1, thay đổi sau parted
pu=$(sudo blkid /dev/sda1 | grep -Po '(?<=PARTUUID=")(.*)(?=")')

# Thay đổi fstab
sudo sed -i "s/^PARTUUID=[a-z0-9]*-01/$pu/
s/^PARTUUID=[a-z0-9]*-02/\/dev\/mapper\/rpi.vg-rootfs.lv/" /mnt/rootfs/etc/fstab

Kiểm tra:

# cat /mnt/rootfs/boot/cmdline.txt
console=serial0,115200 console=tty1 root=/dev/mapper/rpi.vg-rootfs.lv rootfstype=ext4 ...

# cat /mnt/rootfs/etc/fstab
...
xxxxxxxx-01                     /boot           vfat    defaults,flush    0       2
/dev/mapper/rpi.vg-rootfs.lv    /               ext4    defaults,noatime  0       1
...

Xong rồi, dọn dẹp

sudo umount /mnt/rootfs/boot /mnt/rootfs
sudo fsck.vfat /dev/sda1
sudo fsck.ext4 -f /dev/mapper/rpi.vg-rootfs.lv
rm -rf /mnt/rootfs

Khởi động lại

Cuối cùng khởi động lại bằng đĩa mail.example.net. rootfs bây giờ là logical volume.

# lsblk
NAME                 MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
mmcblk0              179:0    0  29.4G  0 disk
├─mmcblk0p1          179:1    0   256M  0 part /boot
└─mmcblk0p2          179:3    0  29.2G  0 part
  └─rpi.vg-rootfs.lv 254:0    0    10G  0 lvm  /

Tạo thêm các LV trên phần đĩa trống của partition #2 nếu cần

lvcreate -L <size> -n <lv_name> rpi.vg
lvcreate -l <size%FREE> -n <lv_name> rpi.vg

Chú thích

  • Điểm quan trọng là dòng lệnh nạp initram phải ở đầu file /boot/config.txt, nếu không các driver của lvm không được nạp lên sớm => không mount được vg, lv. Khi đó có thông báo lỗi rpi.vg not found => không boot được, ngay cả khi thêm option rootdelay ở cmdline.txt
  • Dùng /dev/rpi.vg/rootfs.lv cũng hợp lệ như /dev/mapper/rpi.vg-rootfs.lv, nhưng không hoạt động trong config.txt
  • Khi mount các LV trong fstab, các điểm mount phải tồn tại, nếu không sẽ không khởi động được
  • Toàn bộ quá trình trên có thể ghép lại thành một script

Comments Off on Cài đặt OS trên Logical volume

Filed under Software

Comments are closed.