用于数据持久性、存储寿命和断电保护的 OverlayFS

典型的 Raspberry Pi 使用 microSD 卡来写入操作系统,这是一种方便但容易损坏的存储介质。在 CM5 等工业应用中使用 eMMC,是因为它比 microSD 卡更坚固。在 CM5 等工业应用中使用 eMMC 的原因之一是它是一种比 microSD 卡更坚固的存储介质。

通过将 microSD 卡或其他存储介质的操作系统部分设置为只读,可以大大减少对存储介质的写入量,从而延长存储介质的使用寿命。此外,它还能增加防止操作系统部分在突然断电时受损的可能性。

Raspberry Pi 有一种名为 “覆盖文件系统 “的方法,可以通过 raspi-config 轻松配置。从raspi-config进行配置已经有一段时间了。

OverlayFS 是一种将系统(操作系统)视为只读(RO)的机制,通过只复制和存储写入到另一个可写区域(上层)的文件,使整个系统看起来像一个单一的文件系统。

该可写区域在内存中以 tmpfs 的形式展开,并将在重新打开电源后消失。
乍一看,系统可被视为已被修改和保存,但系统部分是只读的,并未被修改。
因此,如果关闭电源,什么也不会丢失。
这意味着系统将恢复到其被设置为只读时的状态。

我们希望在重启后至少保留和使用最少数量的文件。
使用 Overlayfs 时,可以通过将数据以符号链接的方式疏散到单独的分区来实现这一点。
在本例中,我们只关注与网络相关的更改和保存主文件夹。

本次测试的测试环境

我们这次测试的环境如下。

  • 32 GB microSD 卡(建议 64 GB 或以上)
  • Ubuntu 桌面 25.10(64 位)
  • 将 /data 分割成一个单独的分区
  • 使用符号链接(symlink)保存到/data
  • 网络使用 NetworkManager
  • 通过编辑 cmdline.txt 手动配置 OverlayFS
  • 测试在实际的 Pi 5 机器上进行(此方法同样适用于配备 CM5 的 PL-R5)

我们正试图分割 10 GB /data 空间的 microSD 卡。

分割分区的方法与分割分区的方法相同,其中 如何分割安装操作系统的分区中的方法相同。

启动已分区撤离的 Ubuntu 后,完成更新。
在这种状态下,我们将继续下一步。

配置流程

设置的一般流程如下

1.编写 Ubuntu
2.在实际机器上启动并完成初始设置和更新。
3.在另一台机器上读取一次 microSD 卡并分区(约 10GB 用于保存数据)。
4.覆层前的准备工作
5.启用 Overlayfs


最后,启用 Overlayfs 后,检查网络设置是否有更改等。

挂载另一个分区

我们将在挂载分区后对其进行处理。
lsblk 检查分区是否尚未挂载。(mmcblk0p3)

NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
mmcblk0     179:0    0  29.7G  0 disk 
├─mmcblk0p1 179:1    0   512M  0 part /boot/firmware
├─mmcblk0p2 179:2    0  19.9G  0 part /
└─mmcblk0p3 179:3    0   9.3G  0 part 

在根目录下创建 /data,并在其中挂载 mmcblk0p3。

sudo mkdir -p /data
sudo mount /dev/mmcblk0p3 /data

└─mmcblk0p3 179:3 0 9.3G 0 part /data如果

若要在启动时自动挂载,请在 fstab.blkid 或下一个 coman 中添加,以找出 UUID。

sudo blkid -s UUID -o value /dev/mmcblk0p3

lsblk -f /dev/mmcblk0

复制 UUID,然后将其添加到 fstab 中,地址为sudo nano /etc/fstab 。(UUID 应读作 。)

UUID=f3afb6b2-a959-4c4b-bdb6-3c38a0fe33be /data ext4 defaults 0 2

更新并重新安装,检查 MOUNT 状态。

sudo systemctl daemon-reload
sudo mount -a
mount | grep /data

/dev/mmcblk0p3 on /data type ext4 (rw,relatime,errors=remount-ro)显示,则表示没问题。

/数据分区的作用

