远程 Linux 详解

作者:Richard Ferri

远程 Linux 指的是不从本地介质启动 Linux 内核,而是通过网络(通常是以太网)接收启动指令的 Linux 工作站或节点。由于配置 Linux 内核和操作系统本身都很容易,Linux 正在被定制以在许多不同的环境中使用,从 Web 服务到集群计算和 X 服务器。

为什么选择远程 Linux?

您可能会问的第一个问题是,为什么要远程启动 Linux?毕竟,本地安装 Linux 只需要放入 CD,回答几个问题,然后去喝杯双份拿铁,等待工作站安装完成即可。这对于典型的单工作站安装来说是正确的;但是,一旦您开始管理和安装大量工作站,尤其是在集群或服务器场环境中,本地介质就变得不太实用了。随着像 RLX Technologies, Inc. 这样的公司推出密集型服务器,远程启动成为一种必然,因为密集型服务器不在节点上提供软盘或 CD-ROM 驱动器。密集型服务器希望通过本地快速以太网连接启动,并进行远程管理。远程 Linux 的主要优势是

  • 集中式、无需人工干预的管理:虽然许多安装都有人在现场可以 24/7 地操作 CD 和软盘,但也有许多无人值守的站点(长时间无人亲自在场的站点)。在这些站点,当程序员远程工作并且需要使用本地介质上的特殊镜像启动节点时,在他或她找到人来加载正确的介质之前,就只能束手无策。

  • 密集型服务器解决方案:由于集群和服务器场的趋势是集中式远程管理,CD 和软盘驱动器变得相当过时。节点上本地介质的存在意味着节点必须采用某种外形尺寸,从而增加节点的最小尺寸。为了实现更高的节点封装密度,CD-ROM 和软盘驱动器正在行业的某些领域逐步淘汰。

  • 多功能性:有时,您可以修复阻止节点从本地介质启动的文件系统问题。例如,您可以在远程启动的机器上对本地硬盘驱动器运行 fsck,以修复文件系统问题。

  • 成本和安全性:为什么要为不需要的介质付费?一些公司正在销售不带硬盘驱动器和其他本地介质的工作站,这些工作站旨在用作安全的终端服务器。在这种意义上,安全意味着如果员工无法访问其工作站上的本地介质,则更难以捕获敏感数据。

  • 有助于消除版本偏差:在所有工作站都从单个内核镜像远程启动的情况下,它消除了为内核补丁或增强功能更新本地介质的问题。您可以更新单个远程内核镜像一次,而不是将更改传播到一组工作站硬盘驱动器,或者更糟糕的是,传播到它们本地的启动软盘。

远程启动过程

远程启动过程模仿本地启动过程,但有一些重要的区别。从逻辑角度来看,在不谈论执行这些任务的服务的情况下,这基本上是网络启动过程中发生的事情

  1. 节点已通电或重置,并设置为从网络启动。

  2. 节点广播其唯一的以太网 MAC 地址,寻找服务器。

  3. 服务器先前已设置为侦听特定的 MAC 地址,并使用节点的正确 IP 地址进行响应。或者,服务器使用指定 IP 地址范围内的 IP 信息响应其物理网络上的任何广播。

  4. 节点接收其 IP 信息并配置其以太网适配器以进行 TCP/IP 通信。

  5. 节点通过其新配置的适配器请求内核。

  6. 服务器通过向客户端发送网络加载程序来响应,该加载程序将加载网络启动内核。

  7. 网络启动加载程序以只读方式挂载根文件系统。

  8. 网络加载程序读取从服务器发送的网络启动内核到本地内存,并将控制权转移给它。

  9. 内核以读/写方式挂载根目录,挂载其他文件系统并启动 init 进程。

  10. Init 为节点启动定制的 Linux 服务,并完全启动。

从这个描述中,我们看到启动节点对服务器有几个依赖项:网络启动内核、根文件系统以及将内核和 IP 信息从服务器传输到节点的方法。

基础知识

