Статья

Установка системы на Raspberry pi4 с RAID1 и LVM

Raspberry pi - одна из самых популярных платформ для умного дома, не занимает много места, экономична, имеет неплохие ресурсы на борту (особенно последняя версия) и большое интернет сообщество. Одно плохо - грузится малинка с SD карты, которая не слишком надежна. Слава разработчикам, в последнее время появилась возможность грузится с usb, а это значит, что систему можно установить на ssd диск. И надежность выше и скорость работы. И все же, собирая систему умного дома, хочется, чтобы система была максимально надежна. Со временем любой диск может выйти из строя, и чтобы хоть как-то обезопасить себя, люди придумали много чего, в том числе, зеркалить диски. Но конечно же, raid не панацея, и самое главное - делать бекапы. Но все же, система на зеркале будет более надежной.

Пока аппаратного raid на raspberry нет, можем воспользоваться программным. Подробнее можно прочитать здесь. Конечно, raspberry не умеет грузиться с рейда и у нее нет grub, но если сделать первый раздел на дисках загрузочным, то система загрузится с первого попавшегося ей, а рейд лишь синхронизирует данные на обоих дисках.

Теперь про бекапы. На многих платформах умных домов есть встроенные средства сохранения системы, например, в Home assistant есть замечательный плагин для создания snapshot-ов и сохранения их на google диске. Но что, если на малине установлено много всего, в том числе за пределами home assistant? Хорошо бы сохранять систему целиком. В этом нам может помочь менеджер логических томов lvm, который умеет создавать снимки системы (snapshot). Подробнее можно прочитать здесь.

Отлично, но как засунуть все это в малинку, да еще заставить ее загружаться? Для этого вспомним, что linux может вначале загружать систему с ram диска, выполнять там необходимые действия, а потом уже вызывать "большой" загрузчик. Этим и воспользуемся.

С али пришел комплект из Raspberry pi4 на 4 Гб, корпуса-радиатора, кабеля hdmi и блока питания, который отлично тянет два ssd диска и zigbee стик. Все это у китайцев стоит дешевле, чем голая малина здесь. Там же, на али, были заказаны переходники usb3-sata. Диски SSD покупались не дорогие, на 120 Гб, но известной кампании. Zigbee стик на базе cc2538 приобретен через сообщество в телеграмм. Чтобы все это не болталось на столе, на первое время выпилил из алюминиевого уголка кронштейны, потом нужно будет придумать какой-нибудь корпус.

Raspberry pi4 и ssd диски usb3

Оказывается, pi4 не работает корректно с некоторыми дисками SSD, а точнее, с их контроллерами. Я понял это, когда заметил, что скорость обмена данными с диском на уровне нескольких килобайт в секунду. Решение нашлось здесь. В терминале нужно выполнить команду dmesg и найти строки, относящиеся к подключению диска. Там можно увидеть параметры idVendor и idProduct, значения нужно запомнить.

pi@raspberrypi:~ $ dmesg... [ 2.951799] usb 2-1: new SuperSpeed Gen 1 USB device number 2 using xhci_hcd [ 2.983335] usb 2-1: New USB device found, idVendor=152d, idProduct=0578, bcdDevice=32.02 [ 2.985040] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 2.986676] usb 2-1: Product: External Disk 3.0 [ 2.988513] usb 2-1: Manufacturer: JMicron [ 2.990123] usb 2-1: SerialNumber: 5002627282575325

Затем в файле /boot/cmdline.txt в самое начало добавить параметр usb-storage.quirks=xxxx:yyyy:u, где xxxx и yyyy это значения idVendor и idProduct соответственно.

pi@raspberrypi:~ $ sudo nano /boot/cmdline.txt usb-storage.quirks=152d:0578:u console=serial0,115200 console=tty1 и т.д.

После перезагрузки скорость обмена с дисками значительно увеличилась.

Подготовка системы