/home 目录也保存在 /data 区域。

系统的 rootfs 应该是 Overlayfs,末尾为只读 (ro)。
有两种方法:符号链接(symlink)方法和绑定挂载方法。

这次是一个符号链接。

覆盖文件 + 符号链接

符号链接的工作流程如下

1.创建一个目录作为肢端链接目标,并将其作为挂载点。
2.复制原始文件。
3.创建符号链接。
4.确认符号链接。

正确设置符号链接后,我们将把它们转换为 Overlayfs。

1. 创建挂载点目录

在执行符号链接之前,只准备一个空目录。挂载点。

在这种情况下,以下五个方面将被象征性地联系起来。

  • /etc/NetworkManager
  • /var/lib/NetworkManager
  • /home
  • /etc/hostname
  • /etc/hosts
  • 在 /etc/netplan /data 中创建一个挂载目录。
sudo mkdir -p /data/etc/NetworkManager
sudo mkdir -p /data/var/lib/NetworkManager
sudo mkdir -p /data/home
sudo mkdir -p /data/etc/netplan

2. 复制文件

将原始数据复制到 /data 侧。
命令中的目录名称应包括尾部的斜线,因为在这种情况下,我们只想将内容复制到已经存在的目录中。
如果在这方面出了差错,就会陷入嵌套目录的困境。

-斜线表示 “包含内容”
-无表示 “创建整个文件夹”

# Copy NetworkManager configuration
sudo rsync -a /etc/NetworkManager/ /data/etc/NetworkManager/
sudo rsync -a /var/lib/NetworkManager/ /data/var/lib/NetworkManager/

# Copy netplan configuration
sudo rsync -a /etc/netplan/ /data/etc/netplan/

# Copy the home directory
sudo rsync -a /home/ /data/home/

# Copy configuration files
sudo cp -a /etc/hosts /data/etc/hosts
sudo cp -a /etc/hostname /data/etc/hostname

hosts 和 hostname 是一个文件。因此,cp -a命令没有问题。
*netplan/ 包含 Wi-Fi 连接信息。

3. 创建符号链接

在创建符号链接前删除原始文件组。

sudo rm -rf /etc/NetworkManager
sudo ln -s /data/etc/NetworkManager /etc/NetworkManager

sudo rm -rf /var/lib/NetworkManager
sudo ln -s /data/var/lib/NetworkManager /var/lib/NetworkManager

sudo rm -rf /etc/netplan
sudo ln -s /data/etc/netplan /etc/netplan

# Move to the root directory before modifying /home
cd /
sudo rm -rf /home
sudo ln -s /data/home /home

sudo ln -sf /data/etc/hosts /etc/hosts
sudo ln -sf /data/etc/hostname /etc/hostname

我们将在这里检查一次。

ls -l /etc/NetworkManager
ls -l /var/lib/NetworkManager
ls -l /etc/netplan
ls -l /home
ls -l /etc/hostname
ls -l /etc/hosts

例如,显示屏应该如下所示

lrwxrwxrwx 1 root root 24 Feb  7 21:08 /etc/NetworkManager -> /data/etc/NetworkManager
lrwxrwxrwx 1 root root 28 Feb  7 21:09 /var/lib/NetworkManager -> /data/var/lib/NetworkManager
lrwxrwxrwx 1 root root 17 Feb  9 09:40 /etc/netplan -> /data/etc/netplan
lrwxrwxrwx 1 root root 10 Feb  7 21:09 /home -> /data/home
lrwxrwxrwx 1 root root 18 Feb  7 21:10 /etc/hostname -> /data/etc/hostname
lrwxrwxrwx 1 root root 15 Feb  7 21:10 /etc/hosts -> /data/etc/hosts

检查 NetworkManager 和其他程序是否使用/data 侧的符号链接。

realpath /etc/NetworkManager
realpath /etc/NetworkManager
realpath /var/lib/NetworkManager

因此,如果 realpath 命令也显示了 /data 侧的路径,也没有问题。

/data/etc/NetworkManager
/data/var/lib/NetworkManager

挂载的 /data 分区最终会变成这样。