为了使节点能够正确地远程启动,服务器和客户端节点必须以几种明确定义的方式进行协作。设置节点进行远程启动有几个基本要求

  • 配备完善的服务器:服务器必须运行适当的服务(我们稍后会讨论这些服务),这些服务可以提供远程启动节点所需的信息。

  • 远程电源控制方法:要启动节点的启动序列,您必须能够启动或重置节点。您实际上不能依赖节点上的操作系统此时存在——毕竟,有时您需要重置节点是因为操作系统崩溃了。

  • 网络:所有节点都必须具有到服务器的路由,直接路由或通过网关的间接路由。我们这里只讨论以太网网络。

  • 可网络启动的 Linux 内核:内核可以是压缩的或未压缩的,标记的或未标记的。本文稍后讨论的标记内核由 Etherboot 解决方案使用。另请参阅“资源”部分中的 Etherboot 网站以获取更多信息。

  • 网络加载程序:一种从服务器读取网络启动内核并将其正确放置在节点内存中的方法。

  • 文件系统:在过去,文件系统是通过 NFS 在网络上提供的。使用像 SYSLINUX 这样的解决方案,您实际上可以通过 RAM 磁盘提供整个文件系统,并通过网络与内核一起发送。

现在我们对远程启动过程的流程以及客户端对服务器的一般要求有了基本的了解,让我们从实际角度讨论提供所有这些服务的选项。

远程电源控制

远程电源控制是可用远程硬件功能的一个小子集。各种制造商在其产品中提供专门的硬件和软件,这些硬件和软件提供强大的远程硬件控制功能,例如监控温度、风扇、电源、电源控制、BIOS 更新、警报等等。为了远程启动节点,我们真正需要的唯一远程硬件控制功能是开机和关机能力,尽管拥有重置功能也很方便。

要强制网络启动,可能必须修改工作站上的启动顺序。通常,启动顺序类似于软盘、CD-ROM,然后是硬盘驱动器。最常见的情况是,通过网络启动根本不在启动列表中,或者在列表的最底部,在最后一个本地介质之后。由于大多数工作站都预装了某些可行的操作系统,因此节点的重置或开机将从其本地硬盘驱动器启动它。

以太网

要进行真正的网络启动,您必须拥有一个符合 PXE 标准的以太网适配器。PXE 是预启动执行环境,是英特尔有线管理 (WfM) 计划的一部分。符合 PXE 标准意味着以太网适配器能够在内核本身启动之前从服务器加载和执行网络加载程序。节点上的 BIOS 和以太网适配器上的固件都必须协作以支持 PXE 启动。符合 PXE 标准的系统能够广播适配器 MAC 地址,接收来自服务器的响应,配置适配器以进行 TCP/IP,通过网络接收网络加载程序并将控制权转移给它。

软盘

虽然这是一篇关于远程 Linux 的文章,而软盘是本地介质,但有一种混合的远程启动非常重要,必须提及。由于许多以太网适配器/节点 BIOS 组合不符合 PXE 标准,因此出现了一个开源解决方案:Etherboot。Etherboot 提供了一种创建启动软盘的方法,该软盘包含一个简单的加载程序和一个以太网设备驱动程序。将启动列表设置为磁盘,当客户端启动时,Etherboot 软盘接管将驱动程序加载到内存中并广播 MAC 地址,寻找服务器。在 PXE 情况下,服务器被设置为响应网络启动加载程序;在 Etherboot 情况下,服务器必须使用标记的网络启动内核进行响应。通过对内核运行 mknbi 命令来标记内核。(有关 mknbi 的更多信息,请参阅 etherboot.sourceforge.net/doc/html/mknbi.html。)网络启动节点的目的是将内核加载到本地内存中。无论您选择 PXE 方案还是 Etherboot 方案,网络启动路径都会迅速合并——内核在内存中,控制权已传递给它。

我的 IP 信息是什么?(RARP、BOOTP 和 DHCP)

当客户端通过网络启动时,无论是使用 PXE 还是从软盘启动,它都会通过 LAN 广播其 MAC 地址,寻找设置为提供客户端 IP 信息的服务器。这是为了让客户端可以使用正确的 IP 信息配置其以太网适配器,并使用 TCP/IP 继续其余的启动对话。有几种方法可以向广播节点提供 IP 信息:RARP、BOOTP 和 DHCP。

RARP

RARP(反向地址解析协议)是将适配器唯一的 48 位以太网地址(其 MAC)与 IP 地址关联的方法。当客户端尝试远程启动时,它会将其 MAC 地址广播到物理网络上的所有工作站。一个或多个工作站将运行 RARPD 守护程序,该守护程序读取 /etc/ethers 以建立 48 位以太网地址和 IP 地址之间的关联,并使用其全新的 IP 地址响应广播客户端。接收到 IP 地址后,客户端应启动 TFTP(简单文件传输协议)请求以获取其镜像(稍后详细介绍)。RARP 的最大缺点是它仅在本地物理网络上工作(不重新广播),并且仅提供少量信息,即客户端的 IP 地址。