Для того, чтобы Raspberry могла загружаться с USB, нужно обновить загрузчик. Этот процесс хорошо показан в статье, поэтому только кратко опишу действия.

  • Обновляемся:

sudo apt-get update sudo apt-get upgrade

  • Изменяем канал загрузки с critical на beta:

sudo sed -i 's/critical/beta/' /etc/default/rpi-eeprom-update

  • Устанавливаем программу обновления загрузчика:

sudo apt-get install rpi-eeprom

  • Проверяем, какие версии нам доступны:

ls -la /lib/firmware/raspberrypi/bootloader/beta/

  • На момент написания статьи у меня была последняя версия от 15 июня, ее и ставим:

sudo rpi-eeprom-update -d -f /lib/firmware/raspberrypi/bootloader/beta/pieeprom-2020-06-15.bin

  • Перезагружаемся.
  • Проверяем порядок загрузки малины, если BOOT_ORDER=0xf41, значит мы можем грузиться с usb:

pi@raspberrypi:~ $ vcgencmd bootloader_config [all] BOOT_UART=0 WAKE_ON_GPIO=1 POWER_OFF_ON_HALT=0 DHCP_TIMEOUT=45000 DHCP_REQ_TIMEOUT=4000 TFTP_FILE_TIMEOUT=30000 ENABLE_SELF_UPDATE=1 DISABLE_HDMI=0 BOOT_ORDER=0xf41

  • Меняем канал загрузки обратно:

sudo sed -i 's/beta/critical/' /etc/default/rpi-eeprom-update

Подготовка дисков

Диски для работы в raid должны быть размечены одинаково. Мы создадим два раздела: один - под boot, другой - под root. Мне удобнее использовать утилиту cfdisk. Она проста и понятна и не требует дополнительной установки.

sudo cfdisk /dev/sda

Если диск уже размечен, предварительно нужно все удалить. Затем создаем первый раздел:

[New] -> 512M -> Primary -> [Bootable] -> [Type] -> c W95 FAT32 (LBA)

[New] -> 100G -> Primary -> [Write] -> yes

Disk: /dev/sda Size: 111.8 GiB, 120034123776 bytes, 234441648 sectors Label: dos, identifier: 0xbc19c96f Device Boot Start End Sectors Size Id Type /dev/sda1 * 2048 1050623 1048576 512M c W95 FAT32 (LBA) /dev/sda2 1050624 210765823 209715200 100G 83 Linux

Выходим из программы через [Quit] и аналогично размечаем второй диск:

sudo cfdisk /dev/sdb

RAID

Устанавливаем программу для управления soft raid:

sudo apt-get install mdadm

Создаем два массива под каждый раздел (boot, root). Массивы у нас будут зеркалами, т.е. raid1, в системе они должны быть устройствами c именами /dev/md*. Для того, чтобы с массива произошла загрузка, он должен быть с атрибутом metadata=0.90

sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1 --metadata=0.90 sudo mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sda2 /dev/sdb2

Увидеть текущий статус массивов можно командой:

cat /proc/mdstat

Сразу после создания, массив /dev/md0 будет готов к использованию, а /dev/md1 будет синхронизировать диски. По завершению мы должны увидеть, что оба массива активны:

pi@raspberrypi:~ $ cat /proc/mdstat Personalities : [raid1] md1 : active (auto-read-only) raid1 sda2[0] sdb2[1] 104791040 blocks super 1.2 [2/2] [UU] md0 : active (auto-read-only) raid1 sda1[0] sdb1[1] 524224 blocks [2/2] [UU]

Смотрим, что у нас произошло в системе с помощью команды lsblk:

