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

13 сентября 2020, 16:36

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/{backup,snap}
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. Имя образа мы запомнили раньше.

  [pi4]
  initramfs initrd.img-5.4.51-v7l  followkernel
  • /mnt/disk/boot/cmdline.txt
Заменим точку монтирования root раздела на свою.
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 карту. После подачи питания, система загрузится в том состоянии, когда был сделан бекап.


Все новости мира умных домов - t.me/SprutAI_News или Instagram
Остались вопросы? Мы в Telegram - @SprutAI

Хочешь умный дом но нет времени разбираться?
Посмотри примеры работ и выбери себе интегратора.
  1. Андрей Паневин (gfyz)

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

    • (dahof53988)
      (dahof53988) отредактировано год назад
      Комментарий удален
К списку статей

Устройства в материале

USB Stick CC2538

Производитель: Texas Instruments

Raspberry Pi 4

Производитель: Raspberry Pi
Заказать на:

Тематические чаты

Похожие статьи

25 сентября 2020, 11:49
Сенсорный монитор для управления умным домом. Настройка и использование.
15 ноября 2018, 09:42
Способы автоматизации механических ворот
28 августа 2018, 09:48
От голого Raspbian до веб-интерфейса homebridge за четыре команды в терминале.
03 октября 2018, 22:03
Как собрать и настроить Hyperion Ambilight - адаптивную подсветку ТВ.
01 октября 2019, 07:07
"У всякого в умном дому неведомо никому" (с) Народная мудрость
24 августа 2018, 09:49
Как удаленно управлять Mac через Siri.
26 ноября 2018, 12:35
Выключение и включение компьютера через HomeBridge, а так-же через HomeAssistant
09 января 2019, 17:34
Небольшая статья о том, зачем нужна малина, почему автоматизации в HomeKit это не очень хорошо и чем USB стик лучше отдельного шлюза.
04 апреля 2019, 17:48
Расскажу о том за ~1 час перевезти УД с 2мя USB стиками с Raspberry PI на Synology NAS.
23 сентября 2019, 08:52
Node-RED - пошаговая инструкция для новичков.