通过 NFS 挂载根文件系统 (nfsroot)

作者:

1996 年由 Gero Kuhlmann 编写 <gero@gkminix.han.de>

1997 年由 Martin Mares 更新 <mj@atrey.karlin.mff.cuni.cz>

2006 年由 Nico Schottelius 更新 <nico-kernel-nfsroot@schottelius.org>

2006 年由 Horms 更新 <horms@verge.net.au>

2018 年由 Chris Novakovic 更新 <chris@chrisn.me.uk>

为了使用无盘系统,例如 X 终端或打印机服务器等,根文件系统必须存在于非磁盘设备上。这可以是 initramfs (请参阅Ramfs、rootfs 和 initramfs),ramdisk (请参阅使用初始 RAM 磁盘 (initrd)) 或通过 NFS 挂载的文件系统。以下文本描述了如何使用 NFS 作为根文件系统。在本文的其余部分,“客户端” 指的是无盘系统,“服务器” 指的是 NFS 服务器。

启用 nfsroot 功能

为了使用 nfsroot,需要在配置期间选择内置的 NFS 客户端支持。一旦选择了此选项,nfsroot 选项将变为可用,也应选择此选项。

在网络选项中,可以选择内核级自动配置以及要支持的自动配置类型。选择所有 DHCP、BOOTP 和 RARP 是安全的。

内核命令行

当内核被引导加载程序加载后(请参见下文),它需要被告知要使用的根文件系统设备。在 nfsroot 的情况下,需要告知内核在哪里找到服务器以及服务器上要挂载为根目录的目录的名称。可以使用以下内核命令行参数来建立此信息

root=/dev/nfs

这是启用伪 NFS 设备所必需的。请注意,它不是一个真正的设备,而只是一个同义词,告诉内核使用 NFS 而不是真正的设备。

nfsroot=[<服务器 IP>:]<根目录>[,<nfs-选项>]

如果在命令行上未给出 nfsroot 参数,将使用默认的 ``"/tftpboot/%s"``。

<服务器 IP> 指定 NFS 服务器的 IP 地址。

默认地址由 ip 参数确定(请参见下文)。此参数允许对 IP 自动配置和 NFS 使用不同的服务器。

<根目录> 服务器上要挂载为根目录的目录的名称。

如果字符串中存在 “%s” 标记,它将被替换为客户端 IP 地址的 ASCII 表示形式。

<nfs-选项> 标准 NFS 选项。所有选项都用逗号分隔。

使用以下默认值

port            = as given by server portmap daemon
rsize           = 4096
wsize           = 4096
timeo           = 7
retrans         = 3
acregmin        = 3
acregmax        = 60
acdirmin        = 30
acdirmax        = 60
flags           = hard, nointr, noposix, cto, ac
ip=<客户端 IP>:<服务器 IP>:<网关 IP>:<网络掩码>:<主机名>:<设备>:<自动配置>:<dns0-ip>:<dns1-ip>:<ntp0-ip>

此参数告诉内核如何配置设备的 IP 地址以及如何设置 IP 路由表。它最初被称为 nfsaddrs,但是现在启动时的 IP 配置独立于 NFS 工作,因此它被重命名为 ip,旧名称仍然保留为别名以实现兼容性。

如果内核命令行中缺少此参数,则假定所有字段为空,并应用下面提到的默认值。通常,这意味着内核尝试使用自动配置来配置所有内容。

<自动配置> 参数可以单独作为 ip 参数的值出现(在之前没有所有的 “:” 字符)。如果值为 “ip=off” 或 “ip=none”,则不会进行自动配置,否则将进行自动配置。最常见的用法是 “ip=dhcp”。

<客户端 IP> 客户端的 IP 地址。

默认值:使用自动配置确定。

<服务器 IP> NFS 服务器的 IP 地址。

如果使用 RARP 来确定客户端地址,并且此参数不为空,则仅接受来自指定服务器的回复。

仅对于 NFS 根目录是必需的。也就是说,如果缺少此参数并且 NFS 根目录未运行,则不会触发自动配置。

值以 “bootserver ” 为前缀导出到 /proc/net/pnp(请参见下文)。

默认值:使用自动配置确定。使用自动配置服务器的地址。

