Diskless system (简体中文)

From ArchWiki
翻译状态:本文是 Diskless system翻译。上次翻译日期:2020-05-13。如果英文版本有所更改,则您可以帮助同步翻译。

引用自 Gentoo Wiki:无盘节点

一台无盘机器是一台没有任何诸如硬盘、软盘驱动器或CD-ROM等常见引导设备的PC。无盘节点引导自网络,并需要一台服务器来提供当作本地硬盘来使用的存储空间。

服务端配置

首先我们应当安装如下组件:

  • 用于向无盘节点分配IP地址的 DHCP 服务端。
  • 用于分发启动镜像的 TFTP 服务端 (所有PXE镜像必需)。
  • 选择 (NFS 或 NBD) 中的一种作为存放和传输无盘节点的 Arch 安装副本的网络存储服务。
注意: dnsmasq 能够同时兼任 DHCP 和 TFTP 服务器。更多信息请见 Dnsmasq (简体中文)

DHCP

安装并配置 ISC dhcp:

/etc/dhcpd.conf
allow booting;
allow bootp;

authoritative;

option domain-name-servers 10.0.0.1;

option architecture code 93 = unsigned integer 16;

group {
    next-server 10.0.0.1;

    if option architecture = 00:07 {
        filename "/grub/x86_64-efi/core.efi";
    } else {
        filename "/grub/i386-pc/core.0";
    }

    subnet 10.0.0.0 netmask 255.255.255.0 {
        option routers 10.0.0.1;
        range 10.0.0.128 10.0.0.254;
    }
}
注意: next-server 应为 TFTP 服务端监听的IP地址; 你需要酌情更改配置中的地址以匹配你已有的网络环境。

RFC 4578 定义了"客户机架构类型(Client System Architecture Type)" 的 dhcp 参数。在如上配置中,如果 PXE 客户机(暨无盘系统)请求了 x86_64-efi 镜像 (类型 0x7) 服务端将返回对应的文件, 否则自动回落到 legacy 镜像。这样,同一网络中的 UEFI 和 legacy BIOS 均能正常启动。

然后启动 ISC DHCP systemd (简体中文) 服务。

TFTP

TFTP 用于向无盘系统传输 启动器、内核以及 initramfs。

将 TFTP 根目录设置为 /srv/arch/boot。参阅 Tftpd server 配置安装并配置。

网络存储

NFS 与 NBD 的主要区别是,尽管两者均允许你为多个无盘系统使用同一份安装完毕的 Arch Linux,在使用 NBD 时 (由于其直接与文件系统交互的本质) 你将必需使用 CopyOnWrite 的模式, 并将导致在无盘系统断开连接时丢弃所有改动。然而在一些场景中,这是一项不可多得的优势。

NFS

在服务端安装 nfs-utils

你需要将 Arch 安装副本的根目录加入 NFS (简体中文) 的共享(“导出”)列表:

/etc/exports
/srv       *(rw,fsid=0,no_root_squash,no_subtree_check)
/srv/arch  *(rw,no_root_squash,no_subtree_check)

然后启动 NFS 服务: rpc-idmapd rpc-mountd.

NBD

安装并配置 nbd

/etc/nbd-server/config
[generic]
    user = nbd
    group = nbd
[arch]
    exportname = /srv/arch.img
    copyonwrite = false
注意:
  • 如果你需要多台无盘系统同时启动改镜像,请将 copyonwrite 设为 true;详情请参阅 nbd-server(5)
  • 可能需要使用 chown 将 exportname 目录的所有权赋予 nbd 用户。

启动 nbd systemd 服务。

无盘系统配置

接下来我们将在服务器端的子目录中创建一个完整的 Arch Linux 安装副本。启动无盘机时,其将从 DHCP 服务器获取一个 IP 地址,而后通过 PXE 启动并挂载这份安装副本作为根目录。

安装目录创建

创建一个至少 1GB 的 sparse file 并格式化为 btrfs。 (你当然也可以使用其他块设备如实体硬盘或 LVM)。

注意: 对于 NBD,创建一个单独的文件系统是必须的;但对于 NFS 这是可选的,故可酌情忽略或跳过。
# truncate -s 1G /srv/arch.img
# mkfs.btrfs /srv/arch.img
# export root=/srv/arch
# mkdir -p "$root"
# mount -o loop,compress=lzo /srv/arch.img "$root"

Bootstrap 安装

安装 devtoolsarch-install-scripts, 然后运行 pacstrap 以为无盘系统 安装必须的软件包:

# pacstrap -d "$root" base linux linux-firmware mkinitcpio-nfs-utils nfs-utils
注意: 在任何配置中 mkinitcpio-nfs-utils 都必须安装:它将提供早期启动过程中所需的 ipconfig

现在应当生成好 initramfs。

NFS

要使 NFSv4 挂载正常工作,需要轻微改动 net hook (这不被默认的net hook:nfsmount 所支持)。

# sed s/nfsmount/mount.nfs4/ "$root/usr/lib/initcpio/hooks/net" > "$root/usr/lib/initcpio/hooks/netnfs4"
# cp $root/usr/lib/initcpio/install/net{,nfs4}

此时需要备份 net 以防止其在 mkinitcpio-nfs-utils 升级时被覆盖.

