
凡是做过批量装系统的人都经历过那种一台台插U盘、守屏幕、等进度条的滋味。装三五台还能忍一旦扑到几十台新服务器、机房一排机器要统一重装手工操作就是最大的时间黑洞。我见过有人熬到凌晨两点装完一半第二天发现内核版本选错所有机器又要推倒重来。PXE服务器加无人值守安装就是专门来解决这种批量装机问题的通过局域网实现Linux系统的全自动安装客户端网卡通电启动不用U盘、不用光驱、不用人工点击自动完成分区、装包、配置、交付。这篇文档我会把PXE引导的完整链路、搭建步骤、Kickstart配置和排错经验一次性讲清楚适合系统运维、实验室管理员也适合刚接触网络装机、想摆脱手工重复劳动的新手朋友。1. 弄懂PXE引导链路先想清楚再动手1.1 PXE是怎么把一台裸机送上安装流程的PXE全名Preboot eXecution Environment是Intel定义的一套网络启动协议绝大多数带网卡的服务器和台式机都实现了它的固件级支持。所谓“固件级”意思是机器还没进操作系统网卡自己就能去做网络通信。你可以把整套过程理解成一次“网络取件”客户端开机网卡先向DHCP服务器喊一句“我在哪我的引导文件在哪”DHCP除了分配一个IP还会额外告诉客户端“去哪个TFTP服务点取件取件码是什么”客户端去TFTP把引导程序pxelinux.0拉到内存引导程序再按配置文件里的菜单把内核和initrd下载下来最后内核起来挂载HTTP上的安装源进入anaconda安装界面。如果你是在UEFI引导模式下过程略有不同。UEFI机器需要的引导文件不再是pxelinux.0而是grubx64.efi或shim.efi但整体架构一致DHCP获取地址和启动信息TFTP拉取引导文件HTTP提供安装资源。这个链路里任何一个环节断了表现都不一样所以先把概念在脑子里立住。后面配置的每一行都有的放矢否则很容易出现“配置了半天但客户端就是引导不了”的怪事。我在最初的实验里就是因为没理清DHCP和TFTP各自负责什么反复在错误的方向上改配置白折腾了大半天。1.2 组件选型DHCP、TFTP、HTTP三件套如何搭配PXE搭建最基础的三件套是DHCP、TFTP和HTTP或NFS。很多人一开始就把方案搞复杂了其实选型很自由关键是自己知道为什么这么选。常见组合一是用isc-dhcp-server加tftp-hpa加nginx或apache。各组件独立部署职责清晰排错方便适合生产环境和需要长期维护的场景。组合二是全部用dnsmasq一个服务搞定。dnsmasq同时提供DHCP、DNS和TFTP功能配置短启动快非常适合实验室和临时验证环境但功能相对有限日志区分度也不如独立服务。安装源方面有人习惯用NFS我后来全面转向HTTP。HTTP服务器随便哪个发行版都有现成的包权限简单支持断点续传路径也直观排错时浏览器打开就能验证。组合方案优点缺点适合场景isc-dhcp tftp-hpa nginx职责独立、日志清晰、排错方便配置稍多、服务进程多生产环境、长期维护dnsmasq httpd配置极短、部署快功能集成、排错粒度粗实验室、临时验证传统NFS安装源无需额外HTTP服务权限配置复杂、并发表现一般老旧环境、特殊依赖我在这篇文章里以“独立三件套”为例讲因为拆得开才容易讲得清。如果你只是本地实验完全可以直接用dnsmasq顶替前两项原理没有变化。1.3 部署环境规划一台服务器能撑起多少台客户端架构定了接下来想清楚网络和目录规划。假定PXE服务器固定IP为192.168.1.10客户端使用192.168.1.0/24网段DHCP地址池建议预留至少200个地址避免批量装机时IP耗尽。HTTP安装源按发行版和版本在/var/www/html目录下建子目录例如/var/www/html/linux/rocky9同一台PXE服务器可以同时托管多个版本的系统镜像后续维护时只增加映射即可不用重建环境。服务器配置方面双核CPU加8GB内存跑这套服务其实很充裕真正的瓶颈通常在磁盘IO因为安装源文件会被大量并发读取。这里有个很多人忽略的细节交换机端口如果启用了生成树协议客户端PXE引导可能被STP等待拖慢表现就是网卡显示已启动但迟迟等不到DHCP。在交换机接入端口开启类似portfast的功能不同品牌叫法不同能让PXE引导明显变顺畅。另外UEFI和BIOS两种固件需要的引导文件不同如果你的机器大多是近几年的服务器优先准备UEFI引导文件同时保留BIOS配置作兼容方案。我建议动手前先统计清楚目标机器的固件类型别等批量引导全失败才反应过过来。2. 搭建PXE服务器DHCP、TFTP、HTTP逐项落地2.1 DHCP服务配置让客户端找到起点先装DHCP服务。以Rocky Linux这一类发行版为例安装包名叫dhcp-server。安装完成后核心配置文件是/etc/dhcp/dhcpd.conf。为了让PXE能正确引导关键就两行next-server 192.168.1.10; filename pxelinux.0;next-server告诉客户端TFTP服务器是谁filename告诉客户端去取哪个引导文件。由于这台服务器上DHCP和TFTP都在同一台机器next-server就是本机IP。如果以后TFTP服务器拆分出去改这里就行不用动任何客户端。一个完整的DHCP配置片段大概是这样的subnet 192.168.1.0 netmask 255.255.255.0 { option routers 192.168.1.1; option domain-name-servers 192.168.1.10; range 192.168.1.100 192.168.1.250; next-server 192.168.1.10; filename pxelinux.0; }如果你的客户端有部分是UEFIDHCP会根据client-arch字段区分架构可以把配置写得更灵活。但新手入门阶段先统一BIOS模式跑通一遍再考虑扩展。修改完后用systemctl enable --now dhcpd启动服务并用journalctl -u dhcpd观察日志。这里最容易出的错是配置文件写错后服务起不来排查时先用dhcpd -t检查语法。我在首次配置时就因为写错了option routers的地址导致DHCP服务一直拒绝启动查了半天才发现是个手误。2.2 TFTP引导服务把启动文件交给客户端TFTP服务负责把pxelinux.0、内核和initrd传给客户端。安装tftp-server后默认根目录一般是/var/lib/tftpboot。需要做以下几件事从syslinux包中拷贝pxelinux.0到TFTP根目录从安装ISO的isolinux目录中拷贝vmlinuz和initrd.img到TFTP根目录创建pxelinux.cfg目录编写默认菜单。命令示例cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/ cp /path/to/isolinux/vmlinuz /var/lib/tftpboot/ cp /path/to/isolinux/initrd.img /var/lib/tftpboot/TFTP是UDP 69端口防火墙必须放行。如果你用了SELinux还需注意SELinux布尔值和文件上下文否则客户端可能能下载小文件但下载大文件时总超时。我的做法是安装后直接用semanage给tftpboot目录设置正确的类型省得后续困扰。菜单文件/var/lib/tftpboot/pxelinux.cfg/default控制引导界面一个简单的默认菜单如下default linux timeout 30 label linux menu label Auto Install Linux kernel vmlinuz append initrdinitrd.img inst.stage2http://192.168.1.10/linux/rocky9 kshttp://192.168.1.10/ks/rocky9.ks客户端拿到这行配置后就会去HTTP拉取安装源并请求kickstart文件。TFTP本身传输效率不高但只传内核和initrd这些小文件速度足够。如果有人把整个ISO都塞进TFTP目录那性能会非常难看所以安装源必须放到HTTP里。2.3 HTTP安装源让安装程序随时拉取软件包安装源用HTTP提供最为省心。先把系统ISO挂载到Web根目录下。比如mkdir -p /var/www/html/linux/rocky9 mount -o loop rocky-9.iso /mnt/iso cp -a /mnt/iso/. /var/www/html/linux/rocky9/如果你希望每次系统启动都自动挂载写入/etc/fstab即可。如果空间紧张也可以直接用mount绑定ISO到目录而不复制镜像内容但批量装机时并发读取量大复制到磁盘读起来更稳。这里要提醒一句挂载点所在磁盘尽量用SSD或至少是剩余空间充足的盘机械盘在几十台机器同时读取时会出现明显的I/O瓶颈客户端安装进度会变得非常不均匀。此时浏览器访问http://192.168.1.10/linux/rocky9/应当能看到ISO内的目录结构比如images、isolinux、AppStream这些。确认这一步无误再回来看PXE菜单里的inst.stage2路径。这个路径写错了安装程序会直接报找不到安装源。我习惯在启动客户端前先用curl测试URL而不是一上来就重启机器。测试命令类似curl -I http://192.168.1.10/linux/rocky9/状态码200且返回目录信息就说明HTTP部分没问题。3. 无人值守安装核心Kickstart配置文件实操3.1 Kickstart文件结构拆解无人值守的关键是Kickstart文件简称ks文件它本质上是把手工安装时那些点按钮的操作全部转成一条条文本指令。安装程序启动后会按ks文件继续执行不再问你任何问题。一个基础ks文件长这样install lang en_US.UTF-8 keyboard us timezone Asia/Shanghai --isUtc rootpw --iscrypted $6$encryptedhash url --urlhttp://192.168.1.10/linux/rocky9 network --bootprotodhcp selinux --enforcing firewall --enabled --servicessh zerombr clearpart --all --initlabel bootloader --locationmbr --appendnet.ifnames0 biosdevname0 part /boot --fstypexfs --size1024 part pv.01 --size1 --grow volgroup vg0 pv.01 logvol / --vgnamevg0 --size40960 --fstypexfs logvol swap --vgnamevg0 --size4096 %packages ^minimal vim %end这里每一行都值得看懂。install表示全新安装url指定安装源地址network用dhcp拿地址clearpart清理磁盘bootloader写入MBR并追加内核参数。特别要说下rootpw一定不要直接写明文密码用openssl passwd -6生成加密串填进去否则ks文件一旦被人看到等于把服务器root权限拱手送人。%packages段里^minimal表示最小化环境组后面跟的vim是额外要装的包。文件写好后放到HTTP服务能访问的路径下比如/var/www/html/ks/rocky9.ks。3.2 常用分区与软件包选择策略分区是ks文件里最容易让新手纠结的部分。我的经验是测试机怎么简单怎么写直接分/boot和/两块分区就好生产服务器建议LVM后续扩容不用重新分区。上面的例子先建了物理卷pv.01再创建卷组vg0最后在卷组上划分逻辑卷作为根分区和swap。逻辑卷的好处是一开始不必把大小卡死磁盘剩余空间都留在卷组里后面用lvresize就能扩。比如装完后发现根分区不够用直接执行lvresize -L 20G /dev/vg0/root再xfs_growfs就能完成扩容不需要停机重装。软件包选择上最影响安装速度的是安装组大小。如果只是开机即用选^minimal或core这类基础组安装速度能快不少。需要特定功能时再通过包组追加比如development表示开发工具container-management表示容器管理工具链。你完全可以在ks文件里用多个%packages块或加--exclude排除不想要的包例如排除一些自带但用不上的服务减少安全攻击面。包选择这块可以反复迭代每改一次ks文件重新装机验证一次比手工装完再卸载高效得多。我自己迭代到后面ks文件里不同业务线各有版本几乎不用再动手装任何额外软件。3.3 巧用%post脚本完成安装后自动化Kickstart最实用的部分是%post段。这段脚本在系统安装完成、首次重启之前执行可以在这里做一堆自定义配置。比如%post --interpreter/bin/bash hostnamectl set-hostname node-$RANDOM mkdir -p /root/.ssh echo ssh-rsa AAAA... your-key /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys curl -s -X POST http://192.168.1.10:8080/install-report -H Content-Type: application/json -d {status:ok,ip:$(ip route get 1 | awk {print $NF; exit})} echo export HISTTIMEFORMAT%F %T /etc/profile %end注意%post默认不是在chroot环境下执行的脚本里能访问到安装环境里的文件系统但某些发行版上为了统一可以加--chroot参数。这个细节不同系统有差异我一般按发行版文档选择默认不加。上面用hostnamectl设置随机主机名、注入SSH公钥再用curl上报本机IP到管理端。这样一台机器装完就能通过上报信息看到自己的IP几百台机器统计谁装完了非常方便。还可以在这里配置监控agent、把机器加入集中认证、统一审计策略。如果后续还要定制别忘了ks文件本身也可以用模板动态生成。常见做法是用Python脚本读取IP和MAC清单批量生成多份ks文件每一份带不同的主机名、IP、分区大小甚至软件包集合这样网络装机才能真正做到按需交付。我见过一个团队把ks模板和资产表联动新机器接入网络后自动获得对应配置整个过程不需要人工干预。4. 批量装机实战问题排查与提速经验4.1 新手上路最容易踩的五个坑搭PXE服务器的坑基本都集中在“客户端启动到不了安装界面”和“安装界面能进但到不了安装源”这两个阶段。我把高频问题整理成一张表现象常见原因解决方向客户端提示No boot filename receivedDHCP没下发filename或下发文件名不对检查dhcpd.conf里的next-server和filenameTFTP连接超时、传输中断防火墙未放行UDP 69SELinux拦截放行tftp服务确认文件上下文正确安装程序找不到安装源inst.stage2的URL写错HTTP目录不可见浏览器直接访问URL验证ks文件拉取不到ks路径无法访问或URL端口被防火墙挡确认ks文件可下载测试访问客户端卡在PXE-E32引导文件不存在或网络中断确认TFTP根目录有pxelinux.0或UEFI引导文件还有一类特别容易被忽视客户端网卡虽然支持PXE但BIOS里把网络启动排到了硬盘之后或者启用了SecureBoot直接绕过了PXE引导。批量装机前建议先在目标型号机器上手动确认启动顺序。另外如果客户端装的过程中断电或网线松动可能留下半成品分区导致第二次引导时安装程序报磁盘错误。这时可以在ks里加zerombr和clearpart --all强制清理磁盘再装。4.2 用日志和抓包工具定位故障遇到引导失败最快的路线是看日志和抓包。DHCP服务端看journalctl -u dhcpdTFTP看systemctl status tftp或对应日志文件HTTP看nginx/error.log。如果日志里什么关键信息都没有直接在PXE服务器上抓包tcpdump -i eth0 -nn port 67 or port 68 or port 69 or port 80 -w pxe.pcap然后让客户端重新开机抓完包用Wireshark打开。正常流程应该能看到DHCP的四次握手、客户端向TFTP请求文件、HTTP拉取安装源的连接。看到哪一步断了问题就锁定在哪一层。有一次我在机房排查一晚上最后发现是交换机端口禁用了UDP广播DHCP discover根本到不了服务器抓包后一眼就暴露了。这种问题不看包完全靠猜会非常耗时间。另外TFTP传输文件时客户端可能会请求加载选项文件比如pxelinux.cfg/01-加MAC地址如果文件不存在系统就会退回default这是正常现象不代表错误。看到404不用过度紧张这是PXE菜单机制的一部分它允许你按MAC地址精确匹配配置匹配不到就走默认菜单。4.3 规模化装机的管理与优化建议等网络装机流程完全跑通就可以考虑规模化了。我的建议是先把DHCP地址池按批次划分比如一批50台机器对应50个连续地址装完一批就释放一批避免多批次同时装时混乱。ks文件的URL可以带不同参数比如kshttp://192.168.1.10/ks/rocky9.ks?batch01用脚本在服务端记录请求来源读日志就能看到哪台机器领取了哪份配置。并发量上来后HTTP服务会顶住比较大的读取压力。规格上普通双核服务器带几十台客户端的下载负载压力不大但如果同时装一百台以上建议把安装源放到SSD上并且启用HTTP的keepalive。不要用机械硬盘装ISO再大规模并发否则客户端会频繁出现加载软件包超时。还可以用rsync定期把镜像目录和官方源同步保证ks里指定的包都能找到避免出现“包列表里有某软件但仓库里没有”的尴尬。我自己的习惯是维护一份装机清单一览表包含机器MAC、预计IP、主机名、对应系统版本和ks文件路径。PXE菜单里设多个label比如Auto Install Rocky9、Auto Install Ubuntu、memtest等装机时在客户端启动界面按需选择不会因为版本混装而混乱。菜单组织好之后日常装机基本就是通电开机、选择标签、等进度条走完非常省心。最后再分享一个小技巧在pxelinux菜单里加一个memtest入口把memtest86放到TFTP目录里。新机器装完系统如果频繁报错先用它跑一遍内存能省去很多怀疑系统配置的冤枉时间。我在实际项目中已经靠这个法子排掉过好几台内存条松动的问题。我个人现在的装机流程是服务器上先跑通最小模型验证一台机器无误后再按批次放量所有配置文件都放进版本管理仓库每次改动留变更记录服务器磁盘上的镜像和ks文件定期备份。这套流程看着简单真能把大批量Linux系统交付的不可控因素压到很低也让我从过去被装机绑死在机房的状况里彻底解放出来。