Diskless system (简体中文)
引用自 Gentoo Wiki:无盘节点
- 一台无盘机器是一台没有任何诸如硬盘、软盘驱动器或CD-ROM等常见引导设备的PC。无盘节点引导自网络,并需要一台服务器来提供当作本地硬盘来使用的存储空间。
服务端配置
首先我们应当安装如下组件:
- 用于向无盘节点分配IP地址的 DHCP 服务端。
- 用于分发启动镜像的 TFTP 服务端 (所有PXE镜像必需)。
- 选择 (NFS 或 NBD) 中的一种作为存放和传输无盘节点的 Arch 安装副本的网络存储服务。
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)。
# 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 安装
安装 devtools 和 arch-install-scripts, 然后运行 pacstrap
以为无盘系统 安装必须的软件包:
# pacstrap -d "$root" base linux linux-firmware mkinitcpio-nfs-utils 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
之后加入 nbd
; net
将负责配置网络, 但只要不在 kernel 行中指定,它不会尝试 NFS 挂载。
配置无盘系统
在上述步骤完成后,你仍需要时情况完成主机名,时区,区域设置,键盘布局等其他 Installation guide (简体中文) 提及的配置步骤。
启动器
GRUB
尽管没有详细文档, 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
PXELINUX 由 syslinux 提供,详见 PXELINUX。
额外的挂载点
NBD 根
late boot 时你需要将根分区的文件系统切换为可读写(rw
)并且启动 compress=lzo
以获得相较于 NFS 可观的性能提升。
# vim "$root/etc/fstab"
/dev/nbd0 / btrfs rw,noatime,compress=lzo 0 0
程序状态目录
你可以将 /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
当使用 NBD 作为网络存储服务时,你需要无盘系统启动前确保卸载(umount
)安装副本所在的块设备。
这一特性使得内核更新的过程十分有趣:当客户机开机时你不能挂载它所使用的文件系统, 这意味着你需要用一个单独的内核来执行内核更新。
首先从客户端安装副本复制 $root/boot
到你的 tftp 根目录 (通常即 /srv/boot
).
# cp -r "$root/boot" /srv/boot
然后在客户机启动前卸载 $root
。
# umount "$root"