BOOTP

BOOTP(引导程序协议)是对 RARP 的明显改进,因为它提供网关支持(通过路由器启动)并向启动客户端提供更多信息。除了客户端的 IP 地址外,BOOTP 还提供网关(路由器)的地址、服务器的地址、子网掩码和启动文件(客户端的可启动镜像)。请注意,一个特定的硬件地址只能分配一个 IP 地址。

BOOTP 的最大缺点是它以一对一的关系将 IP 地址分配给 MAC 地址——特定的 MAC 地址始终会被分配相同的 IP 地址。如果您考虑移动办公室和旅行笔记本电脑提出的要求,这种一对一的关系被证明有些局限性。在移动办公室场景中,用户带着笔记本电脑旅行,只需要偶尔登录中央服务器,以接收邮件或其他内容。其余时间,他们的 IP 地址仍然未分配,这对 IP 地址来说是一种可怕的浪费。DHCP 很好地解决了 IP 地址未充分利用的问题。

DHCP

DHCP(动态主机配置协议)是 BOOTP 的逻辑继承者。事实上,BOOTP 被认为有些过时,并且在很大程度上已被 DHCP 取代。DHCP 超越 BOOTP 受欢迎的一个原因是 DHCP 支持动态地址范围分配,而 BOOTP 仅支持静态 IP 分配(单个 MAC 始终分配相同的 IP 地址)。DHCP 的动态 IP 分配功能允许在许多节点之间重用 IP 地址。在移动办公室场景中,节点连接到其网络并广播其 MAC。服务器运行 dhcpd 守护程序,为移动节点分配了一系列 IP 地址,只需将范围内的下一个 IP 地址分配给广播节点即可。DHCP 还通过 DHCP 租约文件管理 IP 地址分配的寿命。

DHCP 的选项非常多,超出了本文的范围。如需进一步研究,请查阅 Ralph Droms 和 Ted Lemon 合著的 The DHCP Handbook(Pearson Higher Education,1999 年)。

传输内核和网络加载程序

在获取其 IP 信息并配置适配器以进行 TCP/IP 后,节点 BIOS 通常会通过网络请求镜像。IP 分配和镜像服务之间的这种清晰划分是故意的;它允许 IP 分配和镜像服务可能由不同的机器提供。TFTP(简单文件传输协议)是将镜像从服务器传输到客户端的正确工具,因为 TFTP 与其重量级同类 FTP(文件传输协议)不同,不需要用户登录即可获取文件。TFTP 内置的原始安全性是,默认情况下,TFTP 仅允许从服务器的 /tftpboot 目录传输文件。由于这种安全方案在系统管理员中广为人知,因此只有公共文件才会放入 /tftpboot 中。在最新版本的 tftp-hpa 中,也添加了文件访问安全性。

请注意,我们一直在谈论传输镜像——这是因为镜像可以是标记的内核 (Etherboot) 或网络加载程序 (PXE)。如果您使用 Etherboot,即软盘启动方法,则 BOOTP 或 DHCP 应指向标记的内核。如果您使用真正的 PXE,则 BOOTP 或 DHCP 应指向网络加载程序。在 PXE 情况下,网络加载程序被加载到内存中,然后通过 TFTP 启动未标记的内核。要使用 PXE,TFTP 服务器必须支持 “tsize” TFTP 选项(RFC 1784、RFC 2349)。H. Peter Anvin 的 tftp-hpa 支持此选项,可以从 www.kernel.org/pub/software/network/tftp 获取。

单内核

无论您使用两步 PXE 启动过程(网络加载程序和内核)还是一步 Etherboot 过程(仅内核),最终内核都会被读取到客户端的内存中,并将控制权转移给它。您可能想知道,网络启动内核和为从本地硬盘驱动器启动而构建的典型内核之间有什么区别?您必须做出的第一个决定是内核是模块化的还是单内核的——意味着没有可加载的模块。如果您曾经构建过 Linux 内核,您就会意识到功能要么选择 “Y”(包含该功能)、“N”(不包含该功能)或 “M”(按需加载)。如果您的内核是单内核的,则不能有任何 M 功能。

