1. 从一次机房上架说起:为什么我要重新审视装机方式
去年冬天接了个活,给一个中等规模的机房上架四十多台同配置的服务器,全部装 CentOS 7。当时我第一反应还是老办法——拿个 U 盘,做个启动盘,一台一台插上去装。结果第一天下来,从早上九点干到晚上十点,连装带配置,勉强搞定十一台。中间还遇到两块 U 盘因为反复插拔加上写入频繁直接罢工,其中一块在装到一半的时候掉盘,那台机器卡在安装界面动不了,只能重来。那天晚上我坐在机房地上,看着剩下三十台还没开箱的机器,脑子里就一个念头:这么干下去,这活没法交。
后来跟一个做运维的朋友聊起这事,他一句话点醒我:“你四十台机器配置一模一样,为什么要一台一台手动装?PXE 不就是干这个的?”说实话,PXE 这东西我早就知道,但一直觉得“搭起来麻烦”“就装几台不值当”,所以从来没认真在批量场景里用过。这次被逼到墙角,我花了一个周末把 PXE 环境搭起来,第二个周一上午,剩下的三十台机器全部装完,人基本没怎么盯着。
这件事之后,我把两种方式都做了系统性的实测对比,把数据、坑点、适用边界都记了下来。这篇东西就是那次实测的完整复盘,适合手里有批量装机需求、正在纠结用 U 盘还是上 PXE 的同行参考,也适合刚接触服务器部署、想搞清楚 PXE 到底值不值得学的新人。我会把效率数据、搭建细节、踩过的坑、以及“什么情况下别用 PXE”都讲清楚,不吹不黑,只讲实测。
2. 两种装机方式的本质差异:不是快慢问题,是“人要不要守着”的问题
2.1 U 盘安装的真实工作流拆解
很多人对 U 盘装机的印象停留在“插上去点下一步”,但真正在批量场景里,它的完整工作流是这样的:先在一台机器上做好启动 U 盘(用 dd 或者 Rufus 写入镜像,这一步大概五到十分钟),然后插到目标机器,进 BIOS 改启动顺序,进安装界面,选语言、分区、网络、主机名、root 密码、软件包组,等安装完成,重启,拔 U 盘,再插到下一台。
单看一台机器,熟练的话从插盘到装完大概二十五到三十五分钟,其中真正需要人操作的部分(改 BIOS、点安装选项)大概八到十分钟,剩下的时间是等待系统写入。问题在于,这八到十分钟的人是被绑死的——你不能走开,因为安装过程中可能弹窗、可能报错、可能需要确认分区。四十台机器,就是四十次“人被绑在机器前”。
更隐蔽的成本是一致性风险。手动装的时候,主机名、IP、分区方案这些参数全靠人记和手输,装到第二十台的时候人已经麻了,很容易出现某台机器主机名忘了改、某台分区多分了一个 /home、某台软件包组选错的情况。这些错误当场看不出来,等集群跑起来做统一管理的时候才会集中爆发,排查起来非常痛苦。
2.2 PXE 引导到底改变了什么
PXE(Preboot eXecution Environment)的本质,是让机器在没有任何本地存储介质的情况下,通过网卡从网络上的服务器拉取启动文件和安装文件。放到 CentOS 7 批量部署的场景里,它的工作流变成了:目标机器设置成网卡启动(很多服务器出厂默认就支持,或者改一次 BIOS 后永久生效),开机后自动通过 DHCP 拿到 IP 和引导文件地址,通过 TFTP 下载引导程序,再通过 HTTP/FTP/NFS 拉取完整的安装源,配合 Kickstart 应答文件自动完成所有安装选项,装完自动重启进入系统。
这里的关键变化是:人的角色从“操作员”变成了“监工”。你只需要在装机前把 Kickstart 文件配好(分区方案、主机名规则、软件包、网络配置全写进去),然后给机器上电,剩下的它自己完成。四十台机器可以同时上电、同时装,你只需要偶尔看一眼进度。
我实测下来,PXE 方案里单台机器的“人工介入时间”接近于零,真正花时间的是前期环境搭建(大概两到三小时,一次性投入)和Kickstart 文件的调试(第一台机器可能要改两三版,后面就稳定了)。这个投入产出比的分水岭,大概在十台左右——少于十台,搭 PXE 的时间够你用 U 盘装完了;超过十台,PXE 的优势开始指数级放大。
2.3 一张表看清两种方式的成本结构
| 对比维度 | U 盘安装 | PXE 网络引导 |
|---|---|---|
| 单台人工操作时间 | 8-10 分钟(全程需在场) | 约 0 分钟(上电后自动) |
| 单台总耗时 | 25-35 分钟 | 15-25 分钟(并行时互不影响) |
| 前期环境搭建 | 5-10 分钟(做盘) | 2-3 小时(一次性) |
| 参数一致性 | 靠人记,易出错 | Kickstart 统一控制,零偏差 |
| 硬件依赖 | 需要可用 U 盘,反复插拔易损 | 需要网络环境和支持 PXE 的网卡 |
| 适合规模 | 1-10 台 | 10 台以上,规模越大越划算 |
| 故障恢复 | 单台重装,简单直接 | 改配置后批量重装,效率极高 |
这张表里最值得说的是“参数一致性”这一行。U 盘装机的隐性成本不在时间,而在返工。我那次四十台机器里,后来发现有五台的主机名规则不统一,导致监控系统里认不出来,又花了大半天逐台改。PXE 用 Kickstart 统一生成,这种问题从根上就不存在。
3. PXE 环境搭建:那些教程不会告诉你的关键细节
3.1 服务选型与最小化组件清单
搭 PXE 环境,核心就四个服务:DHCP(给目标机分配 IP 并告知引导文件位置)、TFTP(传输引导程序 pxelinux.0 和配置文件)、HTTP 或 FTP(传输 CentOS 7 的完整安装源)、以及Kickstart 文件托管(可以放在 HTTP 服务里一起提供)。这四个服务可以跑在同一台机器上,我用的是一台配置很普通的虚拟机,2 核 4G,挂了一块 200G 的盘放安装源,完全够用。
这里第一个容易踩的坑是DHCP 和现有网络冲突。如果你的机房里已经有一个 DHCP 服务器在跑,你再起一个,轻则目标机拿到错误的地址,重则整个网段乱套。我的做法是把 PXE 这台机器的 DHCP 配置成只响应特定网卡、特定网段,并且用next-server精确指向自己。更稳妥的做法是跟网络管理员协调,在现有 DHCP 上直接加next-server和filename两个选项,不另起服务。我那次是自己起的,因为机房是隔离的测试网段,没有冲突风险。
TFTP 服务我用的tftp-server,配置里把disable改成no,根目录指向/var/lib/tftpboot。HTTP 服务用httpd,把 CentOS 7 的 ISO 挂载后整个目录拷到/var/www/html/centos7下。这几个组件都是系统自带的,不需要额外装什么花哨的东西,越简单越稳。
3.2 引导文件与菜单配置的实操要点
引导文件这块,CentOS 7 用的是pxelinux.0(来自syslinux包),配套需要vesamenu.c32(菜单界面)、ldlinux.c32等模块文件。这些文件在syslinux包的安装目录里能找到,拷到 TFTP 根目录下即可。很多人卡在这一步是因为只拷了 pxelinux.0,忘了拷 c32 模块,结果机器能拿到引导文件但菜单出不来,屏幕一片黑或者报 “Could not find kernel image”。
菜单配置文件放在tftpboot/pxelinux.cfg/default,核心内容大概长这样:
default vesamenu.c32 prompt 0 timeout 100 label centos7-auto menu label ^1. CentOS 7 自动安装(Kickstart) kernel vmlinuz append initrd=initrd.img inst.repo=http://192.168.1.10/centos7 ks=http://192.168.1.10/ks/centos7-ks.cfg这里有几个细节值得说。timeout 100是十秒后自动选默认项,批量装机时这个很有用——机器上电后你根本不用碰它,十秒后自动开始装。inst.repo指向 HTTP 上的安装源,ks指向 Kickstart 文件。prompt 0表示不显示 boot 提示符,直接进菜单。
提示:
vmlinuz和initrd.img这两个文件要从 CentOS 7 安装镜像的images/pxeboot/目录里拷出来,放到 TFTP 根目录。很多人直接拿 ISO 根目录的文件,那是错的,引导会失败。
3.3 Kickstart 文件:批量一致性的真正核心
Kickstart 是整个 PXE 方案的灵魂。它把安装过程中所有需要人点的选项全部写成文本,机器读了这个文件就照着装,一个都不问。我那份 ks 文件的核心段落大概是这样:
install url --url=http://192.168.1.10/centos7 lang en_US.UTF-8 keyboard us timezone Asia/Shanghai rootpw --iscrypted $6$xxxx(加密后的密码) network --bootproto=dhcp --device=eth0 --onboot=yes firewall --disabled selinux --disabled part /boot --fstype=xfs --size=1024 part swap --size=8192 part / --fstype=xfs --grow --size=1 %packages @^minimal @core %end reboot这里最容易被忽略的是主机名和 IP 的差异化处理。四十台机器如果全叫 localhost,集群管理会疯掉。我的做法是在 ks 文件里用%pre脚本段,根据目标机的 MAC 地址或者 DHCP 分配的 IP 末位,动态生成主机名。比如:
%pre #!/bin/bash IP=$(hostname -I | awk '{print $NF}' | awk -F. '{print $NF}') echo "network --hostname=node-${IP}" >> /tmp/ks-extra.cfg %end然后在主配置里用%include /tmp/ks-extra.cfg引入。这样每台机器装完主机名自动是 node-11、node-12 这种规则,完全不用人管。这个技巧是我踩了坑之后才想到的——第一版 ks 文件里主机名写死成 node,结果四十台机器全叫 node,后来逐台改,改到怀疑人生。
4. 效率实测:数据摆出来,差距比想象中大
4.1 测试环境与测试方法说明
为了把数据做扎实,我用了同一批次的十六台同配置服务器做对照测试,八台走 U 盘,八台走 PXE,硬件配置完全一致(双路 CPU、64G 内存、两块 480G SSD 做 RAID1),网络是千兆内网,安装源都是同一个 CentOS 7 镜像。测试指标有三个:单台从开始到装完的总耗时、人工介入时间、八台全部装完的墙钟时间(wall clock time,就是从第一台开始到最后一台结束的实际时间)。
需要说明的是,PXE 的八台是同时上电、同时安装的,所以它的墙钟时间约等于单台耗时加上一点排队开销;U 盘的八台是串行的,因为人只有一双手,一次只能装一台。这个对比方式可能有人觉得“不公平”,但恰恰是真实场景——你不可能同时手动操作八台机器。
4.2 单台耗时与人工介入时间对比
实测数据如下:
| 指标 | U 盘安装(单台均值) | PXE 安装(单台均值) |
|---|---|---|
| 引导到进入安装界面 | 1.5 分钟 | 0.5 分钟 |
| 人工配置选项 | 6-8 分钟 | 0 分钟 |
| 系统写入与安装 | 18-22 分钟 | 15-18 分钟 |
| 装完重启到可用 | 2 分钟 | 2 分钟 |
| 单台总耗时 | 约 28 分钟 | 约 18 分钟 |
| 人工介入时间 | 约 8 分钟 | 约 0 分钟 |
单台总耗时 PXE 快了大约十分钟,主要省在“人工配置选项”这一段——U 盘装的时候你要一项项点,PXE 直接读 ks 文件跳过所有交互。系统写入阶段 PXE 也略快,我分析是因为 HTTP 传输安装源的带宽比 U 盘 2.0 接口稳定,U 盘如果是 3.0 的盘差距会小一些,但人工配置那六到八分钟是省不掉的。
真正拉开差距的是人工介入时间。U 盘装八台,人要在机器前站八次、每次八分钟,累计六十四分钟的“被绑死”时间;PXE 装八台,人只需要上电、看一眼、走人,介入时间接近于零。这六十四分钟你可以去干别的,比如配交换机、理线、写文档,这才是批量场景里最值钱的部分。
4.3 八台批量场景的墙钟时间实测
墙钟时间的对比更直观:
- U 盘方案:八台串行,每台约 28 分钟,中间换盘、改 BIOS 的间隙算 2 分钟,总计约240 分钟,也就是整整四个小时,而且这四个小时人基本不能离开机房。
- PXE 方案:八台同时上电,单台约 18 分钟,因为共享网络带宽和安装源,实际略有排队,八台全部装完约26 分钟,人只需要在开始和结束时各看一眼。
四个小时对二十六分钟,这个差距已经不是“效率提升”能形容的了,是工作模式的改变。我那次四十台机器的实测更夸张:U 盘方案第一天十小时装了十一台,PXE 方案第二天上午三小时装完剩余二十九台(含调试 ks 文件的时间)。如果把前期搭环境的两三小时算进去,四十台的总账是 U 盘约三十六小时人工 vs PXE 约六小时(含搭建),差距接近六倍。
4.4 规模越大,PXE 的边际成本越低
这里有个经济学味道的规律值得说清楚:PXE 的成本结构是固定成本高、边际成本极低。搭环境那两三个小时是固定的,之后每多装一台,增加的成本几乎只有网络传输时间,人工成本为零。U 盘的成本结构是固定成本低、边际成本恒定,每台都要花那八分钟人工,装一百台就是八百分钟。
我算过一个粗略的盈亏平衡点:假设搭 PXE 环境花 2.5 小时(150 分钟),U 盘每台人工 8 分钟,那么当机器数量 N 满足8N > 150,即N 大于约 19 台时,PXE 在纯人工时间上就开始回本。如果算上 U 盘损耗、返工排查这些隐性成本,实际平衡点大概在十到十五台。所以我的经验判断是:十台以下老老实实用 U 盘,十五台以上认真考虑 PXE,三十台以上 PXE 基本是唯一理性选择。
5. 踩坑实录:PXE 搭建过程中那些让人抓狂的瞬间
5.1 机器拿到 IP 却卡在 “PXE-E32” 或无限重启
这是最常见的坑,表现是目标机屏幕上显示拿到了 IP,然后报PXE-E32: TFTP open timeout,或者干脆反复重启进不了引导。我第一次遇到时排查了快一个小时,最后发现是防火墙没关。TFTP 用的是 UDP 69 端口,很多人只记得开 TCP,忘了 UDP,或者系统默认的 firewalld 直接把 TFTP 拦了。
排查链路我后来总结成固定顺序:先确认目标机和 PXE 服务器网络通不通(在目标机的 PXE 界面能看到拿到的 IP,ping 一下服务器);再确认 TFTP 服务本身起没起(在服务器上tftp localhost手动拉一下 pxelinux.0);然后确认防火墙和 SELinux 状态;最后才怀疑配置文件。这个顺序能覆盖九成以上的 E32 问题。
还有一个隐蔽原因是TFTP 根目录权限。/var/lib/tftpboot这个目录如果权限不对,TFTP 服务读不到文件,表现也是超时。我习惯性chmod -R 755一下,省得折腾。
5.2 Kickstart 语法错误导致安装中途停住
Kickstart 文件写错一个字符,机器装到一半会停下来弹出一个对话框让你手动确认,这时候如果没人盯着,机器就卡在那里一动不动。我遇到过一次是part那行少写了一个--size,结果分区阶段直接报错停下。还有一次是%packages段里写了一个不存在的包名,安装器会停下来问“要不要继续”。
这类问题的排查技巧是:先用一台机器做“验证性安装”,盯着它从头装到尾,看有没有中途停顿。确认 ks 文件没问题了,再批量上电。另外,CentOS 7 安装时可以在引导参数里加inst.ks=...的同时加一个ksvalidator工具(在pykickstart包里)预先检查语法,能提前发现大部分格式错误。我现在的习惯是每次改完 ks 文件先跑一遍ksvalidator centos7-ks.cfg,通过了再上机。
注意:Kickstart 里
reboot这一行如果漏了,机器装完会停在“安装完成,请按回车重启”的界面,批量场景下没人按回车,机器就一直停着。这个坑非常隐蔽,因为单台测试时你顺手就按了,根本意识不到。
5.3 主机名和 IP 冲突:批量装完才发现全叫一个名字
前面提过主机名写死的问题,这里展开说排查过程。那次四十台装完,登录进去发现全是localhost,因为我在 ks 文件里压根没写 hostname,安装器默认就用 localhost。监控系统按主机名采集,四十台全叫 localhost,数据全混在一起,根本分不清哪台是哪台。
修复方案有两个:一是重装(有 PXE 的话重装很快,改完 ks 批量重来一遍也就半小时);二是逐台手动改(四十台,改到崩溃)。我选了重装,因为 PXE 重装成本极低,这也反过来印证了 PXE 的另一个优势——配置错了可以低成本批量重来,U 盘方案下你根本不敢想重装四十台。
后来我把主机名生成逻辑写进%pre段,用 IP 末位做后缀,同时把 IP 配置也改成静态(在 ks 里根据 MAC 地址映射固定 IP),彻底解决了这个问题。MAC 到 IP 的映射表我放在一个 CSV 里,%pre脚本读这个表来生成网络配置,这样每台机器的 IP、主机名、甚至所属角色都能精确控制。
5.4 安装源带宽被打满导致超时
八台机器同时从一台 HTTP 服务器拉安装源,千兆网卡的理论带宽是 125MB/s,八台一分,每台只有十几 MB/s,如果安装源所在的磁盘本身读速度跟不上,就会出现某几台机器拉包超时、安装失败。我第一次批量装的时候就遇到两台报 “failed to download package”。
解决办法有两个层面:一是安装源用 SSD 存放,别放机械盘,读速度能差好几倍;二是控制并发数,如果机器特别多(比如五十台以上),可以分批上电,一批十到十五台,装完一批再上一批,避免带宽和磁盘 IO 被打爆。另外 HTTP 服务本身可以调一下KeepAlive和MaxKeepAliveRequests,减少连接建立的开销,实测对并发拉取有一定帮助。
6. 什么情况下别硬上 PXE:适用边界的冷静判断
6.1 小规模、异构硬件、临时性任务的现实考量
PXE 虽好,但不是万能。我见过有人为了装三台机器折腾一下午搭 PXE,最后发现还不如 U 盘半小时搞定。十台以下、硬件配置还不一样的场景,PXE 的固定成本摊不薄,而且异构硬件意味着你可能要维护多份 ks 文件、多个驱动,复杂度陡增。这种时候 U 盘反而是更理性的选择。
还有一种情况是临时性、一次性的装机任务,比如就装两台测试机,用完就扔。搭 PXE 的两三小时投入完全收不回来,U 盘插一下十分钟完事。判断标准很简单:问自己这批机器未来半年内还会不会再有批量装机需求,会,就值得搭;不会,就别折腾。
另外,网络环境受限的场景也要谨慎。有些机房网络策略严格,不允许随便起 DHCP,或者网段隔离导致 PXE 服务器和目标机不通,这种时候硬上 PXE 会陷入无休止的协调和排障,不如老老实实 U 盘。
6.2 混合策略:我现在的实际做法
经过这一轮折腾,我现在的实际做法是混合策略:常备一个做好 PXE 环境的“装机服务器”(一台闲置机器或者虚拟机,环境搭好就留着,下次直接用,固定成本可以反复摊薄),日常零星装机用 U 盘,批量超过十台就上 PXE。这样两头的好处都占着。
U 盘我也没扔,反而准备了两三个不同版本的(CentOS 7 一个、常用工具盘一个),因为有些场景 PXE 确实覆盖不到,比如目标机网卡不支持 PXE、或者需要装一个完全不同的系统做对比测试。工具这东西,关键是知道什么时候用哪个,而不是非此即彼。
还有个小技巧值得分享:PXE 环境搭好后,我把整个配置目录(TFTP 根目录、HTTP 安装源、ks 文件)打了个包备份,换机器或者环境重装时直接解压恢复,省得重新配一遍。这个备份大概几个 G(主要是安装源),放移动硬盘里,随用随取。搭一次管很久,这才是 PXE 固定成本能被摊薄的关键——环境是可复用的资产,不是一次性消耗。
7. 写在最后:一点个人体会
这套对比做完,我最大的感受不是“PXE 比 U 盘快多少”,而是装机这件事的性质变了。以前装机是体力活,人得守着,装完一批人累得不行;现在装机是配置活,前期把 ks 文件调好,后面上电就走人,人可以去干真正需要脑子的活。这个转变对做运维的人来说,价值不在省下的那几个小时,而在于把你从重复劳动里解放出来。
当然,PXE 也不是没有学习成本,第一次搭的时候我踩的坑一点不少,TFTP 超时、ks 语法错、主机名冲突,每个都折腾过。但这些坑踩一次就记住了,环境搭好后可以反复用。相比之下,U 盘装机的“坑”是每次都在重复——每次都要改 BIOS、每次都要手输参数、每次都有输错的风险。从这个角度看,PXE 的一次性学习投入,换来的是长期的省心和一致。
如果你现在手里正好有一批机器要装,我的建议是:先数一下数量,超过十五台,花半天把 PXE 搭起来,后面会感谢自己;不到十台,U 盘插上就干,别为了工具而工具。工具是为人服务的,搞清楚自己的场景,比盲目追新技术重要得多。