Dokumentovaná sestava se skládá z těchto komponent:
Napájecí zdroj je kvůli UPS desce, protože UPS deska dokáže přes jack konektor 2,5×5,5 mm dodat až 20W. To je maximum, které půjde do UPS desky dodat a zároveň pokud nebudu připojovat další náročné periferie, tak tento výkon utáhne NVMe disky.
Standardně Raspberry Pi 5 bootuje z microSD karty, ale je možné nakonfigurovat systém tak, aby bootoval přímo z NVMe SSD připojeného přes PCIe. Návod vychází z článku https://wiki.geekworm.com/NVMe_SSD_boot_with_the_Raspberry_Pi_5. Tento postup zahrnuje několik kroků:
Pro instalaci operačního systému na NVMe SSD můžete použít nástroj Raspberry Pi Imager na Windows nebo macOS. K tomu budete potřebovat USB → NVMe adaptér.
Postup:
Ve výchozím nastavení je PCIe port deaktivovaný a je nutné jej povolit.
Otevřete konfigurační soubor:
sudo nano /boot/firmware/config.txt
Přidejte následující řádky na konec souboru:
# Povolení PCIe externího konektoru dtparam=pciex1 # Alternativní zápis pro povolení NVMe portu dtparam=nvme
Uložte změny a restartujte Raspberry Pi:
sudo reboot
Po povolení PCIe portu je třeba upravit pořadí bootování v bootloaderu.
Možnost 1: Použití raspi-config
Spusťte konfigurátor:
sudo raspi-config
Zvolte:
sudo reboot
Možnost 2: Ruční úprava bootovacího řetězce
Otevřete EEPROM konfiguraci:
sudo rpi-eeprom-config --edit
Najděte řádek `BOOT_ORDER` a upravte ho na:
BOOT_ORDER=0xf416
Uložte změny a restartujte Raspberry Pi.
UPS desku jsem kupoval ve verzi 2.5. Je důležité si uvědomit, že UPS X728 není určena k automatickému spuštění Raspberry Pi po obnovení napájení. Její hlavní funkcí je zajistit nepřerušený provoz během výpadku, dokud je baterie dostatečně nabitá.
Jakmile baterie klesne na kritickou úroveň, Raspberry Pi by mělo být řízeně vypnuto, aby se zabránilo náhlé ztrátě dat nebo poškození systému. UPS však Raspberry Pi znovu automaticky nenastartuje, i když je baterie plně nabitá.
Pokud po zapnutí tlačítka na UPS svítí červená LED dioda na Raspberry Pi, znamená to, že deska je pod napětím, ale Raspberry Pi se samo nespustilo. Skutečné spuštění a běh systému indikují jiné LED diody na Raspberry Pi.
Tento návod popisuje postup pro zprovoznění softwaru UPS X728 a jeho správné nastavení.
Nejprve zapněte podporu I2C pomocí `raspi-config`:
sudo raspi-config
Poté nainstalujte potřebné balíčky:
apt-get install i2c-tools apt install python3-smbus
Ověření připojení přes I2C:
root@propasiv-server:~# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- 36 -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
#36 - adresa chipu pro měření úrovně nabití baterie #68 - adresa RTC chipu
Nainstalujte potřebné nástroje:
sudo apt install -y gpiod
Stáhněte ovladače:
git clone https://github.com/geekworm-com/x728-script
Nastavte práva pro skripty:
cd x728-script chmod +x *.sh
Přesuňte potřebné soubory na správná místa:
sudo cp -f ./xPWR.sh /usr/local/bin/ sudo cp -f x728-pwr.service /lib/systemd/system sudo systemctl daemon-reload sudo systemctl enable x728-pwr sudo systemctl start x728-pwr
Tento postup umožní, aby fyzické tlačítko na UPS desce X728 fungovalo takto:
Tento postup nedělá nic jiného – pouze definuje chování tlačítka.
Pro správné softwarové vypnutí je nutné nastavit vlastní alias:
1. Připravte skript `xSoft.sh`:
sudo cp -f ./xSoft.sh /usr/local/bin/
2. Vytvořte alias `x728off`, který bude bezpečně vypínat UPS:
echo "alias x728off='sudo /usr/local/bin/xSoft.sh 0 '''26''' '" >> ~/.bashrc
3. Aktivujte změny v `.bashrc`:
source ~/.bashrc
4. Nyní můžete bezpečně vypnout UPS příkazem:
x728off
Pozor: Nepoužívejte klasický Linuxový příkaz `shutdown`, jinak se UPS nevypne správně a může zůstat zapnutá.
Softwarové bezpečné vypnutí:
x728off
Nepoužívejte příkaz `shutdown` v Linuxu, jinak se X728 nevypne správně.
Pomocí fyzického tlačítka na UPS lze ověřit bezpečné vypnutí:
Tímto postupem zajistíte, že UPS X728 bude správně fungovat a umožní bezpečné vypnutí jak softwarově, tak fyzickým tlačítkem.
Každý skript demonstruje jinou funkcionalitu UPS X728:
Starší ukázkové skripty používají knihovnu RPi.GPIO, která není podporována v jádru Linuxu 6.6.x. Pokud spustíte skript jako:
sudo python3 sample/x728-v2.x-plsd.py
může se objevit chyba kvůli nesprávnému gpiochip číslu.
Doporučuje se přejít na knihovnu libgpiod, která je oficiálně doporučena a lépe podporována. UPS X728 poskytuje jediný oficiální skript využívající libgpiod:
sudo python3 sample/x728-v2.x-plsd-gpiod.py
U ostatních skriptů, které stále používají RPi.GPIO, je doporučeno přepsání na libgpiod nebo jejich převedení na shell skripty.
Skript jsem si tedy přizpůsobil pro libgpiod:
#!/usr/bin/env python import struct import smbus import time import gpiod import logging # Log interval LOG_INTERVAL = 300 # seconds last_power_state = None # Stores last power state last_log_time = 0 # Stores last log timestamp # Logging configuration logging.basicConfig(filename='/var/log/x728-battery.log', level=logging.INFO, format='%(asctime)s - %(message)s') # GPIO chip and line definitions #chipname = "gpiochip0" # Use "gpiochip4" for Raspberry Pi 4/3 chipname = "gpiochip4" # Use "gpiochip4" for Raspberry Pi 5 out_line_offset = 26 # Corresponds to GPIO26 pld_line_offset = 6 # Power loss detection pin buzzer_line_offset = 20 # Buzzer control pin # I2C address for battery monitoring I2C_ADDR = 0x36 # Initialize I2C bus bus = smbus.SMBus(1) # Open GPIO chip chip = gpiod.Chip(chipname) # Get the output lines out_line = chip.get_line(out_line_offset) out_line.request(consumer="battery_monitor", type=gpiod.LINE_REQ_DIR_OUT) buzzer_line = chip.get_line(buzzer_line_offset) buzzer_line.request(consumer="power_monitor", type=gpiod.LINE_REQ_DIR_OUT) # Get the input line for power loss detection pld_line = chip.get_line(pld_line_offset) pld_line.request(consumer="power_monitor", type=gpiod.LINE_REQ_EV_BOTH_EDGES) def readVoltage(bus): """Reads battery voltage from I2C bus.""" address = I2C_ADDR read = bus.read_word_data(address, 2) swapped = struct.unpack("<H", struct.pack(">H", read))[0] voltage = swapped * 1.25 / 1000 / 16 return voltage def readCapacity(bus): """Reads battery capacity from I2C bus.""" address = I2C_ADDR read = bus.read_word_data(address, 4) swapped = struct.unpack("<H", struct.pack(">H", read))[0] capacity = swapped / 256 if capacity > 100: capacity = 100 return capacity def print_power_status(): """Monitors power status and logs changes.""" global last_power_state, last_log_time state = pld_line.get_value() current_time = time.time() if state == 1: print("Power Supply A/C Lost") # First detection of power loss if last_power_state != 1: logging.warning("Power Supply A/C Lost") elif current_time - last_log_time > LOG_INTERVAL: # Subsequent logging at intervals logging.warning("Power Supply A/C Lost") last_log_time = current_time # Activate buzzer to indicate power loss for _ in range(3): # Buzzer alarm cycle buzzer_line.set_value(1) time.sleep(0.1) buzzer_line.set_value(0) time.sleep(0.1) else: print("AC Power OK") if last_power_state != 0: # First detection of power restoration logging.info("AC Power OK") elif current_time - last_log_time > LOG_INTERVAL: # Subsequent logging at intervals logging.info("AC Power OK") last_log_time = current_time buzzer_line.set_value(0) last_power_state = state return state try: while True: print("******************") voltage = readVoltage(bus) capacity = readCapacity(bus) print(f"Voltage: {voltage:.2f}V") print(f"Battery: {capacity:.0f}%") # Log battery voltage and capacity at intervals if time.time() - last_log_time > LOG_INTERVAL: logging.info(f"Voltage: {voltage:.2f}V, Battery: {capacity:.0f}%") last_log_time = time.time() # Monitor power loss detection power_status = print_power_status() if capacity == 100: print("Battery FULL") if capacity < 20: print("Battery Low") # This condition ensures shutdown only if the battery is below 99% and the power is disconnected. # This means that if the power is connected, the server will not shut down. # Everyone should evaluate whether this is safe and adjust the condition if necessary. if voltage < 3.00 and power_status == 1: print("Battery LOW!!!") logging.critical("Battery LOW! Shutdown in 10 seconds") print("Shutdown in 10 seconds") time.sleep(10) out_line.set_value(1) time.sleep(3) out_line.set_value(0) time.sleep(2) except KeyboardInterrupt: print("Exiting...") finally: chip.close()
Pro zajištění automatického spuštění skriptu po restartu použijeme systemd service, což je spolehlivý způsob, jak zajistit, že skript poběží na pozadí.
Otevřete terminál a vytvořte soubor pro službu:
sudo nano /etc/systemd/system/x728-battery.service
Do souboru vložte následující obsah a uložte:
[Unit] Description=X728 Battery Monitor After=multi-user.target [Service] Type=simple ExecStart=/usr/bin/python3 /etc/local-scripts/x728-script/sample/x728-v2.x-asd-gpiod.py Restart=always User=root StandardOutput=append:/var/log/x728-battery.log StandardError=append:/var/log/x728-battery.log [Install] WantedBy=multi-user.target
Načtěte systemd a povolte službu při startu:
sudo systemctl daemon-reload sudo systemctl enable x728-battery.service
Pro okamžité spuštění služby spusťte:
sudo systemctl start x728-battery.service
Pro ověření, zda služba běží správně, použijte:
sudo systemctl status x728-battery.service
Na Raspberry Pi mi aplikace vytvořila nový logový soubor `/var/log/x728-battery.log`. Abych zajistil jeho pravidelnou rotaci a zabránil nadměrnému růstu, rozhodl jsem se použít logrotate. Tento nástroj už byl v systému nainstalován.
Nejprve jsem vytvořil nový konfigurační soubor v `/etc/logrotate.d/`:
sudo nano /etc/logrotate.d/x728-battery
Do souboru jsem přidal následující konfiguraci:
/var/log/x728-battery.log { weekly rotate 4 compress missingok notifempty create 644 root root postrotate systemctl restart x728-battery.service endscript }
Bylo nutné přidat `postrotate` sekci, která restartuje službu `x728-battery.service`, protože jinak aplikace nepokračovala v logování do nového souboru.
Pro kontrolu, zda logrotate soubor správně rozpoznává, jsem spustil:
sudo logrotate -d /etc/logrotate.d/x728-battery
(Debug mód `-d` pouze zobrazí, co by se stalo, ale skutečně rotaci neprovede.)
Pokud konfigurace neobsahovala chyby, provedl jsem ruční rotaci:
sudo logrotate -f /etc/logrotate.d/x728-battery
Po této úpravě se logy správně rotují a starší soubory jsou automaticky komprimovány a spravovány.
Tento návod popisuje kompletní nastavení a použití RTC (Real Time Clock) na UPS X728. UPS využívá RTC modul pro udržení přesného času i po odpojení napájení. Tento postup byl testován na Raspberry Pi OS.
1. Otevřete konfigurační soubor `/boot/config.txt` a přidejte na konec nebo pod sekci `[all]` tento řádek:
sudo nano /boot/config.txt
Přidejte:
dtoverlay=i2c-rtc,ds1307
Uložte změny stisknutím Ctrl+O, potvrďte Enter, a ukončete editor Ctrl+X.
2. Restartujte Raspberry Pi:
sudo reboot
Raspberry Pi OS obsahuje fake-hwclock, který simuluje RTC a může způsobovat problémy s reálným RTC modulem. Proto je nutné ho odstranit:
sudo apt-get -y remove fake-hwclock sudo update-rc.d -f fake-hwclock remove sudo systemctl disable fake-hwclock
Pro správné fungování RTC je třeba upravit soubor `/lib/udev/hwclock-set` a zakomentovat řádky 7-12:
sudo nano /lib/udev/hwclock-set
Najděte následující část kódu:
#!/bin/sh # Reset the System Clock to UTC if the hardware clock from which it # was copied by the kernel was in localtime. dev=$1 #if [ -e /run/systemd/system ] ; then # exit 0 #fi # #/sbin/hwclock --rtc=$dev --systz #/sbin/hwclock --rtc=$dev --hctosys
Každý řádek označený `#` je zakomentován a nebude se vykonávat.
Uložte změny a ukončete editor.
Po dokončení výše uvedených kroků restartujte Raspberry Pi:
sudo reboot
Po restartu můžete ověřit aktuální systémový čas:
date
Pokud je čas nesprávný, nastavte ho ručně:
date -s "5 MAR 2019 13:00:00"
Uložte nastavený čas do RTC:
sudo hwclock -w
Pro ověření času uloženého v RTC modulu použijte:
sudo hwclock -r
Poznámka: Ujistěte se, že jsou v UPS X728 vloženy baterie, aby se uložený čas zachoval i po vypnutí zařízení.
Po dokončení tohoto postupu bude při každém startu Raspberry Pi čas automaticky synchronizován z RTC modulu.
Tato sekce popisuje možné problémy při používání UPS X728 a jejich řešení. Informace čerpám z oficiální dokumentace výrobce: [Zdroj: Geekworm Wiki - X728 FAQ](https://wiki.geekworm.com/X728#FAQ)
Problém: Zobrazuje se hláška „This power supply is not capable of supplying 5A“ na Raspberry Pi 5
UPS X728/X729 má dostatečnou kapacitu pro napájení 5A, nicméně je potřeba provést následující nastavení:
Krok 1: Úprava konfigurace napájení (povinné)
Otevřete terminál v Raspberry Pi OS a spusťte příkaz:
sudo rpi-eeprom-config -e
Na konec souboru přidejte následující řádek:
PSU_MAX_CURRENT=5000
Uložte změny stisknutím Ctrl+O, potvrďte klávesou Enter, a ukončete editor stisknutím Ctrl+X.
Krok 2: Zvýšení proudového limitu USB (volitelné, pokud používáte USB zařízení s vyšší spotřebou)
Otevřete konfigurační soubor:
sudo nano /boot/firmware/config.txt
Přidejte tento řádek:
usb_max_current_enable=1
Uložte změny a zavřete editor stejným způsobem jako v předchozím kroku.
Restartujte Raspberry Pi, aby se změny projevily:
sudo reboot
Poznámka: Pokud používáte jiný operační systém (například Ubuntu), je nutné nejprve nahrát Raspberry Pi OS, provést výše uvedené úpravy a teprve poté znovu nahrát požadovaný operační systém.
Od verze X728 v2.5 je možné softwarově řídit nabíjení baterie pomocí GPIO16. Tato funkce je určena pouze pro pokročilé uživatele, kteří mají zkušenosti s Linuxem. Pokud si nejste jisti, doporučuje se ponechat jumper „CHG Ctrl“ zkratovaný, což umožní automatické nabíjení při připojení napájecího adaptéru.
Možnosti nastavení „CHG Ctrl“ jumperu: - Jumper zkratovaný → Baterie se automaticky nabíjí, pokud je připojen napájecí adaptér. - Jumper otevřený → Nabíjení lze ovládat přes GPIO16:
Pro ruční ovládání nabíjení je nutné nejprve zjistit odpovídající GPIO pin:
GPIO=16 # Zjištění skutečného čísla GPIO pinu GPIO=$(cat /sys/kernel/debug/gpio | grep "GPIO$GPIO" | awk -F'gpio-' '{print $2}' | awk -F' ' '{print $1}') echo "$GPIO" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio$GPIO/direction
Povolení nabíjení:
echo "1" > /sys/class/gpio/gpio$GPIO/value
Zakázání nabíjení:
echo "0" > /sys/class/gpio/gpio$GPIO/value
Poznámka: Nakonec jsem tuto funkci nevyužil, ale uvádím ji pro kompletní dokumentaci, pokud by bylo v budoucnu potřeba řídit nabíjení softwarově.
Při konfiguraci jsem vycházel z těchto návodů, přičemž ani jeden není dokonalý pro moji situaci a musel jsem si návody přízpůsobit. Uvádím je pro úplnost jako zdroj:
Používám Suptronics X1005 2280 M.2 NVMe Dual Shield pro Raspberry Pi 5, který umožňuje připojení dvou disků.
Na desce jsou viditelně označeny dva sloty:
Při připojení jednoho disku do SSD1, systém jej rozpozná jako nvme0n1:
lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk ├─nvme0n1p1 259:1 0 512M 0 part /boot/firmware └─nvme0n1p2 259:2 0 1,8T 0 part /
Po připojení druhého disku do SSD2 došlo k nečekanému přeskupení číslování disků. Systém nyní rozpoznává:
* Disk připojený v SSD2 jako nvme0n1 * Disk připojený v SSD1 jako nvme1n1
Výstup příkazu `lsblk` po připojení druhého disku:
lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk nvme1n1 259:1 0 1,8T 0 disk ├─nvme1n1p1 259:2 0 512M 0 part /boot/firmware └─nvme1n1p2 259:3 0 1,8T 0 part /
Toto chování jsem nečekal, ale beru ho jako fakt a budu s ním dále pracovat obezřetně.
Abych si ušetřil problémy a následné zmatky, tak jsem raději disky prohodil. Tedy disk s operačním systémem jsem dal do slotu SSD2 a nový disk do slotu SSD1. Po změně zapojení vypadá výpis takto:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk ├─nvme0n1p1 259:1 0 512M 0 part /boot/firmware └─nvme0n1p2 259:2 0 1,8T 0 part / nvme1n1 259:3 0 1,8T 0 disk
Před vytvořením softwarového RAIDu je doporučeno ručně vytvořit odpovídající partitiony na novém disku (nvme0n1), aby odpovídaly rozdělení stávajícího disku (nvme1n1). RAID se obvykle vytváří nad existujícími partitionami, nikoliv nad celým diskem (i když je to možné, ale méně běžné).
K tomu použijeme příkaz sfdisk, který umožňuje zkopírovat tabulku oddílů ze nvme1n1 na nvme0n1.
Než cokoliv změníme, je vhodné uložit stávající partition tabulku, pokud by bylo potřeba ji obnovit:
sudo sfdisk -d /dev/nvme0n1 > partition_backup.txt
Tím se uloží rozložení oddílů do souboru partition_backup.txt, což umožní jejich případnou obnovu.
Zkopíruj stejnou partition tabulku ze nvme1n1 na nvme0n1:
sudo sfdisk /dev/nvme1n1 < partition_backup.txt
Tento příkaz vytvoří na nvme1n1 stejnou strukturu jako na nvme0n1.
Po provedení předchozího příkazu je vhodné ověřit, zda jsou partitiony nyní identické:
lsblk fdisk -l /dev/nvme1n1
Pokud se vše shoduje, můžeme pokračovat v nastavování RAIDu.
Pro konfiguraci softwarového RAIDu pro zrcadlení (RAID 1) použijeme mdadm.
Nejprve nainstalujeme potřebný balíček:
sudo apt install mdadm
Vzhledem k tomu, že RAID nastavujeme na běžícím systému, vytvoříme RAID v degradovaném režimu, tedy pouze s jedním diskem. Druhý disk přidáme později.
Místo dvou disků v RAIDu vytvoříme pole pouze s novým diskem (nvme1n1p1 a nvme1n1p2). Druhý disk zatím nebude připojen (`missing`), což RAID umožňuje:
sudo mdadm --create --verbose /dev/md0 --level=1 --raid-devices=2 /dev/nvme1n1p1 missing --metadata=0.90 sudo mdadm --create --verbose /dev/md1 --level=1 --raid-devices=2 /dev/nvme1n1p2 missing
✅ Vysvětlení:
Následujícím krokem je vytvoření souborového systému na nově vytvořeném RAIDu.
Na nových RAID oddílech vytvoříme souborový systém:
sudo mkfs.vfat /dev/md0 sudo mkfs.ext4 /dev/md1
Nyní připojíme RAID a přeneseme systémové soubory.
Nejprve připojíme bootovací oddíl RAID:
mkdir /mnt/raid_boot mount /dev/md0 /mnt/raid_boot rsync -axv /boot/firmware/ /mnt/raid_boot/
Poté připojíme hlavní oddíl a přeneseme systém:
mkdir /mnt/raid_root mount /dev/md1 /mnt/raid_root rsync -axv / /mnt/raid_root --exclude=/mnt --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/run --exclude=/tmp
Otevřeme soubor fstab na novém RAIDu:
nano /mnt/raid_root/etc/fstab
Najdeme řádky obsahující `/dev/nvme0n1p1` a `/dev/nvme0n1p2` a upravíme je:
/dev/md0 /boot/firmware vfat defaults 0 2 /dev/md1 / ext4 defaults,noatime,errors=remount-ro 0 1
Tím zajistíme, že systém při bootu použije RAID.
Zjistíme UUID RAID polí:
mdadm --detail --scan
Výstup bude podobný tomuto:
ARRAY /dev/md0 metadata=0.90 UUID=e11e72e6:cfe13794:c15f4f5c:b4c7de4f ARRAY /dev/md1 metadata=1.2 name=server:1 UUID=6af6a5bd:b7fd9bcc:2cd91b19:bf09e0c3
Tento výstup zapíšeme na konec souboru:
nano /mnt/raid_root/etc/mdadm/mdadm.conf
Otevřeme soubor bootovací konfigurace:
nano /mnt/raid_boot/cmdline.txt
Najdeme řádek obsahující:
root=PARTUUID=aa235387-02
A nahradíme jej:
root=/dev/md1 rootfstype=ext4 fsck.repair=yes rootwait rootdelay=10 cfg80211.ieee80211_regdom=CZ
✅ Vysvětlení:
Aby jádro vědělo, že používáme RAID již při bootu, přidáme moduly do initramfs:
nano /mnt/raid_root/etc/initramfs-tools/modules
Přidáme tyto řádky:
raid1 md_mod ext4
Aktualizujeme initramfs:
umount /mnt/raid_boot mount /dev/md0 /mnt/raid_root/boot/firmware/ mkdir -p /mnt/raid_root/dev /mnt/raid_root/proc /mnt/raid_root/sys /mnt/raid_root/run mount --bind /dev /mnt/raid_root/dev mount --bind /proc /mnt/raid_root/proc mount --bind /sys /mnt/raid_root/sys mount --bind /run /mnt/raid_root/run chroot /mnt/raid_root update-initramfs -u
Tím jsme zajistili, že RAID bude dostupný již při startu systému.
Nyní jsem mohl Raspberry restartovat. Důležitá věc, musel jsem primární disk - tedy disk s RAID přesunout do slotu SSD2 na desce. Dokud jsem to neudělal, boot se nepodařil, systém byl zmatený. Tento krok je klíčový - prohodit disky ve slotech.
Po prohození disků ve slotech (disk s nastaveným RAIDem musí být ve slotu SSD2) a nabootování systému je možné přidat druhý disk zpět do RAID pole. Stejný postup se použije i v případě, že se nějaký disk odpojí a pole je degradované, tedy běží pouze s jedním diskem.
✅ Klíčové pravidlo: Primární disk musí být ve slotu SSD2, aby systém správně nabootoval.
Z výpisu je vidět, že v RAID poli je zatím pouze jeden disk:
cat /proc/mdstat
Výstup:
Personalities : [raid1] [linear] [raid0] [raid6] [raid5] [raid4] [raid10] md0 : active raid1 nvme0n1p1[0] 524224 blocks [2/1] [U_] md1 : active raid1 nvme0n1p2[0] 1952854080 blocks super 1.2 [2/1] [U_] bitmap: 4/4 pages [64KB], 65536KB chunk
Nově připojený disk nvme1n1 zatím není součástí RAID pole.
Podíváme se na aktuální stav připojených disků:
lsblk
Výstup:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk ├─nvme0n1p1 259:1 0 512M 0 part │ └─md0 9:0 0 511,9M 0 raid1 /boot/firmware └─nvme0n1p2 259:2 0 1,8T 0 part └─md1 9:1 0 1,8T 0 raid1 / nvme1n1 259:3 0 1,8T 0 disk ├─nvme1n1p1 259:4 0 512M 0 part └─nvme1n1p2 259:5 0 1,8T 0 part
Zkontrolujeme aktuální stav RAID pole:
mdadm --detail /dev/md0
/dev/md0: Version : 0.90 Creation Time : Sat Feb 15 16:52:29 2025 Raid Level : raid1 Array Size : 524224 (511.94 MiB 536.81 MB) Used Dev Size : 524224 (511.94 MiB 536.81 MB) Raid Devices : 2 Total Devices : 1 Persistence : Superblock is persistent Update Time : Sat Feb 15 19:15:46 2025 State : clean, degraded Active Devices : 1 Working Devices : 1 Failed Devices : 0 Spare Devices : 0 Consistency Policy : resync Number Major Minor RaidDevice State 0 259 1 0 active sync /dev/nvme0n1p1 - 0 0 1 removed
Stejným způsobem můžeme zkontrolovat i hlavní RAID oddíl:
mdadm --detail /dev/md1
Výstup ukazuje, že RAID pole je degradované – chybí druhý disk.
Nyní přidáme nový disk nvme1n1 do RAID pole:
mdadm --add /dev/md0 /dev/nvme1n1p1 mdadm --add /dev/md1 /dev/nvme1n1p2
Po přidání zkontrolujeme stav RAIDu:
cat /proc/mdstat
Výstup ukazuje, že RAID začíná synchronizaci:
Personalities : [raid1] [linear] [raid0] [raid6] [raid5] [raid4] [raid10] md0 : active raid1 nvme1n1p1[1] nvme0n1p1[0] 524224 blocks [2/2] [UU] md1 : active raid1 nvme1n1p2[2] nvme0n1p2[0] 1952854080 blocks super 1.2 [2/1] [U_] [=>...................] recovery = 5.3% (104572928/1952854080) finish=149.1min speed=206517K/sec bitmap: 4/4 pages [64KB], 65536KB chunk
Pro sledování průběhu synchronizace RAID pole můžeme použít:
watch -n 1 cat /proc/mdstat
✅ RAID nyní probíhá synchronizace a disk bude plně zrcadlen po dokončení procesu.
Pokud dojde k odpojení jednoho disku a následně jej znovu připojíme, systém rozhodne, který disk bude v RAIDu upřednostněn, a to na základě několika faktorů.
Nezáleží na tom, že je disk ve slotu SSD2, protože po připojení obou disků systém automaticky vybere ten, který běžel jako poslední aktivní po rozpojení RAIDu.
Systém rozhoduje na základě poslední aktualizace metadat RAIDu. Každý disk v RAIDu obsahuje metadata (superblock), která uchovávají informace o změnách v poli. Klíčový parametr je tzv. Event Count, což je čítač změn.
✅ RAID vybere disk s nejvyšším Event Count jako platný. Pokud má jeden disk vyšší Event Count než druhý, systém považuje tento disk za aktuální a použije jej jako primární.
Můžeš si ověřit, který disk má aktuálnější metadata pomocí příkazu:
mdadm --examine /dev/nvme0n1p2 /dev/nvme1n1p2
Výstup bude obsahovat řádky podobné tomuto:
/dev/nvme0n1p2: Events : 405 /dev/nvme1n1p2: Events : 392
✅ Disk s vyšším číslem „Events“ je považován za aktuální. Pokud se Event Count neshoduje, mdadm automaticky označí starší disk jako neaktuální a vyřadí ho z RAID pole.
Pokud má jeden z disků nižší Event Count, systém jej při dalším spuštění považuje za zastaralý a označí jej jako neaktivní. RAID pak při připojení tohoto disku provede resynchronizaci dat.
Proto je důležité po výpadku disku **zkontrolovat stav RAID