<网关 IP> 如果服务器位于不同的子网上,则为网关的 IP 地址。

默认值:使用自动配置确定。

<网络掩码> 本地网络接口的网络掩码。

如果未指定,则网络掩码是从客户端 IP 地址派生的,假设是按类的寻址。

默认值:使用自动配置确定。

<主机名> 客户端的名称。

如果存在 “.” 字符,则第一个 “.” 之前的任何内容都用作客户端的主机名,之后的任何内容都用作其 NIS 域名。 可以通过自动配置提供,但它的缺失不会触发自动配置。如果指定了并且使用了 DHCP,则用户提供的主机名(以及 NIS 域名,如果存在)将包含在 DHCP 请求中;这可能会导致为客户端创建或更新 DNS 记录。

默认值:客户端 IP 地址以 ASCII 表示法使用。

<设备> 要使用的网络设备的名称。

默认值:如果主机只有一个设备,则使用它。否则,使用自动配置来确定设备。这是通过从所有设备发送自动配置请求,并使用收到第一个回复的设备来完成的。

<自动配置> 用于自动配置的方法。

在指定多个自动配置协议的选项的情况下,将使用所有协议发送请求,并使用第一个回复的协议。

无论此选项的值如何,都只会使用已编译到内核中的自动配置协议

off or none: don't use autoconfiguration
              (do static IP assignment instead)
on or any:   use any protocol available in the kernel
             (default)
dhcp:        use DHCP
bootp:       use BOOTP
rarp:        use RARP
both:        use both BOOTP and RARP but not DHCP
             (old option kept for backwards compatibility)

如果使用 dhcp,则可以使用以下格式 “ip=dhcp,client-id-type,client-id-value” 使用客户端标识符

默认值:任意

<dns0-ip> 主名称服务器的 IP 地址。

值以 “nameserver ” 为前缀导出到 /proc/net/pnp(请参见下文)。

默认值:如果未使用自动配置则为无;如果使用自动配置则自动确定。

<dns1-ip> 辅助名称服务器的 IP 地址。

请参阅 <dns0-ip>。

<ntp0-ip> 网络时间协议 (NTP) 服务器的 IP 地址。

值被导出到 /proc/net/ipconfig/ntp_servers,但在其他情况下未使用(见下文)。

默认值:如果未使用自动配置则为无;如果使用自动配置则自动确定。

配置完成后(无论是手动还是自动),将创建两个格式如下的文件;如果配置后它们各自的值为空,则会省略相应的行

  • /proc/net/pnp

    #PROTO: <DHCP|BOOTP|RARP|MANUAL>(取决于配置方法) domain <dns-domain>(如果自动配置,则为 DNS 域名) nameserver <dns0-ip>(主域名服务器 IP) nameserver <dns1-ip>(辅助域名服务器 IP) nameserver <dns2-ip>(第三域名服务器 IP) bootserver <server-ip>(NFS 服务器 IP)

  • /proc/net/ipconfig/ntp_servers

    <ntp0-ip>(NTP 服务器 IP) <ntp1-ip>(NTP 服务器 IP) <ntp2-ip>(NTP 服务器 IP)

<dns-domain> 和 <dns2-ip>(在 /proc/net/pnp 中)以及 <ntp1-ip> 和 <ntp2-ip>(在 /proc/net/ipconfig/ntp_servers 中)是在自动配置期间请求的;它们不能被指定为“ip=”内核命令行参数的一部分。

由于“domain”和“nameserver”选项被 DNS 解析器识别,因此在使用 NFS 根文件系统的系统中,/etc/resolv.conf 通常链接到 /proc/net/pnp。

请注意,内核不会与它发现的任何 NTP 服务器同步系统时间;这是用户空间进程的责任(例如,initrd/initramfs 脚本,它会在挂载真正的根文件系统(如果它在 NFS 上)之前,将 /proc/net/ipconfig/ntp_servers 中列出的 IP 地址传递给 NTP 客户端)。

nfsrootdebug

此参数使调试消息在启动时出现在内核日志中,以便管理员可以验证正确的 NFS 挂载选项、服务器地址和根路径是否传递给 NFS 客户端。

rdinit=<可执行文件>