pi@raspberrypi:~ $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 111.8G 0 disk ├─sda1 8:1 0 512M 0 part │ └─md0 9:0 0 512M 0 raid1 └─sda2 8:2 0 100G 0 part └─md1 9:1 0 100G 0 raid1 sdb 8:16 0 111.8G 0 disk ├─sdb1 8:17 0 512M 0 part │ └─md0 9:0 0 512M 0 raid1 └─sdb2 8:18 0 100G 0 part └─md1 9:1 0 100G 0 raid1 mmcblk0 179:0 0 14.9G 0 disk ├─mmcblk0p1 179:1 0 256M 0 part /boot └─mmcblk0p2 179:2 0 14.6G 0 part /

Массивы созданы. Теперь, чтобы они собирались после перезагрузки, выполним команду sudo mdadm --examine --scan:

pi@raspberrypi:~ $ sudo mdadm --examine --scan ARRAY /dev/md0 UUID=b410b8c5:2fd8edd0:fe2970c7:3724fbef ARRAY /dev/md/1 metadata=1.2 UUID=4281b979:31d37be3:c5cb9ab1:a41d7544 name=raspberrypi:1

И добавим ее вывод в конец файла /etc/mdadm/mdadm.conf:

sudo nano /etc/mdadm/mdadm.conf # mdadm.conf # # !NB! Run update-initramfs -u after updating this file. # !NB! This will ensure that initramfs has an uptodate copy. # # Please refer to mdadm.conf(5) for information about this file. # # by default (built-in), scan all partitions (/proc/partitions) and all # containers for MD superblocks. alternatively, specify devices to scan, using # wildcards if desired. #DEVICE partitions containers # automatically tag new arrays as belonging to the local system HOMEHOST <system> # instruct the monitoring daemon where to send mail alerts MAILADDR root # definitions of existing MD arrays # This configuration was auto-generated on Sat, 15 Aug 2020 14:48:16 0100 by mkconf ARRAY /dev/md0 UUID=b410b8c5:2fd8edd0:fe2970c7:3724fbef ARRAY /dev/md/1 metadata=1.2 UUID=4281b979:31d37be3:c5cb9ab1:a41d7544 name=raspberrypi:1

Перезагружаемся.

LVM

Установка:

sudo apt-get install lvm2

Инициализируем раздел диска:

sudo pvcreate /dev/md1

Создадим группу томов с именем vgsys на разделе /dev/md1:

sudo vgcreate vgsys /dev/md1

Активируем группу томов:

sudo vgchange -a y vgsys

Создадим логический том с именем lvroot на группе lgsys, размером 50 гигабайт. Впоследствии размер легко изменить.

sudo lvcreate -L50G -n lvroot vgsys

Собираем все вместе

Создаем файловые системы:

sudo mkfs.vfat /dev/md0 sudo mkfs.ext4 /dev/vgsys/lvroot

Тестируем. Создадим необходимые папки в /mnt и смонтируем на них созданные разделы:

sudo mkdir /mnt/disk sudo mount /dev/vgsys/lvroot /mnt/disk sudo mkdir /mnt/disk/boot sudo mkdir /mnt/disk/mnt/ sudo mount /dev/md0 /mnt/disk/boot

Проверяем:

pi@raspberrypi:~ $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 15052924 1498160 12911220 11% / devtmpfs 1827808 0 1827808 0% /dev tmpfs 1959904 0 1959904 0% /dev/shm tmpfs 1959904 8692 1951212 1% /run tmpfs 5120 4 5116 1% /run/lock tmpfs 1959904 0 1959904 0% /sys/fs/cgroup /dev/mmcblk0p1 258095 67025 191070 26% /boot tmpfs 391980 0 391980 0% /run/user/1000 /dev/mapper/vgsys-lvroot 51343840 1547944 47158072 4% /mnt/disk /dev/md0 523944 68448 455496 14% /mnt/disk/boot

Разделы смонтировались, значит все в порядке. Запомним, как выглядит раздел lvm (/dev/mapper/vgsys-lvroot), дальше это нам понадобится.Теперь самое главное - соберем образ initramfs.

pi@raspberrypi:~ $ sudo update-initramfs -c -k `uname -r` update-initramfs: Generating /boot/initrd.img-5.4.51-v7l

