PXE+Kickstart+YUM仓库:批量装机无人值守全流程实战

发布时间:2026/10/5 13:26:10
PXE+Kickstart+YUM仓库:批量装机无人值守全流程实战 如果你干过运维大概率经历过这种场景新到了一批服务器要装几十台系统手边只有U盘和一堆ISO镜像一台一台插着装装完还要手动配置源、更新软件。纯粹靠体力活堆。后来我把YUM仓库部署、PXE远程部署、ks无人值守三样东西串在一起才算真正把装机这件事从“重复劳动”变成“一键触发”。这篇内容不打算讲高深理论就是把完整流程一步步拆开讲清楚为什么要这么配置、哪些参数是不得不注意的坑以及我实际操作里踩过的那些雷。这篇内容更适合两类人一类是刚接手批量装机、被半自动化配置折磨过的新手运维另一类是已经能手动装系统、但想把YUM仓库和PXE引导玩明白的人。内容会覆盖服务端和客户端的完整链路从YUM源搭建到DHCP/TFTP引导再到kickstart文件自动化应答最后讲联调时常见的故障。看完之后哪怕你手头只有一台能跑的服务器和几台支持PXE启动的裸机也能把整套环境搭起来。1. 为什么要搭这套组合思路设计与整体规划1.1 核心需求拆解YUM仓库、PXE远程部署、ks无人值守这三样东西单独看都挺常见但组合在一起才是一套完整的批量装机方案。YUM仓库解决的是“系统装完之后软件从哪来”的问题PXE解决的是“机器怎么通过网络引导启动”的问题ks无人值守解决的是“安装过程中怎么自动应答”的问题。你会发现这三者是一条业务链客户端通电后网卡通过PXE从服务器拉取引导文件进入安装程序然后ks文件告诉anaconda“你该用哪个源、怎么分区、装哪些包”而安装时访问的软件源就是YUM仓库。再往后系统装完重启第一次进入系统后需要yum安装的常用软件也全部来自同一个YUM仓库。所以这套组合既解决装机过程自动化也顺带把后续的软件包管理基础设施搭好了。如果你只用PXE不加ks装到一半还是会跳出分区、手填IP这种交互界面人还是得盯着屏幕。只有加上ks文件才能真正无人值守。这也是很多新手搭PXE时容易忽略的点以为能引导进anaconda就完事了结果每台机器还是得人工点下一步。1.2 网络拓扑与服务规划我实际搭建时的网络规划大概是这样的一台服务器当作“装机服务器”IP固定为192.168.100.10安装CentOS 7作为宿主机。这台服务器上跑三个服务HTTP服务提供YUM仓库和ks文件DHCP服务给客户端分配IP地址TFTP服务提供PXE引导文件。客户端处于同一个二层网络内网卡支持PXE或者通过板载网卡启动。最简单的方式是把服务器接到交换机上客户端也接同一台交换机不要把DHCP部署在别的地方不然会互相干扰。如果你的生产环境已经有DHCP服务器那就需要在现有DHCP配置里加入next-server和filename这两个选项避免起两个DHCP服务冲突。我的习惯是把HTTP和TFTP分开因为HTTP传大文件更稳定TFTP只负责引导阶段的小文件。有些人图省事pxelinux.0后面所有文件都想走TFTP传输这样会把TFTP拖得很慢还容易超时。实际上在进入内核阶段之后vmlinuz和initrd.img下载完成后续安装源就靠HTTP了TFTP只承担引导这一小段。这样设计是有道理的。1.3 三种安装方式的对比在动手之前可以对比一下手动安装、半自动PXE和PXEks无人值守三种方式能更清楚这套组合的价值。安装方式耗时以10台为例人力成本可重复性依赖条件手动U盘/光驱安装每台20-40分钟全程盯屏幕差人工操作容易选错需要物理介质PXE半自动每台15-25分钟每台仍需人工点击一般后续步骤仍需要人需要PXE服务器PXEks无人值守每台10-20分钟可并行启动后不用管高同一套配置可重复使用需要YUM源DHCPTFTPHTTP从表格里能看出来真正的收益在于“可重复性”和“人力成本”。一旦ks文件写好了后面再装同版本系统基本就是开机、插网线、等结果。而且如果你有10台机器同时网络启动也不需要一台一台排队只要网络带宽和地址池足够可以并行安装这个效率提升非常明显。2. YUM仓库部署给后续所有操作打好底子2.1 准备基础目录与HTTP服务YUM仓库是整个链条里最基础的一环也是网络源、ks文件提供方。我先说最简单的实现方式把一个CentOS 7镜像挂载到HTTP目录下再配合createrepo生成repodata。生产环境里也可以用reposync同步外网源但作为起步用本地ISO更可靠速度也最快。先安装必要的软件yum install -y httpd createrepo然后创建存放仓库的目录。我的习惯是/var/www/html/centos/7/下面按照base、extras、updates分开目录方便后续扩展mkdir -p /var/www/html/centos/7/base mkdir -p /var/www/html/centos/7/extras mkdir -p /var/www/html/centos/7/updates接着把ISO挂载到base目录利用镜像里自带的基础包mount -o loop CentOS-7-x86_64-DVD-2009.iso /var/www/html/centos/7/base这里注意如果你把ISO直接挂载到某个目录里面的repodata是镜像自带的一个子集但有时候anaconda在安装时只认这个目录下的安装源所以这个目录结构高概率是能用的。如果你想同步外网源例如同步extrasreposync -p /var/www/html/centos/7/extras --repoidextras这个过程会比较久一般我建议用cron定期做增量更新。不过第一版环境直接把ISO挂载起来作为base仓库就够了后续再做外网源更新。启动httpd并设置开机自启systemctl enable --now httpd systemctl status httpd访问 http://192.168.100.10/centos/7/base/ 如果能列出目录说明HTTP服务正常。2.2 制作仓库元数据如果你只是挂载ISO那目录下本身就有repodata目录理论上不需要重新createrepo。但我仍然建议你执行一遍createrepo一是为了确保元数据完整二是如果你后续添加了RPM包到目录里必须更新repodata才能被yum识别。进入base目录并生成元数据cd /var/www/html/centos/7/base createrepo -v .执行完之后你会看到repodata目录下生成了一堆xml.gz文件。这里的-v参数能显示详细过程方便排查哪些包读取失败。如果目录里已经有旧的repodata重新生成时建议用createrepo --update .这样做的好处是只需要重新扫描变动的RPM包速度会快很多尤其源仓库很大时效果明显。为什么这一步重要因为YUM客户端在解析一个仓库时必须拿到repodata目录里的repomd.xml文件通过这个文件找到组信息和包列表。如果缺了repodata客户端就会报“Could not resolve host”或者“Cannot retrieve repository metadata”之类的错误。我见过很多人搭YUM源时直接把RPM文件拷进去了却没有执行createrepo结果一直失败。2.3 客户端验证与开通防火墙仓库服务端配置完成后要在一台客户端机器上测试。在客户端的/etc/yum.repos.d/目录下创建一个repo文件比如local.repocat /etc/yum.repos.d/local.repo EOF [local] nameLocal YUM Repo baseurlhttp://192.168.100.10/centos/7/base/ enabled1 gpgcheck0 EOF然后执行yum clean all yum makecache看到“metadata cache created”之类的输出说明仓库已经生效。以后客户端安装软件就直接来源这个仓库了。服务端到这里还没完别忘了防火墙和SELinux。CentOS 7默认可能开着firewalld需要放行HTTP端口firewall-cmd --permanent --add-servicehttp firewall-cmd --reloadSELinux也容易让httpd无法读取挂载目录下面的文件。我通常把SELinux设为permissive或直接关闭如果是内网测试环境。如果你不想关闭可以给目录打上正确的etiquetechcon -R -t httpd_sys_content_t /var/www/html/centos/这一步是很多人拿HTTP端口访问正常、但yum下载包始终404的根源之一。目录权限、SELinux标签、暂时防火墙没放行三板斧排查完基本都能解决。3. PXE引导服务让服务器开机自动进安装程序3.1 DHCP服务配置PXE的核心思路是客户端不知道从哪里下载引导文件所以它要先通过DHCP拿到IP地址同时从DHCP报文里取出“谁提供引导文件”和“引导文件名是什么”这两个关键信息。在CentOS 7服务端安装DHCP服务yum install -y dhcp这里有人喜欢用dnsmasq它一个服务同时提供DHCP、DNS、TFTP配置更简单但排错时不如独立服务清晰。我建议第一次搭建还是老老实实用DHCPTFTPHTTP三个独立服务哪里出问题就查哪里不会一锅乱炖。编辑/etc/dhcp/dhcpd.confsubnet 192.168.100.0 netmask 255.255.255.0 { range 192.168.100.100 192.168.100.200; option routers 192.168.100.1; option domain-name-servers 192.168.100.10; default-lease-time 600; max-lease-time 7200; next-server 192.168.100.10; filename pxelinux.0; }这个配置里next-server指定TFTP服务器地址filename指定客户端要下载的引导文件。如果客户端不设置filename它一般会默认请求pxelinux.0但最好显式写出来。启动DHCP服务systemctl enable --now dhcpd注意启动dhcpd之前要确保服务端这台机器自己的IP地址在所属子网内并且网卡没有配置DHCP否则dhcpd很可能启动失败报“Not configured to listen on any interfaces”。3.2 TFTP服务与引导文件放置TFTP服务是PXE引导阶段的核心。安装tftp-serveryum install -y tftp-serverCentOS 7下tftp可以通过xinetd托管也可以直接用socket激活。修改/etc/xinetd.d/tftp把disable改成no然后重启xinetdsystemctl enable --now xinetd或者更省事的方式直接启用tftp.socketsystemctl enable --now tftp.socket默认情况下TFTP根目录是/var/lib/tftpboot。现在需要把PXE引导文件放进去。syslinux包提供pxelinux.0yum install -y syslinux cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/然后从CentOS 7镜像的isolinux目录拷贝内核和initrd文件到tftpboot根目录mkdir -p /var/lib/tftpboot/centos7 cp /var/www/html/centos/7/base/isolinux/vmlinuz /var/lib/tftpboot/centos7/ cp /var/www/html/centos/7/base/isolinux/initrd.img /var/lib/tftpboot/centos7/如果你的TFTP根目录下文件比较多建议单独建一个centos7子目录放引导内核不让根目录太乱。注意TFTP传输是没有认证和加密的文件名路径必须和配置文件里一致大小写也很敏感。3.3 PXE默认菜单配置在/var/lib/tftpboot/pxelinux.cfg/目录下创建default文件。这个文件名本身就有讲究PXE客户端在启动时会按特定顺序查找配置文件先找与MAC地址对应的文件找不到再找IP地址相关的文件最后才找default。你可以先用default这样所有客户端都用同一套菜单。cd /var/lib/tftpboot/pxelinux.cfg cat default EOF default vesamenu.c32 prompt 0 timeout 100 label linux menu label ^1) Install CentOS 7 with ks kernel centos7/vmlinuz append initrdcentos7/initrd.img kshttp://192.168.100.10/ks/ks7.cfg EOF注意我特意把ks参数的地址指向HTTP而不是TFTP因为ks文件通常比pxelinux.0大一些TFTP传大文件效率太低。HTTP传输速度更快而且方便你在服务端查看日志、修改内容。如果你想要一个图形化菜单还需要vesamenu.c32这个文件同样从syslinux或isolinux里拷贝到TFTP根目录。不加也行纯黑底白字的命令行菜单也足够用了。3.4 PXE引导链路原理复盘客户端从开机到进入安装程序其实是这样一个流程BIOS/UEFI中启用网卡启动网卡发DHCP discovery包DHCP服务器返回IP、next-server和filename客户端立刻通过TFTP下载pxelinux.0到内存执行。pxelinux.0读取pxelinux.cfg/default再通过TFTP下载vmlinuz和initrd.img。这两个文件下载完内核就被加载起来了接下来内核通过append参数访问HTTP地址的ks文件然后进入anaconda安装界面。我把这个流程讲清楚是为了方便你去排查问题。例如如果客户端停在“PXE-E53: no boot filename received”说明DHCP没有正确返回filename字段如果下载pxelinux.0之后提示找不到配置文件说明default文件的路径不对或者TFTP服务有问题如果已经进入anaconda但找不到安装源那就是HTTP仓库路径配置有误跟TFTP已经没有关系了。每次排查的时候先在服务端确认三个端口都在监听DHCP使用UDP 67TFTP使用UDP 69HTTP使用TCP 80。这三个缺一不可。防火墙放行命令firewall-cmd --permanent --add-servicedhcp firewall-cmd --permanent --add-servicetftp firewall-cmd --permanent --add-servicehttp firewall-cmd --reload4. ks无人值守文件从“半自动”到“全自动”4.1 Kickstart文件的核心字段ks文件本质上就是一段按固定语法组织的文本anaconda在安装时逐条读取执行。它至少有四个段安装语言、键盘等基础设置安装源指向分区策略软件包选择。还可以加%pre和%post脚本来做安装前后自定义操作。我先给一个最精简的ks示例#versionRHEL7 install url --urlhttp://192.168.100.10/centos/7/base/ lang en_US.UTF-8 keyboard us network --bootprotodhcp rootpw --iscrypted $6$xxxxxxxxx timezone Asia/Shanghai zerombr clearpart --all --initlabel part /boot --fstypexfs --size1024 part / --fstypexfs --grow --size1 bootloader --locationmbr selinux --permissive firewall --disabled %packages --nobase core %end %post --log/root/ks-post.log cat /etc/yum.repos.d/local.repo EOF [local] nameLocal YUM Repo baseurlhttp://192.168.100.10/centos/7/base/ enabled1 gpgcheck0 EOF %end这几个字段的优先级很高url指定了安装源也就是前面搭建的YUM仓库目录clearpart和part负责清空磁盘并重建分区rootpw是加密后的root密码%packages里可以用core这种方式安装包组。注意url的路径必须指向一个包含repodata的目录否则anaconda会直接报“找不到安装源”。有人会问为什么rootpw不是明文因为ks文件可能被局域网内任何机器访问明文密码很容易泄露。可以用下面命令生成加密字符串openssl passwd -1 你要设置的密码把输出替换到ks文件中的rootpw那行前面保留--iscrypted。4.2 快速生成与校验ks文件手写ks文件容易出错我的建议是先在现有系统上参考生成的anaconda-ks.cfg文件。如果你在某个CentOS机器上手动安装过系统/root/anaconda-ks.cfg里就有当前系统安装时的完整应答配置这可以作为模板。把里面的分区、语言、网络配置调整成目标环境就行。另一种方式是安装system-config-kickstart这个图形化工具来生成基础模板虽然CentOS 7仓库里这个工具比较老但生成基础框架还是比纯手写快。写完ks文件之后用ksvalidator校验一下语法yum install -y pykickstart ksvalidator ks7.cfg如果没有输出错误就可以放到HTTP可访问的目录下比如/var/www/html/ks/ks7.cfgmkdir -p /var/www/html/ks cp ks7.cfg /var/www/html/ks/4.3 与PXE菜单联动实现全自动安装这一步其实前面已经做好了就是default菜单里append行的ks参数append initrdcentos7/initrd.img kshttp://192.168.100.10/ks/ks7.cfg当客户端通过PXE引导时内核启动后会把这个URL下载成临时文件然后交给anaconda解析。此时安装过程就完全不再需要人工干预了。除非你在ks文件里设置了交互参数比如auth --enableshadow --passalgosha512之外还有交互行为或者分区选择有误anaconda才会重新回到交互界面。我最早搭PXE时因为ks文件里的url写成了/files而不是/files/导致anaconda报了找不到仓库。这个问题排查了很久后来才发现在HTTP路径中如果末尾缺少反斜杠浏览器可以智能补全但anaconda严格解析不会帮你补。所以这里的坑在于路径的完整性和一致性建议用curl在服务端试一遍curl -I http://192.168.100.10/centos/7/base/确保返回200目录列表正常。4.4 %post脚本的实战应用ks文件里最灵活的是%post段它会在系统安装完成、首次重启前执行。我通常会在里面做三件事配置YUM源安装常用工具调整SSH配置。这样装出来的机器就是“开箱即用”的状态。上面的例子里已经通过%post写了一个YUM源配置文件。如果你想安装常用软件可以继续在%post里加%post --log/root/ks-post.log yum install -y vim wget telnet net-tools systemctl enable sshd %end注意%post脚本执行时目标是新系统的chroot环境所以好多在正常系统里的操作在这里都能用但是没有图形界面、没有交互网络是否可用取决于ks文件里的network配置。我在实际使用中遇到过%post里yum源没生效的情况原因是系统还在chroot状态时resolv.conf可能没有配置DNS。如果ks里配置了静态IP网关这个问题比较少如果完全DHCP偶尔会慢。稳妥一点的做法是在%post里先写死DNSecho nameserver 192.168.100.10 /etc/resolv.conf或者在ks的network字段里带上网关和DNS参数network --bootprotostatic --ip192.168.100.101 --netmask255.255.255.0 --gateway192.168.100.1 --nameserver192.168.100.10这里的参数要按实际环境调整不然装出来的机器网络配置会是错的。5. 全流程联调与问题排查5.1 从客户端开机到安装完成的一次完整巡检所有服务配置完成后我习惯在真正批量装机前先用一台机器完整跑一遍流程。具体过程是这样的客户端插上网线开机进入引导菜单选择“PXE Boot”不同厂商BIOS快捷键不一样常见的有F12、F8、Esc等。屏幕上出现DHCP获取IP的日志然后开始从TFTP下载pxelinux.0。如果一切正常看到一行“Trying to load: pxelinux.cfg/default”接着出现菜单自动选中默认label。之后加载vmlinuz和initrd.img这个过程可能几秒钟。进入anaconda图形或者字符安装界面这时你可以按CtrlShiftF3或F4切换终端看到后台日志确认ks文件被下载、分区已执行、包安装进度。等待安装完成系统自动重启进入GRUB最终登录到shell。在这个流程的每一个节点我都会在服务端同步观察日志。比如查看HTTP访问日志确认ks文件被拉取tail -f /var/log/httpd/access_log看到类似“GET /ks/ks7.cfg”的记录说明客户端确实拿到了ks。如果始终没有这条记录那问题就出在PXE引导阶段或网络链路。5.2 常见问题速查表与避坑指南我把实际部署中容易踩的问题整理成一个速查表方便你直接对照。现象常见原因排查/解决方式客户端卡在PXE-E53DHCP没有返回filename或TFTP服务未启动检查dhcpd.conf是否有next-server和filename检查UDP69端口TFTP下载pxelinux.0后提示找不到配置文件pxelinux.cfg目录不存在或default文件路径错误确认目录在tftp根目录下文件名拼写正确引导成功但anaconda提示找不到安装源ks文件里的url路径不正确或HTTP目录没有repodata用curl验证url是否能访问检查createrepo是否执行安装过程弹出分区或语言选择界面ks文件没有正确被读取确认ksURL可达、ksvalidator校验通过YUM仓库客户端makecache报错防火墙/SELinux/权限问题查看httpd日志检查目录标签放行80端口DHCP服务启动失败IP规划错误或接口未监听子网检查dhcpd.conf中subnet与服务端IP是否一致这里再补充两个独家心得。第一如果客户端数量超过10台TFTP的并发能力可能不够引导阶段会出现部分机器超时。解决办法是不要所有机器同时开机可以分批启动或者把引导阶段的小文件尽量控制在几百KB以内。第二HTTP仓库承载整个安装过程的RPM包传输建议把服务端网卡打成千兆或万兆否则并发安装时带宽会成为瓶颈。5.3 利用系统日志提高排错效率在整个PXEks联调过程中充分利用日志能省下大量时间。TFTP服务虽然默认不记录访问日志但如果你有xinetd管理可以在/etc/xinetd.d/tftp里加上log_type file /var/log/tftp.log这样每一次TFTP请求都会被记下来。不过CentOS 7的tftp.socket方式默认不一定记录可以通过tcpdump抓包确认tcpdump -i eth0 -nn port 69如果看到客户端不断发TFTP Read Request服务端却没有应答基本可以判定是tftp服务状态或防火墙问题。客户端侧如果需要看anaconda日志可以在安装界面切到tty3或tty4屏幕上会滚动输出很多关键信息。比如“Failed to read ks”这种错误几乎一眼就能定位是ks访问失败了。这些细节在实际排错时比Google一顿乱搜更有效。6. 一些额外建议与个人体会这套环境搭过之后我再装机基本都是直接PXE引导、ks自动应答基本不用再碰物理介质了。不过有几点还是想提醒一下。第一YUM仓库不是一套就完事的。系统的base包虽然能通过ISO覆盖但extras和updates源如果长期不更新新装出来的系统会带着一堆旧版本软件存在安全隐患。建议配置cron定期执行reposync同步外网源只同步需要的repo即可否则磁盘占用会很大。比如extras源有时要好几十GB同步之前先看下磁盘剩余空间。第二ks文件应该纳入版本管理。我见过不少人在/var/www/html/ks/下面堆了一堆ks6.cfg、ks7-new.cfg、ks-final.cfg时间一长自己也分不清哪个是最新的。后来我把ks文件统一放在一个目录文件名带日期或版本号改动前先备份这样不管过多久都能追溯。第三如果你要支持UEFI启动上面的BIOS模式pxelinux.0方案是不行的需要额外配置grub2-efi引导文件和EFI菜单。如果你的机器全是传统BIOS那本文这套流程完全够用如果网卡默认UEFI且不支持CSM记得在BIOS设置里打开传统引导模式不然PXE客户端根本不会走到pxelinux.0。最后再分享一个小技巧如果你不想让PXE服务器在整个网络里随意给机器分配IP可以在dhcpd.conf里用host MAC做绑定只给需要装机的机器分配IP并返回引导文件。这样能避免生产环境里一些不该被重装的机器意外进入PXE安装流程。毕竟无人值守意味着只要满足条件机器就真的会自动重装这个风险一定得控制好。