Edit $root/etc/mkinitcpio.conf and add nfsv4 to MODULES, netnfs4 to HOOKS, and /usr/bin/mount.nfs4 to BINARIES.

然后 chroot 到安装副本的根目录并执行 mkinitcpio:

# arch-chroot "$root" mkinitcpio -p linux

NBD

在无盘系统的 Arch 安装副本中安装 mkinitcpio-nbdAUR。使用 makepkg (简体中文) 构建并安装它:

# pacman --root "$root" --dbpath "$root/var/lib/pacman" -U mkinitcpio-nbd-0.4-1-any.pkg.tar.xz

然后你需要将 HOOKS array 中 net 之后加入 nbdnet 将负责配置网络, 但只要不在 kernel 行中指定,它不会尝试 NFS 挂载。

配置无盘系统

在上述步骤完成后,你仍需要时情况完成主机名,时区,区域设置,键盘布局等其他 Installation guide (简体中文) 提及的配置步骤。

启动器

GRUB

Merge-arrows-2.pngThis article or section is a candidate for merging with GRUB.Merge-arrows-2.png

尽管没有详细文档, GRUB 支持从 PXE 加载:

# pacman --root "$root" --dbpath "$root/var/lib/pacman" -S grub

使用 grub-mknetdir 在目标系统(无盘系统的 Arch 安装副本)中创建一个 grub prefix:

# arch-chroot "$root" grub-mknetdir --net-directory=/boot --subdir=grub

幸运的是,grub-mknetdir 为所有已编译/安装的目标创建 prefix, 且 grub 的维护者在同一包中提供了两种架构, 所以 grub-mknetdir 仅需执行一次。

现在我们创建一个 GRUB 配置:

# vim "$root/boot/grub/grub.cfg"
menuentry "Arch Linux" {
    linux /vmlinuz-linux quiet add_efi_memmap ip=:::::eth0:dhcp nfsroot=10.0.0.1:/arch
    initrd /initramfs-linux.img
}

GRUB 黑魔法将会自动设置 set root=(tftp,10.0.0.1),这样内核和 initramfs 将自动通过 TFTP 传输过来,不过当你有其他非 TFTP 的启动项时,你仍希望显式声明这些配置。

注意: 根据需要依照PXELINUX修改你的于NBD相关的内核行配置。

PXELINUX

PXELINUX 由 syslinux 提供,详见 PXELINUX

额外的挂载点

NBD 根

late boot 时你需要将根分区的文件系统切换为可读写(rw)并且启动 compress=lzo 以获得相较于 NFS 可观的性能提升。

# vim "$root/etc/fstab"
/dev/nbd0  /  btrfs  rw,noatime,compress=lzo  0 0

程序状态目录

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: 当 /var/log/journal 为 tmpfs 或不存在时,systemd 默认不会进行持久日志记录。 (Discuss in Talk:Diskless system (简体中文))

你可以将 /var/log 挂载为例如 tmpfs 的文件系统,这样多台主机的日志将不会意外混杂在一起。对于 /var/spool/cups 亦可实行此操作,这样 20 个使用相同 spool 的 CUPS 不会互相打架然后执行进行 1498 份打印工作并在一夜之间吃掉整摞纸(或更糟:墨盒)。

# vim "$root/etc/fstab"
tmpfs   /var/log        tmpfs     nodev,nosuid    0 0
tmpfs   /var/spool/cups tmpfs     nodev,nosuid    0 0

对于有某种唯一状态或数据库的软件,最好的配置是为每台无盘主机配置唯一的储存目录。例,如果你想要运行 puppet 你可以简单地在 puppet 的 systemd unit file 中使用 %H 标识符:

# vim "$root/etc/systemd/system/puppetagent.service"
[Unit]
Description=Puppet agent
Wants=basic.target
After=basic.target network.target

[Service]
Type=forking
PIDFile=/run/puppet/agent.pid
ExecStartPre=/usr/bin/install -d -o puppet -m 755 /run/puppet
ExecStart=/usr/bin/puppet agent --vardir=/var/lib/puppet-%H --ssldir=/etc/puppet/ssl-%H

[Install]
WantedBy=multi-user.target

Puppet-agent 将会在 vardir 或 ssldir 不存在时自动创建之。

如果上述方法都不适用,你还可以选择使用 systemd generator 来针对当前主机创建一个 mount unit,不幸的是 %H 标识符无法使用。

无盘机启动

NBD

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: 在服务端启动了CopyOnWrite特性时,所有无盘系统应当均有效地只读挂载了根分区所在的文件系统,所以理论上在NBD服务器上读写挂载是安全的。 (Discuss in Talk:Diskless system (简体中文))

当使用 NBD 作为网络存储服务时,你需要无盘系统启动前确保卸载(umount)安装副本所在的块设备。

这一特性使得内核更新的过程十分有趣:当客户机开机时你不能挂载它所使用的文件系统, 这意味着你需要用一个单独的内核来执行内核更新。

首先从客户端安装副本复制 $root/boot 到你的 tftp 根目录 (通常即 /srv/boot).

# cp -r "$root/boot" /srv/boot

然后在客户机启动前卸载 $root

# umount "$root"
注意: 如上配置中如需升级内核,你需要在开始内核更新前于无盘机中使用 NFS (简体中文)fstab 中挂载 /srv/boot,或是在客户机于NBD断开后手动挂载客户机文件系统。

参阅