内核标志

必须为单内核网络启动内核启用几个标志。首先,如果您要创建单内核,则需要关闭模块支持。在 .config 文件中,您将看到

#CONFIG_MODULES is not set

如果您正在执行单内核,则应将其关闭,如下所示

CONFIG_MODULES=n
如果您打算在客户端上创建 ext2 文件系统或从服务器挂载它们,如在 NFS 根文件系统的情况下,则必须支持 ext2 文件系统
CONFIG_EXT2_FS=y
如果您打算使用通过 NFS 挂载的远程根文件系统,则需要 NFS 选项
CONFIG_NFS_FS=y
CONFIG_ROOT_FS=y
由于您将使用以太网启动远程客户端,因此您必须启用网络配置,并且至少要支持客户端上的特定网络接口卡 (NIC)
CONFIG_NETDEVICES=y
CONFIG_EEXPRESS_PRO100=y
最后,您必须配置通过 RARP、BOOTP 或 DHCP 获取 IP 地址的功能
CONFIG_IP_PNP_RARP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_DHCP=y
如果您通过 RAM 磁盘而不是通过 NFS(请参阅下一节)提供根文件系统,则必须指定 RAM 文件系统选项
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
模块化内核

在模块化内核中,您可以选择使用 M 来选择要由内核按需加载的模块。由于模块不是静态绑定在内核中的,因此必须有一个位置来加载模块,以便在需要时加载。Linux 提供的加载内核模块的位置是 RAM 磁盘。此 RAM 磁盘仅在启动过程中使用,并且仅用于提供内核模块。RAM 磁盘的另一个用途是提供远程根文件系统,这超出了本文的范围。

为了演示模块化内核的使用,我们可以使对 MINIX 文件系统的支持模块化,以支持将从软盘加载的 MINIX 根文件系统。要创建模块化内核,首先要做的是启用模块化支持并重建内核

CONFIG_MODULES=y

在我们的示例中,我们将通过动态模块提供 MINIX 支持,因此我们将该选项设置为 M

CONFIG_MINIX_FS=M
在重建模块化内核并将其 (bzImage) 复制到 /tftpboot 后,我们将需要一种加载它的方法。像开源 SYSLINUX 包这样的工具提供了加载模块化内核并提供 RAM 磁盘的方法。一个示例 default pxelinux.cfg 文件可能如下所示
DEFAULT bzImage
APPEND vga=extended initrd=minix.gz root=/dev/fd0 ro
PROMPT 1
TIMEOUT 50
配置文件表明内核的名称为 bzImage,RAM 磁盘名称为 minix.gz,客户端根目录将从软盘 (/dev/fd0) 加载。

我们将必须创建一个 RAM 磁盘,其中包含 MINIX 模块 (minix.o),以及 insmod(加载 MINIX 模块的命令)、控制台设备 (/dev/console) 和 linuxrc,即在调用 RAM 磁盘时调用的命令。(有关 RAM 磁盘在 Linux 中如何工作的完整描述,请参阅 Werner Almesberger 和 Hans Lerman 编写并作为内核 RPM 一部分分发的 initrd.txt 文件。)要创建自定义 RAM 磁盘,该磁盘将动态挂载 MINIX 模块化和来自软盘的 MINIX 根文件系统,您必须创建一个文件并使用 dd 将其归零

dd if=/dev/zero of=minixroot bs=1k count=4096

接下来,将文件与环回设备 /dev/loop0 关联

losetup /dev/loop0 minixroot
创建 ext2 文件系统
mkfs.ext2 /dev/loop0
将设备挂载到方便的挂载点,例如 /mnt
mount /dev/loop0 /mnt
创建一些常用的目录
mkdir /mnt/dev /mnt/lib /mnt/sbin
创建控制台设备
mkdev /mnt/dev/console c 5 1
将 minix.o 模块复制到 /lib,并将 sash 和 insmod 复制到 /sbin
cp /usr/src/linux/fs/minix/minix.o /mnt/lib/minix.o
cp /sbin/sash /mnt/sbin/sash
cp /sbin/insmod /mnt/sbin/insmod
找出 insmod 需要哪些库
ldd /sbin/insmod
并将它们复制到 /mnt/lib
cp /lib/libc.so.6 /mnt/lib
cp /lib/ld-linux.so.2 /mnt/lib
然后创建一个加载 minix 模块的 /mnt/linuxrc 文件
#!/sbin/sash
/sbin/insmod /lib/minix.o
使 linuxrc 可执行
chmod 777 linuxrc
卸载 /mnt 并分离环回设备
umount /mnt
losetup -d /dev/loop0
对 minixroot 文件进行 gzip 压缩,您就可以启动客户端了
gzip minixroot
此示例将使您能够让内核尝试从 /dev/fd0 加载其根文件系统。要完全测试该示例,您必须在软盘上创建一个 MINIX 文件系统,挂载它并至少复制 init 和 sh 以及它们需要的库,并创建一个控制台设备。
远程 NFS 根目录