副本已在 /data 侧准备就绪,该侧是可写的。

4. 安装和更新 Overlayfs


安装 overlayroot 并更新 initramfs。

1. 安装 Overlayfs(overlayroot)
2. 添加到 cmdline.txt
3. 使用 Overlayfs 更改网络设置,并检查是否是永久性的

sudo apt update
sudo apt install overlayroot
sudo update-initramfs -u
sudo reboot

更新完成后,initramfs 会显示如下内容。

update-initramfs: Generating /boot/initrd.img-6.17.0-1007-raspi
Using DTB: bcm2712-rpi-5-b.dtb
Installing /lib/firmware/6.17.0-1007-raspi/device-tree/broadcom/bcm2712-rpi-5-b.dtb into /boot/dtbs/6.17.0-1007-raspi/./bcm2712-rpi-5-b.dtb
Taking backup of bcm2712-rpi-5-b.dtb.
Installing new bcm2712-rpi-5-b.dtb.
flash-kernel: installing version 6.17.0-1007-raspi
Copying kernel assets to /boot/firmware/new/
Copying boot firmware to /boot/firmware/new/
Copying device trees to /boot/firmware/new/
Copying device tree overlays to /boot/firmware/new/overlays/
Please be aware next reboot will boot twice

5.添加到 cmdline.txt


cmdline.txt 的路径与 Raspberry Pi 操作系统不同。

sudo nano /boot/firmware/current/cmdline.txt

添加到 cmdline.txt 的开头。
注意:cmdline.txt 必须写在一行上。不得换行。项目之间用空格隔开。

overlayroot=tmpfs:recurse=0
overlayroot=tmpfs:recurse=0 zswap.enabled=1 zswap.compressor=zstd multipath=off dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 panic=10 rootwait fixrtc quiet splash

写完后,重新启动。


重新启动,查看是否只有 bootfs 现在是只读 (ro)。

检查只读和可写。

重启后,确保在 rootfs 端正确启用 Overlayfs。
反之,也会检查 /data 的可写性。

首先,lsblk 的结果是 rootfs 现在是正确的 overlayfs。(/media/root-ro)
/data 原本就是 rw。

mmcblk0     179:0    0  29.7G  0 disk 
├─mmcblk0p1 179:1    0   512M  0 part /boot/firmware
├─mmcblk0p2 179:2    0  19.9G  0 part /media/root-ro
└─mmcblk0p3 179:3    0   9.3G  0 part /data

在终端中连接 SSH 时,通常可以看到它,因为连接时会显示。

tmpfs-root /media/root-rw tmpfs rw,relatime,inode64 0 0
overlayroot / overlay rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_,uuid=on,nouserxattr 0 0
/dev/mmcblk0p2 /media/root-ro ext4 ro,relatime 0 0

我们将逐一与他们核实。

mount | grep " on / "
mount | grep /data
ls -l /etc | grep NetworkManager
ls -l / | grep /home

预期成果:

mount | grep " on / "
overlayroot on / type overlay (rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_,uuid=on,nouserxattr)

mount | grep /data
/dev/mmcblk0p3 on /data type ext4 (rw,relatime)

ls -l /etc | grep NetworkManager
lrwxrwxrwx 1 root                 root                    24 Feb  7 21:08 NetworkManager -> /data/etc/NetworkManager

ls -l / | grep /home
lrwxrwxrwx   1 root    root            10 Feb  7 21:09 home -> /data/home

您看到预期结果了吗?Overlayfs 已完成。

我会做最后的测试。

我要测试几样东西。

更改 Wi-Fi 目的地

即使在 Overlayfs 状态下,我们也会更改 Wi-Fi 目标地址,并验证重启后是否仍能反映出来。

Wi-Fi 连接信息以 yaml 格式存在于 /etc/netplan 中。
由于这也是一个符号链接,因此 /data 侧被重写,原始 /etc 也应引用它。

在更改之前,有一个名为 90-NM-~ 的 yaml。

sudo ls -l /data/etc/netplan/

