1. 课程导入

各位同学好,我是老赵。今天咱们开始第一讲——PXE网络启动的原理。说实话,这玩意儿我入行头两年一直觉得它很神秘,直到有一次在数据中心批量部署200台服务器,被BIOS和UEFI的兼容性问题折腾了一整夜……嗯,从那以后我就把PXE的每个细节都啃透了。

PXE,全称Preboot eXecution Environment,说白了就是让一台还没装系统的裸机,通过网络从远程服务器启动。你想想看,没有硬盘、没有光驱、没有U盘,机器怎么活?靠的就是网络。

1.1 PXE协议栈:三剑客

PXE不是单一协议,它是一套协议栈。我习惯把它拆成三层:

  • 底层:UDP/IP,网络通信的基础
  • 中间层:DHCP + TFTP,负责地址分配和文件传输
  • 应用层:NBP(Network Bootstrap Program),也就是启动程序本身

为什么用UDP?因为启动阶段没有完整的TCP栈,UDP轻量、无状态,适合这种"先活下来再说"的场景。

核心要点:PXE客户端只实现了极简的网络协议栈,仅支持DHCP、TFTP和基本的UDP/IP通信。别指望它跑HTTP或HTTPS——那是操作系统的事。

1.2 DHCP与TFTP交互流程

这个流程我画过不下50遍。每次给新人讲,我都会说:记住四个阶段——发现、提供、请求、确认。但PXE比普通DHCP多了一步。

咱们一步步拆解:

  1. DHCP Discover(广播):客户端大喊"我在这,谁给我IP?"
  2. DHCP Offer(单播/广播):DHCP服务器回应"给你IP,还有启动文件地址"
  3. DHCP Request(广播):客户端说"我就要这个"
  4. DHCP Ack(单播):服务器确认"好的,你的启动文件在tftp://192.168.1.100/pxelinux.0"
  5. TFTP下载启动文件:客户端通过TFTP拉取NBP文件
  6. 执行NBP:启动文件接管控制权,继续加载内核和initrd

这里有个坑,我曾经踩过:DHCP Offer里必须携带next-server和filename选项。很多新手只配了IP池,忘了配启动文件路径,结果客户端卡在"PXE-E53: No boot filename received"。

我的经验:在生产环境中,我建议把DHCP和TFTP分开部署。DHCP用isc-dhcp-server,TFTP用tftp-hpa。别图省事全塞一台机器上,否则流量一上来,TFTP的UDP丢包会让你怀疑人生。

来看一个典型的DHCP配置片段:

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;
  next-server 192.168.1.10;   # TFTP服务器地址
  filename "pxelinux.0";      # 启动文件名
}

为什么会这样设计?因为DHCP负责"指路",TFTP负责"送货"。各司其职,清晰明了。

1.3 BIOS与UEFI启动差异

这是最容易出问题的地方。我记得有一次给客户部署,BIOS机器全正常,UEFI机器全黑屏。查了半天,原来是启动文件名不对。

咱们用表格对比一下:

对比项 BIOS(Legacy) UEFI
启动文件 pxelinux.0 bootx64.efi 或 grubx64.efi
网络栈 使用UNDI(通用网络驱动接口) 使用UEFI网络协议栈
TFTP传输 支持blksize协商,默认512字节 支持blksize协商,可调大至1468
安全启动 不支持 支持Secure Boot,需签名
配置文件 pxelinux.cfg/ grub.cfg 或 refind.conf

你想想看,BIOS下的PXE客户端,启动文件是pxelinux.0,这是一个实模式下的二进制文件。而UEFI下,启动文件必须是PE32+格式的EFI应用,比如bootx64.efi。混着用?直接报错。

避坑指南:我曾经在混合环境中(既有BIOS又有UEFI机器),用dnsmasq的dhcp-match功能,根据客户端发送的DHCP选项93(Client System Architecture)来区分。BIOS发0,UEFI发7或9。然后动态返回不同的启动文件。具体配置如下:

dhcp-match=set:bios,option:client-arch,0
dhcp-match=set:uefi,option:client-arch,7
dhcp-match=set:uefi64,option:client-arch,9
dhcp-boot=tag:bios,pxelinux.0
dhcp-boot=tag:uefi,bootx64.efi
dhcp-boot=tag:uefi64,bootx64.efi

1.4 完整交互流程图

下面这张图我手绘过很多次,它把整个PXE启动的"握手"过程讲清楚了:

PXE网络启动完整交互流程 PXE客户端 DHCP服务器 TFTP服务器 ① DHCP Discover ② DHCP Offer (含next-server+filename) ③ DHCP Request ④ DHCP Ack ⑤ TFTP: 下载启动文件 (pxelinux.0 / bootx64.efi) ⑥ 返回启动文件 ⑦ 执行NBP启动文件 ⑧ 加载内核+initrd 关键说明 • 步骤①-④是标准DHCP四步握手 • 步骤⑤-⑥是TFTP文件传输,使用UDP 69端口 • 步骤⑦-⑧由NBP文件接管,加载操作系统内核

1.5 实际部署中的几个关键点

讲完原理,咱们聊聊实战中容易翻车的地方:

  • TFTP传输效率:默认512字节一个块,传个大内核慢得要死。我习惯把blksize调到1468,配合tsize选项,速度能提升3-5倍。
  • DHCP超时重试:客户端默认重试4次,每次间隔递增。如果网络延迟大,建议在DHCP服务器上降低lease-time,避免客户端等太久。
  • UEFI Secure Boot:如果开了安全启动,启动文件必须签名。我遇到过最坑的情况是——明明配置都对,就是启动不了,最后发现是Secure Boot在作祟。

我的习惯:在实验室里,我会先用VirtualBox搭建一个迷你PXE环境,把BIOS和UEFI两种模式都测一遍。确认无误后再上生产。别问我为什么——当年在机房蹲了一夜修出来的教训。

好了,这一章的内容就是这些。PXE的原理其实不复杂,但细节很多。你只要把DHCP和TFTP的交互流程刻在脑子里,再记住BIOS和UEFI的差异,后面章节的实操就会顺畅很多。