无盘系统

出自 ArchWiki

出自 Wikipedia:Diskless node

无盘节点(或无盘工作站)是不带磁盘驱动器的工作站或个人电脑,它采用网络启动从服务器加载其操作系统。

服务器配置

首先,我们必须安装以下组件

  • 一个 DHCP 服务器,用于为我们的无盘节点分配 IP 地址。
  • 一个 TFTP 服务器,用于传输启动镜像(所有 PXE 选项 ROM 的要求)。
  • 一种网络存储(NFSSamba 或 NBD),用于将 Arch 安装导出到无盘节点。
注意
  • dnsmasq 能够同时充当 DHCP 和 TFTP 服务器。更多信息,参见 dnsmasq 条目。
  • 您也可以完全不使用 PXE 启动 Arch Linux。参见下面的 SKUF 项。

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 服务器的地址;其他所有内容都应更改以匹配您的网络

RFC:4578 定义了 “客户端系统架构类型” dhcp 选项。在上面的配置中,如果 PXE 客户端请求 x86_64-efi 二进制文件(类型 0x7),我们会适当地提供一个,否则回退到旧版二进制文件。这允许 UEFI 和旧版 BIOS 客户端在同一网段上同时启动。

启动 ISC DHCP systemd 服务。

TFTP

TFTP 服务器将用于将引导加载程序、内核和 initramfs 传输到客户端。

将 TFTP 根目录设置为 /srv/arch/boot。有关安装和配置,请参见 TFTP

网络存储

使用 NFS 和 NBD 的主要区别在于,虽然两者都可以允许多个客户端使用相同的安装,但使用 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 服务:nfs-idmapd nfs-mountd

NBD

安装 nbd 并进行配置。

/etc/nbd-server/config
[generic]
    user = nbd
    group = nbd
[arch]
    exportname = /srv/arch.img
    copyonwrite = false
注意: 如果您希望多个客户端同时使用同一个 NBD 共享,请将 copyonwrite 设置为 true;有关更多详细信息,请参阅 nbd-server(5)。 另请使用 chown 将 exportname 目录的所有权更改为用户 nbd

启动 nbd systemd 服务。

SKUF

您可以使用 SKUF 网络启动系统 项目启动 Arch Linux,其中文件系统的根目录将是位于 Samba 服务器上的 稀疏文件

要开始使用,请安装 samba 并创建一个配置文件

/etc/samba/smb.conf
[global]
	workgroup = WORKGROUP
	security = user

[arch]
	path = /srv/samba
	valid users = @skuf
	write list = @skuf
	guest ok = no
	read only = no
	writeable = yes
	browseable = yes
注意: 您的所有稀疏镜像都将位于指定的目录中(在本例中为 /srv/samba)。

启动 smb systemd 服务

然后,创建一个 skuf 组和将成为其成员的用户,客户端机器上的 SAMBA 挂载将通过他们进行。

# groupadd skuf
# useradd test -g skuf
# smbpasswd -a test

客户端安装

接下来,我们将在服务器上的子目录中创建一个完整的 Arch Linux 安装。在启动期间,无盘客户端将从 DHCP 服务器获取 IP 地址,然后使用 PXE 从主机启动并将此安装挂载为其根目录。

目录设置

注意: 创建单独的文件系统对于 NBD 是必需的,但对于 NFS 是可选的,并且可以跳过/忽略。

创建一个至少 2 GiB 的 稀疏文件,并在其上创建一个 btrfs 文件系统(当然,如果需要,您也可以使用真实的块设备或 LVM)。

# truncate -s 2G /srv/arch.img
# mkfs.btrfs /srv/arch.img
# export root=/srv/arch
# mount --mkdir -o loop,compress=lzo /srv/arch.img "$root"

引导安装

安装 devtoolsarch-install-scripts,并运行 pacstrap 来为客户端安装 基本软件包

# pacstrap -K "$root" base linux linux-firmware mkinitcpio-nfs-utils nfs-utils
注意: 在所有情况下,仍然需要 mkinitcpio-nfs-utils。早期启动中使用的 ipconfig 仅由后者提供。

现在需要构建 initramfs。

NFS

为了使 NFSv4 挂载工作(nfsmount 不支持,nfsmountnet 钩子的默认设置),需要对 net 钩子进行微小的修改。

# 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 时,它不会被覆盖。

编辑 $root/etc/mkinitcpio.conf 并将 nfsv4 添加到 MODULES,将 netnfs4 添加到 HOOKS,并将 /usr/bin/mount.nfs4 添加到 BINARIES

接下来,我们 chroot 进入我们的安装并运行 mkinitcpio

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

NBD

需要在客户端上安装 mkinitcpio-nbdAUR 软件包。使用 makepkg 构建并安装它

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

然后,您需要将 nbd 附加到 net 之后的 HOOKS 数组中;net 将为您配置网络,但如果内核行中未指定 nfsroot,则不会尝试 NFS 挂载。

SKUF

要在使用 SKUF 网络启动系统稀疏文件 上安装 Arch Linux,请克隆 git 存储库

$ git clone https://github.com/BiteDasher/skuf.git
$ cd skuf
$ ./switch-tag latest

然后,构建 skuf 软件包和 ISO 镜像,该镜像稍后将用作“kickstart”以使用 kexec 启动主系统

