网络启动核心组件:DHCP服务器、TFTP服务器、NFS/HTTP服务器、启动加载器

网络启动这件事,说白了就是让一台裸机通过网络把操作系统拉起来。你想想看,没有硬盘、没有光驱,机器怎么活?靠的就是几个核心组件协同工作。这一章我把它们拆开来讲,每个组件负责什么、怎么配、坑在哪,咱们一个一个过。

一句话总结:DHCP 给客户端发地址和启动文件路径,TFTP 或 HTTP 传小文件(启动加载器),NFS 或 HTTP 挂载根文件系统,启动加载器负责加载内核和 initrd。四者缺一不可。

2.1 DHCP 服务器:网络启动的“引路人”

DHCP 不只是发 IP 地址。在 PXE 场景里,它还要告诉客户端:“你的启动文件在哪,去哪个服务器拿。” 我刚开始接触 PXE 时,以为 DHCP 配个地址池就行,结果客户端死活不启动。后来才发现,少配了 next-server 和 filename 这两个选项。

DHCP 的核心配置项如下:

配置项 作用 示例值
subnet 定义客户端所在的子网 192.168.1.0 255.255.255.0
range 可分配的 IP 地址池 192.168.1.100 192.168.1.200
next-server TFTP/HTTP 服务器的 IP 地址 192.168.1.10
filename 启动加载器的文件名 pxelinux.0 或 bootx64.efi
option bootfile-name UEFI 环境下的启动文件路径 efi/grubx64.efi

我个人习惯用 ISC DHCP Server,因为它稳定、文档全。下面是一个典型的 PXE 配置片段:

subnet 192.168.1.0 netmask 255.255.255.0 {
  range 192.168.1.100 192.168.1.200;
  option routers 192.168.1.1;
  option domain-name-servers 8.8.8.8;

  # PXE 专用选项
  next-server 192.168.1.10;
  filename "pxelinux.0";

  # UEFI 客户端走不同文件
  class "pxeclients" {
    match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
    filename "pxelinux.0";
  }
  class "eficlients" {
    match if substring (option vendor-class-identifier, 0, 9) = "EFI Client";
    filename "efi/grubx64.efi";
  }
}

注意:如果 DHCP 和 PXE 服务器不在同一台机器,必须确保 DHCP 中继(ip helper)能正确转发 PXE 请求。我曾经在一个跨 VLAN 的环境里折腾了两天,最后发现是中继没开 DHCP Option 66 和 67。

2.2 TFTP 服务器:小文件传输的“老黄牛”

TFTP 协议很简单,基于 UDP 69 端口,没有认证、没有加密,就是传文件。你可能会问:“为什么不用 FTP 或 SCP?” 原因很简单——PXE 客户端在启动阶段,网卡固件只内置了 TFTP 和 HTTP 客户端,没有别的选择。

TFTP 的典型用途:

  • 传输启动加载器(pxelinux.0、grubx64.efi)
  • 传输配置文件(pxelinux.cfg/default、grub.cfg)
  • 传输内核和 initrd(vmlinuz、initrd.img)

我推荐用 tftp-hpa 或 dnsmasq 自带的 TFTP 模块。配置起来很简单:

# 安装 tftp-hpa
yum install tftp-server -y

# 编辑 /etc/xinetd.d/tftp
service tftp
{
  socket_type     = dgram
  protocol        = udp
  wait            = yes
  user            = root
  server          = /usr/sbin/in.tftpd
  server_args     = -s /var/lib/tftpboot
  disable         = no
  per_source      = 11
  cps             = 100 2
  flags           = IPv4
}

# 重启服务
systemctl restart xinetd

小技巧:TFTP 默认传输块大小是 512 字节,传输大文件(比如内核)会很慢。可以在 server_args 里加 -b 1468 调整块大小,能明显提速。我在部署 500 台机器时,这个参数让启动时间从 3 分钟降到了 40 秒。

2.3 NFS/HTTP 服务器:根文件系统的“大后方”

启动加载器把内核和 initrd 拉下来之后,内核需要挂载根文件系统。这时候有两种主流方案:NFS 和 HTTP。

方案 协议 端口 适用场景 性能
NFS NFSv3/v4 2049 传统 PXE、无盘工作站 中等,依赖网络延迟
HTTP HTTP/HTTPS 80/443 现代 PXE、大规模部署 高,支持并发和缓存