要指定哪个文件包含启动系统初始化的程序,管理员可以使用此命令行参数。此参数的默认值为“/init”。如果指定的文件存在并且内核可以执行它,则会忽略与根文件系统相关的内核命令行参数,包括“nfsroot=”。

有关挂载根文件系统过程的说明,请参阅 早期用户空间支持

引导加载程序

为了将内核加载到内存中,可以使用不同的方法。它们取决于可用的各种设施

  • 使用 syslinux 从软盘启动

    构建内核时,创建使用 syslinux 的引导软盘的一种简单方法是使用 zdisk 或 bzdisk make 目标,它们分别使用 zimage 和 bzimage 映像。这两个目标都接受 FDARGS 参数,该参数可用于设置内核命令行。

    例如

    make bzdisk FDARGS="root=/dev/nfs"
    

    请注意,运行此命令的用户需要有权访问软盘驱动器设备 /dev/fd0

    有关 syslinux 的更多信息,包括如何为预构建内核创建引导盘,请参阅 https://syslinux.zytor.com/

    注意

    以前可以使用 dd 直接将内核写入软盘,使用 rdev 配置引导设备,并使用生成的软盘引导。Linux 不再支持这种引导方式。

  • 使用 isolinux 从 CD-ROM 启动

    构建内核时,创建使用 isolinux 的可引导 CD-ROM 的一种简单方法是使用 isoimage 目标,该目标使用 bzimage 映像。与 zdisk 和 bzdisk 类似,此目标接受 FDARGS 参数,该参数可用于设置内核命令行。

    例如

    make isoimage FDARGS="root=/dev/nfs"
    

    生成的 iso 映像将是 arch/<ARCH>/boot/image.iso 这可以使用包括 cdrecord 在内的各种工具写入 CD-ROM。

    例如

    cdrecord dev=ATAPI:1,0,0 arch/x86/boot/image.iso
    

    有关 isolinux 的更多信息,包括如何为预构建内核创建引导盘,请参阅 https://syslinux.zytor.com/

  • 使用 LILO

    使用 LILO 时,可以使用 LILO 配置文件中的“append=”指令指定所有必需的命令行参数。

    但是,要使用“root=”指令,还需要创建一个虚拟的根设备,该设备可以在运行 LILO 后删除。

    例如

    mknod /dev/boot255 c 0 255
    

    有关配置 LILO 的信息,请参阅其文档。

  • 使用 GRUB

    使用 GRUB 时,内核参数只需附加在内核规范之后:kernel <内核> <参数>

  • 使用 loadlin

    loadlin 可用于从 DOS 命令提示符引导 Linux,而无需本地硬盘作为根挂载。本文档的作者没有对此进行彻底的测试,但一般来说,应该可以配置内核命令行,类似于 LILO 的配置。

    有关更多信息,请参阅 loadlin 文档。

  • 使用引导 ROM

    这可能是引导无盘客户端的最优雅方式。使用引导 ROM,可以使用 TFTP 协议加载内核。本文档的作者不知道任何支持通过网络引导 Linux 的商业引导 ROM。但是,有两种免费的引导 ROM 实现,netboot-nfs 和 etherboot,它们都可以在 sunsite.unc.edu 上找到,并且都包含引导无盘 Linux 客户端所需的一切。

  • 使用 pxelinux

    Pxelinux 可以用来使用许多现代网卡上存在的 PXE 引导加载程序来引导 Linux。

    使用 pxelinux 时,内核映像使用“kernel </tftpboot 下的相对路径>”指定。nfsroot 参数通过将它们添加到“append”行传递给内核。通常将串行控制台与 pxeliunx 结合使用,有关更多信息,请参阅 Linux 串行控制台

    有关 isolinux 的更多信息,包括如何为预构建内核创建引导盘,请参阅 https://syslinux.zytor.com/

鸣谢

内核中的 nfsroot 代码和 RARP 支持由 Gero Kuhlmann <gero@gkminix.han.de> 编写。

IP 层自动配置代码的其余部分由 Martin Mares <mj@atrey.karlin.mff.cuni.cz> 编写。

为了编写 nfsroot 的初始版本,我要感谢 Jens-Uwe Mager <jum@anubis.han.de> 的帮助。