-rw------- 1 root root 157 Oct  7 11:52 50-cloud-init.yaml
-rw------- 1 root root 706 Oct  7 11:55 90-NM-32f4a827-cc10-4a0e-aae9-64158b7a33e7.yaml

我使用桌面上的图形用户界面控件将 5g Wi-Fi 更改为 2g Wi-Fi。
结果,我又多了一个。当然,它是连接到 Wi-Fi 的。

-rw------- 1 root root 157 Oct  7 11:52 50-cloud-init.yaml
-rw------- 1 root root 706 Feb  9 09:54 90-NM-201e82b9-74eb-4783-a9db-48e3a5d7f14e.yaml
-rw------- 1 root root 706 Oct  7 11:55 90-NM-32f4a827-cc10-4a0e-aae9-64158b7a33e7.yaml

如果在此状态下重启后,两者的维护方式相同,则没有问题。它们确实得到了维护。

现在,我们甚至可以在 Overlayfs 状态下更改 Wi-Fi 连接信息。

如果重启后文件不见了,确定。


让我们直接在 root 下创建一个测试文件。

sudo touch /test_file

由于 rootfs 是一个 overlayfs,它的行为就像在内存中被修改过一样。此时,你可以对它进行写入操作。
但这只是写在 tmpfs 中,所以重启后就会消失。

如果文件本身在重启后消失,则说明 Overlayfs 正常工作。

重新启动并使用ls -l /test_file等进行检查。
它应该会消失。

要撤销 overlayfs

因此,在 Overlayfs 状态下,重启将使系统返回到创建 Overlayfs 时的状态。
这是因为原始 rootfs 区域为只读 (ro),在其上层内存中表现为 (tmpfs) 扩展。
重启后,tmpfs 将消失。

要将 rootfs 的只读状态恢复为正常读/写状态,请删除附在 cmdline.txt 中的overlayroot=tmpfs:recurse=0
然后重新启动,就会恢复正常。

如果想再次转换为 Overlayfs,只需在 cmdline.txt 中添加相同的信息即可。
这样做是因为 bootfs 仍然是可写的。

最低限度的数据持久性

这次,在 Overlayfs 环境中,我们将一些与网络相关的目录和 /home 目录转移到了一个单独的分区。
这些更改得到了正确的维护,因此数据被成功持久化。

符号链接对某些文件很有效。

但是,持久保存一整组经常被访问的文件并没有太大意义。在这种情况下尤其如此,因为这些分区只是在同一个存储介质中被切断了。
如果使用 Overlayfs 将 rootfs 设置为只读,但访问同一媒体的次数却越来越多,那就不好了。

最好能导出配置数据或保存在 Overlayfs 状态下生成的文件。
,我希望尽可能精确地确定设置。

补编第 1 号

事实上,使用 Raspberry Pi OS 时,我无法实现这一功能,我还以为是 Trixie 的问题,但显然在 bullseye 之前是可以实现的,而在 bookworm 中则无法实现同样的操作。

就我发现和验证的情况来看,无论是 symlinks 还是 bindmounts,都没有产生预期的结果;它们似乎是在 Raspberry Pi 操作系统的深处被强制执行的。

特别是,绑定挂载已改为逐块挂载,并降级为简单挂载。
我不是这方面的 Raspberry Pi OS 开发人员,所以不知道为什么。这可能是防止初学者意外破坏系统的一种方法。

据我测试,Ubuntu 没有问题。

补编第 2 号

我尝试使用 hostnamectl 命令更改 overlayfs 状态下的主机名,但 SSH 连接仍然是个问题,只能使用更改前的主机名进行连接。连接后,主机名也发生了变化,只有 SSH 似乎能接收到漂亮的主机名。看来最好在禁用 overlayfs 后再更改主机名。

请注意,Ubuntu 最初并未安装 SSH 服务器。必须使用以下命令安装并激活。

sudo apt install openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh

文章由拉斯必达提供

非工程师也能愉快使用的 Raspberry Pi 信息网站 raspida.com一个非工程师也能享受和使用的 Raspberry Pi 信息网站。他还为 PiLink 网站提供有关工业用 Raspberry Pi 的技术博客文章