众所周知,没有根文件系统 (/) 的生活毫无意义。在本地启动时,根 FS 几乎总是在本地硬盘驱动器上找到。在网络启动的客户端上,根目录来自哪里?要提供根目录,您有两种选择:从服务器通过 NFS 远程挂载根目录或通过 RAM 磁盘。如果您通过 NFS 提供根目录,默认情况下,您的内核会在 /tftpboot/ip 中查找根目录,其中 ip 是您的客户端的 IP 地址。这需要在服务器上启动 NFS 并导出 /tftpboot(或每个节点的 /tftpboot/ip)。要使客户端节点启动到登录提示符,对根文件系统有几个要求,包括 init 和 shell 二进制文件;设备,至少是控制台设备;以及 init 和 shell 二进制文件可能依赖的任何动态加载的库。

填充远程根文件系统的一种快速而简陋的方法是复制 init、sh、必要的库和控制台设备,如下所示

cp /sbin/init /tftpboot/192.168.64.1/sbin/init
cp /bin/sh /tftpboot/192.168.64.1/bin/sh

要确定 init 的动态加载库,请使用 ldd 命令

ldd /sbin/init
ldd /bin/sh
然后将 ldd 命令列出的库复制到 /tftpboot/ip/lib。要创建设备,有一个方便的 MAKEDEV 命令,它是 MAKEDEV 包的一部分
/dev/MAKEDEV -d /tftpboot/129.168.64.1/dev console
如果您的其他服务在服务器上正确启动并运行,当您强制客户端上的网络启动时,它将从其远程根目录运行 init 脚本,使用其远程根目录中提供的控制台,启动 shell 并提示输入运行级别(因为远程根目录中没有 /etc/inittab 文件)。输入 s 表示单用户模式,就像那样,您的客户端已启动并运行到 shell 提示符。

有一个特殊的 shell 可用,称为 sash(代表独立 shell),在远程环境中非常有用。这是因为 sash 没有动态加载的库,并提供了一些操作文件系统(mount、umount、sync)、更改文件权限(chmod、chgrp、chown)和存档(ar、tar)的标准内置命令,以及其他功能。例如,您可以将 /sbin/sash 复制到 /tftpboot/ip/sbin/sash,而不是启动 sh,内核将启动独立 shell。您可能还想提供自己的基本 inittab 文件以在启动时运行 sash,如下所示

id:1:initdefault:
1:1:respawn:/sbin/sash
结论

在本文中,我们探讨了一些用于远程启动 Linux 的服务和方法。远程 Linux 是继续研究的非常肥沃的土壤。随着网络变得更快,可以支持更多数量的远程客户端,并且随着集群变得更大,并且对集中式管理的依赖性更大,远程 Linux 技术将在行业中发挥更大的作用。随着密集型服务器技术的出现,远程 Linux 不仅仅是一种便利,而是一种必然。

致谢

我衷心感谢 Wesleyan 的 Vasilios Hoffman 的研究。“V”,他喜欢这样称呼自己,他演示了在创建 RAM 磁盘中环回设备的使用以及如何正确创建模块化网络可启动内核。V 简直是 Linux 信息的宝库。

资源

Remote Linux Explained
电子邮件:rcferri@us.ibm.com

Richard Ferri 是 IBM Linux 技术中心的高级程序员,他在那里从事开源 Linux 集群项目,例如 LUI (oss.software.ibm.com/lui) 和 OSCAR (www.openclustergroup.org)。他拥有乔治城大学的英语文学学士学位,现在与他的妻子 Pat、三个十几岁的儿子和三只血统可疑的狗住在纽约州北部。

加载 Disqus 评论