我可以使用 Synology DS 1618+ 作为 TFTP 和 NFS 服务器,通过 NFS 在 Raspberry Pi 4b 上网络启动 Ubuntu 20.04。但我想保护根文件系统,以便overlayroot
多台机器可以从同一个根目录同时运行。这对我来说行不通。我问了一个问题几天前我在 Ask Ubuntu 上问过这个问题,但并没有得到任何有用的见解。我现在对这个问题有了更多的了解,想在这里为更广泛的受众重新表述这个问题。
问题
虽然我可以使用 NFS 在 RPi4 上通过网络启动 Ubuntu 20.04,但只要我启用overlayroot
( overlayroot="tmpfs:recurse=0"
),系统就会以degraded
( systemctl is-system-running
) 的状态启动。这似乎很明显某物与……有关overlayroot
。
在这种状态下,只有root
可以登录。其他用户都无法通过登录/密码提示。
检查syslog
发现,启动过程中出现的第一个错误是 的启动system-networkd
,它失败并显示消息(“不支持操作”)。进一步检查发现systemd-networkd
试图以用户身份运行(system-network
)。由于system-netwworkd
无法启动,因此许多其他服务也无法启动:
UNIT LOAD ACTIVE SUB DESCRIPTION
● atd.service loaded failed failed Deferred execution scheduler
● avahi-daemon.service loaded failed failed Avahi mDNS/DNS-SD Stack
● systemd-networkd.service loaded failed failed Network Service
● systemd-resolved.service loaded failed failed Network Name Resolution
● systemd-timesyncd.service loaded failed failed Network Time Synchronization
● systemd-networkd.socket loaded failed failed Network Service Netlink Socket
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
6 loaded units listed.
配置
DHCP服务器
我有一对 ISC DHCP 服务器,它们已经运行了一年多。我对它们的配置进行了以下更改以支持网络启动:
# DHCP configuration for PXE boot of RPI4
option tftp-server-name "192.168.8.20"; #option 66
option bootfile-name "bootcode.bin"; #option 67
option vendor-class-identifier code 60 = string;
option vendor-encapsulated-options code 43 = string;
option space RPi code width 1 length width 1;
option RPi.discovery code 6 = unsigned integer 8;
option RPi.menu-prompt code 10 = text;
option RPi.menu-item code 9 = text;
option vendor-class-identifier "PXEClient";
option vendor-encapsulated-options "Raspberry Pi Boot";
vendor-option-space RPi;
option RPi.discovery 3;
option RPi.menu-prompt "PXE";
option RPi.menu-item "Raspberry Pi Boot";
filename "pxelinux.0";
next-server 192.168.8.20;
option tftp-server-address 192.168.8.20;
我承认我并不完全理解这一点,但它确实有效:-) 我确信其中有些东西是 RPi4 没有使用到的。
树莓派 4b
我已经设置了 RPi4 引导加载程序,如下所示:
$ sudo rpi-eeprom-config
[all]
BOOT_UART=0
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=1
BOOT_ORDER=0xf21
TFTP_PREFIX=1
TFTP_PREFIX_STR=RPi4-Ubuntu/
Synology DS 1618+ NAS
TFTP 服务器
在启动时,RPi4 发送TFTP_PREFIX_STR
上述文件并从 Synology NAS 上的 TFTP 服务器接收以下文件:
bcm2710-rpi-2-b.dtb bootcode.bin initrd.img
bcm2710-rpi-3-b.dtb boot.scr overlay_map.dtb
bcm2710-rpi-3-b-plus.dtb cmdline.txt overlays
bcm2710-rpi-cm3.dtb config.txt start4cd.elf
bcm2710-rpi-zero-2.dtb fixup4cd.dat start4db.elf
bcm2711-rpi-400.dtb fixup4.dat start4.elf
bcm2711-rpi-4-b.dtb fixup4db.dat start4x.elf
bcm2711-rpi-cm4.dtb fixup4x.dat start_cd.elf
bcm2837-rpi-3-a-plus.dtb fixup_cd.dat start_db.elf
bcm2837-rpi-3-b.dtb fixup.dat start.elf
bcm2837-rpi-3-b-plus.dtb fixup_db.dat start_x.elf
bcm2837-rpi-cm3-io3.dtb fixup_x.dat vmlinuz
这些来自 RPi 的 Ubuntu 20.04 安装映像(分区boot
)。我对进行了以下修改config.txt
:
[pi4]
# Run as fast as firmware / board allows
arm_boost=1
[all]
arm_64bit=1
device_tree_address=0x03000000
enable_uart=1
cmdline=cmdline.txt
kernel=vmlinuz
initramfs initrd.img followkernel
include syscfg.txt
include usercfg.txt
和cmdline.txt
:
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.8.20:/volume3/pxe/nfs/RPi4-Ubuntu/OS,tcp,rw ip=dhcp rootfstype=nfs elevator=deadline rootwait
NFS 服务器
NFS 服务器提供nfsroot
中提到的cmdline.txt
根目录 ( /
)。这基本上是rootfs
Ubuntu 发行版的分区。它还提供 Ubuntu 发行版boot
分区中的文件,这些文件安装在/boot
。
exports -v
显示以下内容:
/volume3/pxe 192.168.0.0/21(rw,async,no_wdelay,hide,crossmnt,no_subtree_check,insecure_locks,anonuid=1024,anongid=100,sec=sys,insecure,root_squash,no_all_squash)
/volume3/pxe 192.168.8.0/21(rw,async,no_wdelay,hide,crossmnt,no_subtree_check,insecure_locks,anonuid=1024,anongid=100,sec=sys,insecure,root_squash,no_all_squash)
/volume3/pxe 192.168.32.0/21(rw,async,no_wdelay,hide,crossmnt,no_subtree_check,insecure_locks,anonuid=1024,anongid=100,sec=sys,insecure,root_squash,no_all_squash)
/volume3/pxe 192.168.72.0/21(rw,async,no_wdelay,hide,crossmnt,no_subtree_check,insecure_locks,anonuid=1024,anongid=100,sec=sys,insecure,root_squash,no_all_squash)
在启动过程中,Synology NFS 和 RPi4 似乎只会使用 NFSv3。/etc/fstab
然而,它们似乎都乐于使用 NFSv4/NFSv4.1。
回到 Pi
有了这样的配置,RPi 就可以以 root 身份通过 NFS 文件系统在网络上顺利启动和运行。然而,此时,为了保护根文件系统不被写入,我继续修改配置文件,使其如下overlayroot
所示/etc/overlayroot.conf
:
overlayroot_cfgdisk="disabled"
#overlayroot=""
overlayroot="tmpfs:recurse=0,debug=1"
(我省略了之前的 160 多行注释。)
当我重新启动时,上述问题又出现了。
请帮助?
我已经尝试了上述方法,分别在 32 位和 64 位 Ubuntu 22.04 上,结果完全相同。我尝试了 Raspberry OS 11(64 位),但它没有提供overlayroot
选项。它的替代方案内置于 中raspi-config
,不适用于 NFS。所以我没有继续尝试。
然而,基于 Raspberry OS 的做法,我大大简化了 Ubuntu 的 TFTP 配置。
如果问题与 Synology NFS 服务器有关,我不会感到惊讶,但我真的不知道从哪里开始查找。
我当然不会排除我在某个地方犯了错误的想法,所以如果有人能指出这一点,我将不胜感激。
一旦 Ubuntu 22.04 推出,我也会尝试一下。
网上有很多人讨论过如何做这件事。我读了很多文章,并试图采纳他们的意见。我看到过一两篇关于 NFS 根文件系统可能存在问题的文章overlayroot
。但我没有看到任何准确描述我试图做的事情的文章。
答案1
答案2
从 askubuntu 上的同一个问题复制而来:
根本问题似乎是在某些 NFS 服务器配置中行为不正确。也就是说,在未实现 NFSv3 导出的服务器上使用overlayfs
时,会出现问题overlayfs
v3 的可选 NFSACL 协议扩展. 看起来像这样并不是唯一一个overlayfs
在 ACL 方面非常脆弱的情况。显然,v3 和 v4 NFS 都存在(仍然存在?)问题。
我能够将问题简化为不涉及启动的问题,而只需 overlayfs 和 NFS 导出。使用从 Ubuntu 机器(确实实现了 NFSACLv3)提供的 Ubuntu 映像的 NFS 导出以及其中带有/tmp/overlaygames/
空的upper
、work
和overlay
目录的目录,以下脚本将运行而不会出错:
#!/bin/bash
sudo mount -t nfs -o ro,vers=3 10.99.0.1:/srv/nfs/ubuntu-20.04.3 /media/nfs/
sudo mount -t overlay -o lowerdir=/media/nfs,upperdir=/tmp/overlaygames/upper,workdir=/tmp/overlaygames/workdir/ overlay /tmp/overlaygames/overlay
ls /tmp/overlaygames/overlay/home
运行该脚本后,运行此脚本来卸载并清理:
#!/bin/bash
pushd /tmp/overlaygames
sudo umount overlay
rm -rf workdir
mkdir workdir
sudo umount /media/nfs
popd
现在运行完全相同的脚本,但使用 noacl 选项禁用 NFSACLv3 客户端:
#!/bin/bash
sudo mount -t nfs -o ro,noacl,vers=3 10.99.0.1:/srv/nfs/ubuntu-20.04.3 /media/nfs/
sudo mount -t overlay -o lowerdir=/media/nfs,upperdir=/tmp/overlaygames/upper,workdir=/tmp/overlaygames/workdir/ overlay /tmp/overlaygames/overlay
ls /tmp/overlaygames/overlay/home
将回归熟悉的
ls: cannot open directory '/tmp/overlaygames/overlay/home': Operation not supported
同样,从第一个脚本开始但将 NFS 导出放在 FreeNAS/TrueNAS(FreeBSD)机器上,也会返回,Operation not supported
因为 FreeBSD 没有实现 NFSACLv3(通过捕获数据包验证)。
有趣的是,在 FreeBSD 上使用 NFS 共享时指定vers=2
似乎工作得很好。当然,与 NFSv3 相比,NFSv2 有一些限制。