Заметим, какое имя получил файл образа, оно нам пригодится.

Копируем разделы:

sudo cp -afxv / /mnt/disk sudo cp -afxv /boot /mnt/disk

Последнее, что осталось - это внести изменения в конфигурационные файлы.

/mnt/disk/boot/config.txt

[pi4] initramfs initrd.img-5.4.51-v7l followkernel

  • /mnt/disk/boot/cmdline.txt

root=/dev/mapper/vgsys-lvroot

  • /mnt/disk/etc/fstab

Опять же, заменим точки монтирования своими. Плюс у меня прописано монтирование сетевой папки для бекапов.

/dev/md0 /boot vfat defaults 0 2 /dev/mapper/vgsys-lvroot / ext4 defaults,noatime 0 1 nas4free:/mnt/pool/backup /mnt/backup nfs auto 0 0

Все, останавливаем систему.

sudo shutdown now

Выключаем питание и вынимаем SD карту. Теперь, при подаче питания вновь, система должна загрузиться с raid массива. SD карту откладываем, она еще потребуется.

После загрузки проверяем:

pi@raspberrypi:~ $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 111.8G 0 disk ├─sda1 8:1 0 512M 0 part │ └─md0 9:0 0 512M 0 raid1 /boot └─sda2 8:2 0 100G 0 part └─md1 9:1 0 100G 0 raid1 └─vgsys-lvroot 253:0 0 50G 0 lvm / sdb 8:16 0 111.8G 0 disk ├─sdb1 8:17 0 512M 0 part │ └─md0 9:0 0 512M 0 raid1 /boot └─sdb2 8:18 0 100G 0 part └─md1 9:1 0 100G 0 raid1 └─vgsys-lvroot 253:0 0 50G 0 lvm /

Все получилось, у нас два зеркальных массива, поверх стоит том lvm и система грузится без sd карты.

Важный момент

При следующих обновлениях системы может случиться так, что сборка Linux изменится, initramsf обновит образ, а параметры в config.txt останутся прежними. В результате система не поднимется после перезагрузки. В принципе не страшно, можно опять загрузится с sd карты (ведь мы ее отложили на всякий случай) смонтировать папки и исправить файл. Но можно заставить систему обновлять параметры автоматически. Для этого создадим файл скрипта:

sudo touch /etc/initramfs-tools/hooks/update_initrd_image

И поместим в него следующий код:

#! /bin/sh -e # Update reference to $INITRD in $BOOTCFG, making the kernel use the new # initrd after the next reboot. BOOTLDR_DIR=/boot BOOTCFG=$BOOTLDR_DIR/config.txt INITRD_PFX=initrd.img- INITRD=$INITRD_PFX$version case $1 in prereqs) echo; exit esac FROM="^ *\\(initramfs\\) \\ $INITRD_PFX.\\ \\ \\(followkernel\\) *\$" INTO="\\1 $INITRD \\2" T=`umask 077 && mktemp --tmpdir genramfs_XXXXXXXXXX.tmp` trap "rm -- \"$T\"" 0 sed "s/$FROM/$INTO/" "$BOOTCFG" > "$T" # Update file only if necessary. if ! cmp -s "$BOOTCFG" "$T" then cat "$T" > "$BOOTCFG" fi

Сохраним и сделаем файл исполняемым:

sudo chmod x /etc/initramfs-tools/hooks/update_initrd_image

Теперь скрипт запустится всякий раз при обновлении и изменит параметры в файле config.txt при необходимости.

Изменение размера тома

Изначально мы создали раздел для root, размером в 50 гигабайт. Теперь при помощи lvm можем легко поменять это. Просто выполним команду и укажем, какой размер нам нужен.

sudo lvextend -L64G /dev/mapper/vgsys-lvroot

Проверяем:

pi@raspberrypi:~ $ sudo lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert lvroot vgsys -wi-ao---- 64.00g