NFS 配置示例:

# 安装 NFS 服务器
yum install nfs-utils -y

# 编辑 /etc/exports
/var/nfsroot 192.168.1.0/24(rw,no_root_squash,sync,no_subtree_check)

# 启动服务
systemctl enable nfs-server
systemctl start nfs-server

HTTP 方案更现代,配合 nginx 或 apache 就能用。内核启动参数里加 root=/dev/nfs nfsroot=192.168.1.10:/var/nfsroot 或者 root=live:http://192.168.1.10/rootfs.squashfs。

我的建议:如果是新项目,优先用 HTTP。NFS 在并发高时容易出锁问题,HTTP 配合 squashfs 或 ext4 镜像更稳定。我在一个教育机房项目里,用 HTTP 方案同时启动 200 台终端,没出过问题。

2.4 启动加载器:承上启下的“指挥官”

启动加载器是网络启动的“大脑”。它从 TFTP/HTTP 下载配置文件,根据配置找到内核和 initrd,然后加载并启动系统。主流的有两种:

  • pxelinux.0:传统 BIOS 下的选择,基于 SYSLINUX 项目,配置文件在 pxelinux.cfg/ 目录下。
  • grubx64.efi:UEFI 下的选择,基于 GRUB2,配置文件是 grub.cfg。

pxelinux 的配置文件示例:

# /var/lib/tftpboot/pxelinux.cfg/default
default linux
prompt 1
timeout 100

label linux
  kernel vmlinuz
  append initrd=initrd.img root=/dev/nfs nfsroot=192.168.1.10:/var/nfsroot rw

GRUB2 的配置文件示例:

# /var/lib/tftpboot/efi/grub.cfg
set default=0
set timeout=10

menuentry "Network Boot - CentOS 7" {
  linuxefi vmlinuz root=/dev/nfs nfsroot=192.168.1.10:/var/nfsroot rw
  initrdefi initrd.img
}

避坑指南:我曾经遇到过一个问题——pxelinux 配置文件里写对了路径,但客户端就是找不到文件。后来发现是文件名大小写问题。PXE 客户端对大小写敏感,而 TFTP 服务器默认是大小写不敏感的。解决方案:统一用小写文件名,或者在配置里严格匹配。

2.5 核心组件协作流程图

下面这张图展示了客户端从加电到启动完成的完整流程,以及每个组件在其中的位置:

网络启动核心组件协作流程图 网络启动核心组件协作流程图 PXE 客户端 ① DHCP 请求 DHCP 服务器 ② 返回 IP + 启动文件路径 PXE 客户端 ③ TFTP 请求 TFTP 服务器 ④ 返回 pxelinux/grub 启动加载器 ⑤ 读取配置文件 配置文件 ⑥ 请求内核/initrd TFTP / HTTP ⑦ 挂载根文件系统 NFS / HTTP 根文件系统 流程说明 ① 客户端广播 DHCP 请求 ② DHCP 返回 IP 和启动信息 ③ 客户端通过 TFTP 下载 启动加载器 ④ 启动加载器读取配置 ⑤ 下载内核并挂载根文件系统

2.6 组件选型与版本兼容性

选型时要注意版本匹配。我见过有人用 ISC DHCP 4.x 配旧版 pxelinux,结果 Option 67 解析失败。下面是我整理的兼容性对照表:

组件 推荐版本 兼容性说明
ISC DHCP 4.3+ 支持 Option 66/67,兼容 UEFI HTTP Boot
dnsmasq 2.80+ 内置 DHCP + TFTP + DNS,适合小规模环境
tftp-hpa 5.2+ 稳定,支持块大小调整
pxelinux.0 6.03+ 支持 BIOS 和 UEFI(通过 syslinux.efi)
GRUB2 2.04+ 支持 UEFI HTTP Boot,支持加密启动
NFS nfs-utils 2.3+ 建议用 NFSv4,减少端口协商问题
nginx 1.20+ 支持大文件并发,适合 HTTP 启动方案

个人经验:如果你在 UEFI 环境下用 GRUB2,记得把 grubx64.efi 和 grub.cfg 放在 TFTP 根目录的 efi/ 子目录下。DHCP 的 filename 要写成 efi/grubx64.efi,否则客户端会报找不到文件。这个坑我踩过两次,一次是手误写成了 EFI/grubx64.efi(大写),一次是忘了加子目录路径。