首先,您需要调整 SAMBA 密码的加密方法(有关更多详细信息,请参见 [1]

tune.crypt
A B
X Y
I O
tune.password
1234 Test password!

设置 defaults

defaults
SAMBA_USERNAME="testuser"
SAMBA_PASSWORD="pa33w0rd"
SAMBA_ADDRESS="192.168.0.5"
SAMBA_PORT="445"
SAMBA_VERSION="3.0"
...

安装所需的软件包

# ./install_deps.sh

最后,构建 skuf 软件包

$ ./tune_crypt.sh
$ ./tune_password.sh
$ ./setup_defaults.sh
$ ./build_rootfs_tar.sh
$ ./build_package.sh

ISO 镜像

# ./setup_repo.sh
# ./build_iso.sh

和带有 Arch Linux 的 稀疏文件

# ./create_image.sh -s SIZE_IN_GIGABYTES additional_packages

然后,将 arch.ext4 移动到 /srv/samba 中。

客户端配置

除了这里提到的设置外,您还应该设置您的 hostnametimezonelocalekeymap,并遵循 安装指南 的任何其他相关部分。

引导加载程序

GRUB

本文或本节可能需要与 GRUB 合并。

注意: (在 Talk:Diskless system 中讨论)

尽管文档记录不佳,但 GRUB 支持通过 PXE 加载。

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

使用 grub-mknetdir 在目标安装上为两种架构创建 grub 前缀。

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

幸运的是,grub-mknetdir 为所有当前编译/安装的目标创建前缀,并且 grub 维护者非常友好地在同一个软件包中为我们提供了这两个,因此 grub-mknetdir 只需要运行一次。

注意: 此示例配置假定 NFS/NBD 服务器的 IP 为 10.0.0.1

现在我们创建一个简单的 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
}

menuentry "Arch Linux (NBD)" {
    linux /vmlinuz-linux quiet add_efi_memmap ip=:::::eth0:dhcp nbd_host=10.0.0.1 nbd_name=arch root=/dev/nbd0
    initrd /initramfs-linux.img
}

GRUB 将自动 set root=(tftp,10.0.0.1),以便内核和 initramfs 通过 TFTP 传输,而无需任何额外配置,但是如果您有任何其他非 tftp 菜单项,您可能需要显式设置它。

注意
  • 所有 GRUB 文件和 initcpio 文件都必须通过 TFTP 可用。 例如,对于 TFTP 根目录设置为 /srv/tftp 的 NBD 安装,必须存在 /srv/tftp/grub/x86_64-efi/core.efi/srv/tftp/vmlinuz-linux 才能成功启动。 您可以将镜像内的所有 /boot 文件复制到 TFTP 服务器的根目录。
  • 您可以通过 grub-mkconfig 生成 grub 配置以确保视频设置正确。 但是,之后需要编辑 boot.cfg,以删除 search --no-floppy ... 并确保 linux initrd 选项(路径、NBD 设置、NFS 设置)设置正确。
  • 根据需要修改您的内核行,有关 NBD 相关选项,请参阅 PXELINUX

PXELINUX

PXELINUX 由 syslinux 提供,详情参见 PXELINUX

额外的挂载点

NBD 根目录

在启动后期,您可能希望将根文件系统挂载切换为 rw,并启用 compress=lzo,以便与 NFS 相比,磁盘性能得到很大提高。

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

程序状态目录

本文或本节的事实准确性存在争议。

原因: 当 /var/log/journal 位于 tmpfs 中和/或不存在时,systemd 默认不使用持久日志记录(在 Talk:Diskless system 中讨论)

您可以将 /var/log(例如)挂载为 tmpfs,以便来自多个主机的日志不会不可预测地混合在一起,并对 /var/spool/cups 执行相同的操作,这样使用相同后台处理程序的 20 个 cups 实例就不会互相冲突,生成 1,498 个打印作业,并在一夜之间吃掉整整一令纸(或更糟:墨粉盒)。

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

最好将某些具有某种状态/数据库的软件配置为对每个主机使用唯一的状态/数据库存储目录。 例如,如果您想运行 puppet,您可以简单地在 puppet 单元文件中使用 %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

如果 vardirssldir 不存在,Puppet-agent 会创建它们。

如果这些方法都不合适,那么最后一个理智的选择是创建一个 systemd.generator(7),它创建一个特定于当前主机的挂载单元(不幸的是,挂载单元中不允许使用说明符)。

客户端启动

NBD

本文或本节的事实准确性存在争议。

原因: 当在服务器上使用 COW 时,客户端实际上都对原始文件系统进行了只读挂载;理论上,在 NBD 服务器上进行读写挂载应该是安全的(在 Talk:Diskless system 中讨论)

如果您正在使用 NBD,您将需要在启动客户端之前/期间卸载 arch.img

当涉及到内核更新时,这会使事情变得特别有趣。 当您启动客户端时,您不能挂载客户端文件系统,但这也意味着您需要使用与客户端文件系统分开的内核来构建它。

您将需要首先将客户端安装中的 $root/boot 复制到您的 tftp 根目录(即 /srv/boot)。

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

然后,您需要在启动客户端之前卸载 $root

# umount "$root"
注意: 要在此设置中更新内核,您需要先在客户端上的 fstab 中使用 NFS 挂载 /srv/boot(在执行内核更新之前),或者在客户端断开与 NBD 的连接后挂载客户端文件系统

SKUF

skuflinux-smth.iso 写入您的 USB 驱动器,将其插入客户端计算机并在 UEFI/BIOS 设置中选择作为启动设备。

注意: 如果客户端计算机具有 UEFI,您可以将 SKUF 安装在 ESP 分区上,这样您就不必使用 USB 闪存驱动器/CD/DVD。 为此,请将 skuflinux-smth.iso 挂载到某个位置(如 /mnt),然后将 /mnt/skuf/boot/x86_64/{vmlinuz-linux,initramfs-linux.img} 复制到 ESP 分区,并执行 efibootmgr -c -d /dev/sdX -p Y -u 'initrd=\initramfs-linux.img' -l '\vmlinuz-linux' -L 'SKUF',其中 /dev/sdX 是目标磁盘,Y 是目标 ESP 分区号。

参见