Diskless system (简体中文) - ArchWiki

Jump to content

# Diskless system (简体中文)

From ArchWiki

相关文章

- NFS
- NFS Troubleshooting
- PXE
- Mkinitcpio#Using_net
- iSCSI Boot

翻译状态：本文是 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 安装

安装 devtools 和 arch-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` 之后加入 `nbd`； `net` 将负责配置网络, 但只要不在 kernel 行中指定，它不会尝试 NFS 挂载。

## 配置无盘系统

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

### 启动器

#### GRUB

This article or section is a candidate for merging with GRUB.

Notes: (Discuss in Talk:Diskless system (简体中文))

尽管没有详细文档, 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

#### 程序状态目录

The factual accuracy of this article or section is disputed.

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

The factual accuracy of this article or section is disputed.

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断开后手动挂载客户机文件系统。

## 参阅

- kernel.org: Mounting the root filesystem via NFS (nfsroot)
- syslinux.org: pxelinux FAQ

Category:

- Installation process (简体中文)

Hidden categories:

- Pages or sections flagged with Template:Merge
- Pages or sections flagged with Template:Accuracy