Теперь нужно расширить файловую систему:

sudo resize2fs /dev/mapper/vgsys-lvroot

Проверяем:

pi@raspberrypi:~ $ df -h Filesystem Size Used Avail Use% Mounted on udev 1.8G 0 1.8G 0% /dev tmpfs 383M 5.4M 378M 2% /run /dev/mapper/vgsys-lvroot 63G 1.5G 59G 3% / tmpfs 1.9G 0 1.9G 0% /dev/shm tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup /dev/md0 512M 67M 445M 14% /boot 192.168.1.50:/mnt/pool/backup 2.6T 485G 2.1T 19% /mnt/backup tmpfs 383M 0 383M 0% /run/user/1000

Snapshots. Сохранение и восстановление системы

Перед тем, как создать snapshot, посмотрим, какой объем будет нужен. Из листинга выше видим, что root занимает 1.5 Гб, значит, можем выделить пару гигов. Snapshot создается той же командой, что и логический том, только с ключем -s. После -n задаем имя снимка.

sudo lvcreate -s -L2G -n snap /dev/vgsys/lvroot

Проверяем:

pi@raspberrypi:~ $ sudo lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert lvroot vgsys owi-aos--- 64.00g snap vgsys swi-a-s--- 2.00g lvroot 0.01

Как можно заметить, создан snapshot оригирального тома lvroot на группе vgsys. Теперь можно смело проводить эксперименты по установке разного софта. По окончании можно либо откатить все изменения командой:

sudo lvremove vgsys/snap

Тогда система вернется в состояние на момент создания snapshot, либо принять изменения командой:

sudo lvconvert --merge vgsys/snap

В этом случае все изменения будут приняты, а snapshot автоматически удалится.

Внимание! Не следует все время держать в системе созданный snapshot, это будет замедлять работу.

Кроме того, созданный snapshot можно примонтировать как обычный том и убедится, что в нем снимок системы. Я буду монтировать в режиме только для чтения, для избежания проблем.

sudo mount /dev/vgsys/snap /mnt/snap -r

И конечно, можно сделать бекап системы. Я сохраняю на сервер вот такой командой:

cd /mnt/snap && sudo tar --ignore-failed-read -czpf /mnt/backup/pi/snapshots/`date %Y%m%d%H%M%S`.tar.gz *

После копирования, snapshot следует отмонтировать и удалить. Если во время копирования tar будет ругаться на сокеты (socket ignored), можно не обращать внимания. Файлы сокетов не копируются, они все равно создаются заново при необходимости.

Для восстановления системы из бекапа нужно загрузится с оставленной SD карты, примонтировать сетевое хранилище, vlm раздел на рейде и скопировать сохраненные ранее данные. Чтобы не монтировать разделы каждый раз, нужно указать их в /etc/fstab файле на карточке. Добавим следующие строки в файл:

/dev/mapper/vgsys-lvroot /mnt/disk ext4 defaults,noatime 0 0 nas4free:/mnt/pool/backup /mnt/backup nfs auto 0 0

Проверяем правильность командой:

sudo mount -a

Если разделы смонтировались, значит все правильно и в следующий раз при загрузки с карточки все смонтируется автоматически. Теперь нужно очистить раздел:

cd /mnt/disk && sudo rm -frdv *

И восстановить данные из нужного архива:

cd /mnt/backup/pi/snapshots sudo tar --preserve-permissions --same-owner --directory=/mnt/disk -xvf 20200828141828.tar.gz

После этого останавливаем малинку, выключаем питание и вынимаем SD карту. После подачи питания, система загрузится в том состоянии, когда был сделан бекап.

1

Лайк ща труды!!!

Как будто облизнул анус


Вернуться назад

Устройства


Texas Instruments

USB Stick CC2538

(1 отзыв)

Raspberry Pi

Raspberry Pi 4

(15 отзывов)

Вернуться назад