Kickstart无人值守实战:从配置文件到PXE批量装机的完整指南
发布时间:2026/10/24 0:55:02 锦皓数字建站

干运维的人都有体会批量装系统是最磨人的活之一。早期我经历过的场景是这样的几十台裸机一台一台塞光盘、点鼠标选语言、分区、设密码、等进度条重复几十遍。中间稍有分神分区选错了、时区选差了回头还得重来。后来接触到Kickstart才算把这件脏活彻底解放出来——把安装过程中所有需要人工点击确认的步骤全部预先写进一个配置文件里安装程序自动读取、自动执行全程无人值守十几台机器的系统部署基本就是从开机到重启一气呵成。这篇文章想跟大家聊的正是Linux环境下的无人值守安装脚本Kickstart的完整玩法。内容不光讲配置文件长什么样更会拆解它是怎么生效的、实际生产环境怎么配合网络装机来用、遇到问题怎么排查。不管你是刚入行的系统管理员还是已经在维护几十台服务器的老运维这套东西都能直接落地上手。1. Kickstart解决的是什么问题——批量装机的痛点和核心原理1.1 手工安装最大的成本不是等而是“重复决策”一台机器手动装Linux单看时间不算长半小时到四十分钟能跑完。但如果你一个月要装二十台、五十台呢麻烦的不是等进度条而是那十几分钟密集的交互决策语言选什么、键盘布局用什么、磁盘怎么分、swap给多大、root密码设什么、软件包选哪批、时区是哪个、安装源从哪来。每一项都要人盯着每一项出错都可能让你前功尽弃。Kickstart的思路很直接把安装程序需要问的所有问题预先整理成一个纯文本配置文件。安装时通过引导参数告诉安装器“读这个文件”安装器就不再用交互界面问你问题而是直接从文件里拿答案。这个思路其实跟日常生活中的“模板思维”一模一样。你填过在线表单吧每次填同样的姓名、地址、联系方式很烦对吧。Kickstart相当于做了一份自动填表脚本表单来了程序自己把答案填好、点提交。你唯一的任务是确保模板里的内容是准确的。1.2 Kickstart工作机制不是安装器的一部分而是安装器的“答题卡”很多初学者会误以为Kickstart是一个单独的工具或一个安装程序其实不是。它本质上是一个配置文件格式是纯文本的服务对象是Red Hat系的安装器Anaconda。流程是这样的机器从启动介质引导加载内核和初始initrd镜像此时引导程序传参里带了类似kshttp://192.168.1.10/ks.cfg的选项。Anaconda在初始化阶段读到这个参数就会通过网络拉取这个文件然后把这个文件里的配置逐条解析成安装动作。文件里写了分区它就自动分区写了时区它就自动设置时间写了密码它就直接写入。整个过程没有任何交互界面出现装完自动重启。所以Kickstart本身不参与安装它更像一份说明书Anaconda是照着说明书干活的工人。1.3 Kickstart配置文件的结构三段式的清晰布局Kickstart文件的主干由三大部分组成理解了这个结构后面手写就不会乱。命令段 %packages ... %end %pre ... %end %post ... %end命令段是必选的放的是最基础的系统配置指令包括安装源、语言、键盘、网络、分区、引导装载程序、root密码等。%packages段指定要安装哪些软件包。%pre和%post段分别是在安装开始前和系统安装完成后执行的脚本用于做定制化处理。还有一类可选段比如%addon com_redhat_kpatch、%anaconda某些特定发行版或特定需求才会用到。日常使用中绝大多数人只需要掌握命令段、%packages段和%post段就够了。2. 配置文件从哪来——三种获取方式各有适用场景2.1 系统自带样板root家目录的anaconda-ks.cfg如果你手头已经有一台装好的Linux服务器进到root用户家目录会发现一个叫anaconda-ks.cfg的文件。这个文件就是当初安装这台系统时Anaconda根据你手动选择的选项生成的Kickstart文件。这份文件完全可以拿来当作新机器的安装配置模板。优点是生成真实、跟当前系统状态完全一致缺点是里面内容有冗余而且如果你当初很多选项是默认的生成的文件可能不符合你的预期。我在实际项目中经常拿这台机器的配置做底子改几处再上新机器比如把IP改了、把分区调一下速度比自己从头写快很多。2.2 图形化工具配置system-config-kickstart部分发行版可以安装一个叫system-config-kickstart的图形化配置工具界面是表单式的基本配置、软件包、分区等都能用鼠标选。我个人的评价是适合完全不想手写文件、只想快速生成一个可用配置的人。但它的界面比较老旧支持的选项跟Anaconda实际版本不一定完全对齐高级选项也不全。我用过几次最后还是回到了手写因为手写虽然要记语法但可控性强太多。2.3 手写最小模板生产环境最推荐的方式生产环境我最推荐的方式是自己维护一份精练的Kickstart模板需要什么功能往里加。这个模板是经年在多台机器上验证过的风险低、可控性高。我给团队里带的模板通常控制在五十行以内涵盖了安装源、分区、网络、密码、软件包和一段post脚本。这样任何新机器拿过来改几个参数就能用。文件不追求大而全核心是可读、可维护。这个思路跟“代码评审”一个道理——Kickstart也是运维的代码一样要简洁、要写注释、要有版本记录。3. 核心配置项逐段拆解——从命令段到%post的完整语法3.1 命令段基础安装源、语言时区、网络和root密码命令段是Kickstart文件的骨架每个指令一行。先看一段最基本的配置install url --urlhttp://mirror.example.com/centos/7/os/x86_64/ lang en_US.UTF-8 keyboard us timezone Asia/Shanghai --isUtc --nontp network --bootprotodhcp --deviceens33 --onbootyes --ipv6auto rootpw --iscrypted $6$xxx...加密后的哈希 selinux --enforcing firewall --enabled --servicessh services --enabledsshd reboot逐行解释一下install明确告诉安装器这是全新安装而不是升级。配合url、nfs、cdrom、harddrive等参数指定安装源。url --url从HTTP服务器拉取安装树。生产环境最常用HTTP方式因为配置简单、速度快。也支持nfs --server --dir的写法。lang和keyboard设置语言和键盘布局。注意这里的时区设置timezone Asia/Shanghai --isUtc--isUtc表示硬件时钟按UTC处理生产服务器一般建议这样配避免BIOS时钟和系统时区相互干扰。network网络配置。--bootprotodhcp表示用DHCP也可以写成--bootprotostatic --ip192.168.1.10 --netmask255.255.255.0 --gateway192.168.1.1 --nameserver8.8.8.8。--device指定网卡名如果你不确定机器的网卡名可以省略这一项安装器会自动判断。rootpwroot密码。强烈建议用--iscrypted参数传加密后的哈希不要明文写密码。明文密码在配置文件和安装日志里都会出现风险太大。selinux、firewall、services系统安全基线。生产环境我一般开启SELinux--enforcing防火墙只放行ssh。如果你内部网络环境复杂可以按需调整。reboot安装完成后自动重启。加上它会省去最后一步手动点重启的麻烦但也要注意别在测试环境误用容易导致重复装机。可以这么理解命令段就是“全局配置面板”所有跟系统初始状态有关的选项都在这里处理。3.2 分区与引导装载程序最容易写错也最怕写错的部分分区指令是Kickstart中出问题最多的地方写错容易把磁盘数据搞没需要格外谨慎。常用写法分两种自动分区版clearpart --all --initlabel autopart --typelvmclearpart --all --initlabel表示清除磁盘上的所有分区表和已有分区--initlabel是无交互地初始化磁盘标签。autopart让Anaconda自动创建分区方案--typelvm声明用LVM布局。默认情况下它会自动创建/、swap、/home等逻辑卷省事但灵活性低。手写分区版clearpart --all --initlabel part /boot --fstypexfs --size1024 part pv.01 --size1 --grow volgroup vg_root pv.01 logvol / --fstypexfs --namelv_root --vgnamevg_root --size20480 logvol swap --namelv_swap --vgnamevg_root --size4096先说clearpart --all --initlabel如果没有这一行安装器在磁盘已有分区时会停下来问你要不要清理无人值守模式下这就卡住了。所以要么写clearpart要么写ignoredisk总得给磁盘一个交代。part和logvol的写法要重点注意part /boot --size1024这段表示创建一块大小约1GB的/boot分区。--size单位是MB不写--grow就表示固定大小。part pv.01 --size1 --grow表示创建一个LVM物理卷起始给1MB大小并允许扩展到剩余所有空间。这是LVM配置的惯用写法好处是分区大小能随磁盘容量自动调整不需要在配置里写死总大小。volgroup vg_root pv.01把物理卷卷进卷组。logvol /系列为逻辑卷分配空间。手写分区的价值在于你能精确控制每个挂载点的大小。比如某些业务场景/srv或/data需要大空间独立挂载自动分区就做不到。还要注意bootloader指令bootloader --locationmbr --boot-drivesda--locationmbr表示把GRUB引导装载程序安装到主引导记录传统BIOS启动的机器这么写。UEFI启动的机器写法不同需要引导到EFI分区这里不展开实际部署前请务必确认目标机器的启动模式。3.3 %packages段软件包选择的两种组合思路%packages段控制装完系统后都有哪些软件里面有两种写法%packages ^minimal-environment core vim lrzsz -unused-packages %end以开头的是包组比如^minimal-environment是环境组core是核心包组。^符号表示它是环境组定义一个Kickstart文件里只能有一个环境组。不带的是单个软件包名。减号-开头表示从包组里排除某个包。团队里新的机器一般都用最小化环境minimal-environment加上core组这样系统体积小、攻击面小、后续维护干净。需要什么工具再用yum手动装就行避免装上大量用不到的软件包占用磁盘和内存。如果你装的是图形化桌面用途可以写成^graphical-server-environment但不建议生产服务器这么干。3.4 %pre和%post脚本安装前后的个性化处理窗口%pre段在所有安装动作之前执行脚本运行在一个极简环境里可以做磁盘检测、网络探测甚至动态生成分区配置。我举一个实际场景某次项目里需要根据机器磁盘大小决定swap分区是4GB还是8GB%pre里就用lsblk拿到磁盘容量根据条件重新生成一个分区配置片段写入/tmp/partition.cfg然后命令段里用%include /tmp/partition.cfg引用。这种方式让一套Kickstart配置能同时适配不同配置的机器。%post段是在系统安装完成、配置文件已经写入磁盘后执行的运行环境是一个完整的系统此时可以用yum装软件、改配置、创建用户、调整内核参数。这段是实际运用最多的地方可以把本需要装完系统手工做的所有事后操作全部自动化。%post --log/root/kickstart-post.log echo export LANGen_US.UTF-8 /etc/profile.d/env.sh useradd deploy mkdir -p /data echo 192.168.1.20 monitor.example.com /etc/hosts timedatectl set-timezone Asia/Shanghai %end--log参数会把post脚本的输出写到指定文件排查问题的时候非常好用。如果没写这个参数脚本报错信息会丢失出问题很难定位。post脚本默认在chroot环境里执行多数情况下问题不大。如果脚本里有需要访问安装介质或宿主环境的路径要用%post --nochroot但这种情况较少见。3.5 需要特别注意的语法细节有几个Kickstart语法上的细节我踩过坑写出来告诉大家所有命令大小写敏感。install和Install是不同的写错会被当作未知命令跳过或直接报错。时间、密码类参数格式不统一。rootpw密码必须写--iscrypted参数并传入加密哈希格式为$6$salt$hash但早期版本允许--plaintext直接传明文。每改一个版本前先查文档不要依赖记忆。%pre、%post、%packages段必须以%end结束如果漏了Anaconda解析时会报错并中止安装。ks文件里的注释以#开头但%pre、%post内部的脚本里注释符按脚本语言的规则来不能用#通吃。4. 真正跑起来——搭配PXE和HTTP实现从网络引导到全自动安装4.1 整体架构是什么样子的Kickstart文件和安装源都有了但没人想一台台去插光盘引导。生产环境的标准做法是配合PXE进行网络引导。机器开机时网卡里的PXE固件会向DHCP服务器要一个IP地址同时向DHCP要一个“下一阶段引导文件”的位置通常是TFTP服务器上的pxelinux.0。机器接着从TFTP下载引导程序然后按引导配置文件里的指令加载内核和initrd内核启动后Anaconda开始运行此时再传给它ks文件的位置安装程序拉取ks文件全自动往下跑。整个链路PXE引导DHCP TFTP pxelinux.0 ↓ 内核和initrd加载 ↓ Anaconda启动读取ks参数 ↓ 从HTTP拉取ks文件 安装树 ↓ 无人值守安装完成用一句话概括DHCP决定机器从哪里引导TFTP提供引导文件HTTP提供安装内容而Kickstart文件决定整个安装过程如何展开。4.2 DHCP、TFTP、HTTP三个服务的具体配置DHCP服务配置以dnsmasq或dhcpd为例核心要配置的地方是next-server 192.168.1.10; # TFTP服务器地址 filename pxelinux.0; # PXE引导程序文件名如果用的是dnsmasq则dhcp-range192.168.1.100,192.168.1.200,12h dhcp-option66,192.168.1.10 # next-server dhcp-option67,pxelinux.0 # filenameTFTP服务器配置安装tftp-server后将/usr/share/syslinux/pxelinux.0、ldlinux.c32、vmlinuz、initrd.img等文件放到TFTP根目录下。pxelinux.0是PXE引导程序vmlinuz和initrd.img从安装树镜像的isolinux目录里拿。在TFTP根目录创建pxelinux.cfg/default文件default linux label linux kernel vmlinuz append initrdinitrd.img inst.kshttp://192.168.1.10/ks/ks.cfg inst.repohttp://192.168.1.10/centos/7/os/x86_64/ net.ifnames0 biosdevname0 ksdeviceeth0default文件名表示所有未单独配置的机器都使用这个引导配置。如果你希望不同MAC地址的机器执行不同的ks文件在pxelinux.cfg目录下放01-aa-bb-cc-dd-ee-ff这样命名的主机配置文件即可。HTTP服务器配置HTTP服务的角色是存放安装树和Kickstart文件。把ISO镜像挂载到/var/www/html/centos/7/os/x86_64/下再把ks文件放到/var/www/html/ks/目录下一个静态文件服务就完成了。生产环境我一般用Nginx纯静态文件服务简单稳定。如果对性能没有特殊要求用系统自带的httpd也没问题。4.3 引导参数的取舍ks、ksdevice、ip这些参数到底是干什么的引导配置里的append行是打包所有启动参数的地方其中跟Kickstart直接相关的有kshttp://192.168.1.10/ks/ks.cfg告诉Anaconda从哪里读取Kickstart文件。这是无人值守安装的关键参数没有它Anaconda就回到交互模式。ksdeviceeth0指定安装过程中使用哪块网卡来访问网络。机器有多块网卡时如果不指定安装器可能选错网口导致后续找不到安装源。ip192.168.1.10 netmask255.255.255.0 gateway192.168.1.1如果你不希望安装过程依赖DHCP分配IP可以直接在引导参数里把IP配死这样ks文件的网络配置和引导参数网络配置要保持一致。net.ifnames0 biosdevname0关闭网卡的命名规则让网卡按传统的eth0、eth1命名。这个参数看个人习惯如果你已经习惯了新命名规则可以不写。vnc如果机器没有显示器和键盘需要远程图形化安装时可以加vnc vncpasswordxxx参数不过既然用Kickstart通常都用不到了。还有一个容易忽略的点如果引导参数里不写ksAnaconda会在交互界面里以菜单形式问你ks文件在哪那就不叫无人值守了。所以引导参数里ks必须写上。5. 常见问题与排查技巧实录——那些装了几十台机器才会踩到的坑5.1 问题一安装卡在“No root password”或“You must set a root password”现象Kickstart文件里明明写了root密码但安装仍然卡在原地不动。原因最常见的是rootpw指令本身写挂了。比如明文密码在旧版本允许在新版本中默认被拒绝或者--iscrypted参数写错了位置。排查方式看http服务器上的访问日志确认ks文件确实被请求到了再看文件内容rootpw那一行的参数顺序对不对。我遇到过一次问题是加密哈希里的$符号在KoKickstart文件传输过程中被转义导致哈希错误。建议手写加密哈希时务必要复制完整的$6$...字符串。以HTTP方式拉取ks文件时文件内容必须是原样文本不要加上任何编码转换。5.2 问题二%post脚本没执行或执行了但没生效现象系统装完用户没创建成功配置文件没改到位日志也没留下。原因很多情况下是%post段的脚本语法错误或者某个命令依赖网络而当时网络还没就绪。排查方式给%post加--log/root/ks-post.log参数让脚本输出落盘脚本里也要自己加set -e让报错及时暴露。%post --log/root/ks-post.log set -e ... %end我个人习惯是post脚本内先加sleep 10等网络服务稳定后再执行网络相关命令。很多问题是网络设备刚初始化马上拉包容易超时。5.3 问题三PXE引导正常但Anaconda说“Unable to download the kickstart file”现象机器能从PXE启动内核加载后没多久报错说拉不到ks文件。原因HTTP路径写错了、防火墙没放行、或者ks参数里的IP写错了。排查方式先看web服务器访问日志确认有没有收到来自目标机器IP的请求。如果连请求都没有说明网络路径有问题。用浏览器或curl在局域网内试一下确认http://192.168.1.10/ks/ks.cfg能直接访问到。检查HTTP服务器有没有放行端口如果开着firewalld要记得添加规则。确认ks文件权限是644Nginx/apache用户有足够权限读取。5.4 问题四分区相关错误安装器一直提示磁盘信息无法识别现象安装过程在分区步骤中止出现You have not defined a root partition (/), which is required for installation to continue之类的报错。原因分区配置里没有给根分区分配足够空间尤其是手写逻辑卷时/逻辑卷没写--size或者写的是--size1但没写--grow导致创建失败。排查方式检查part pv.01、volgroup vg_root、logvol /这三条指令的归属关系。LVM链路缺一环就不生效。再检查clearpart --all后的磁盘是否被正确识别。我踩过最深的一个坑是服务器磁盘是RAID卡直通系统看到的磁盘设备名不是sda而是sdb但配置文件里--drivesda把这个盘忽略了导致分区全部落空。排查了很久才发现是磁盘设备名的问题。5.5 问题五ks文件下载到了但语法报错看不到具体原因现象Anaconda报错说ks配置文件有错误但屏幕上只显示一行笼统信息细节看不到。排查方式Kickstart文件的报错日志在Anaconda的日志目录里具体文件位置因发行版不同略有差异一般在/var/log/anaconda.log或/tmp/anaconda.log。用SSH或串口拿到日志后再看具体是哪条指令报错。在用HTTP方式部署时我建议先在本地用yum install pykickstart把ksvalidator装上用它检查语法ksvalidator /var/www/html/ks/ks.cfg这个命令会直接报出哪一行有问题省得装机时反复试错。我把ksvalidator作为所有ks文件上线前的强制检查步骤没有通过不允许进生产流程。5.6 常规排错思路总结从网络、文件、语法三个层面入手我排Kickstart问题的经验大概可以框成三步网络层先确认引导阶段机器能拿到IP、能访问HTTP服务器。用tcpdump在服务器端抓包看有没有来自目标机器的HTTP请求最快。文件层确认ks文件路径、权限、内容正确。直接看HTTP访问日志或者用curl模拟拉取。语法层用ksvalidator做静态检查。如果过了静态检查仍报错就去翻Anaconda的详细日志。只要按照这个顺序排查百分之八十的问题都能在十分钟内定位。6. 扩展玩法——Kickstart的更多生产实践6.1 搭配正则脚本实现不同机器不同配置在实际项目中几十台机器可能不完全是同配置的。有的内存大swap就多分点有的业务角色不同软件包组也不一样。这些差异可以通过在%pre阶段写识别逻辑来解决。例如根据MAC地址前缀或主板序列号判断机器角色再向/tmp/role.cfg写入不同配置片段用%include引入%pre if [[ $(dmidecode -s system-serial-number) VMware-1234 ]]; then echo part /data --fstypexfs --size20480 /tmp/extra-part.cfg echo nginx /tmp/extra-packages.cfg else echo part /data --fstypexfs --size10240 /tmp/extra-part.cfg fi %end %include /tmp/extra-part.cfg %packages %include /tmp/extra-packages.cfg %end这种动态生成的思路让一套Kickstart模板可以覆盖多种规格的机器非常实用。6.2 Kickstart的最佳实践配置文件也需要版本管理Kickstart文件本质上是运维代码那么就应该像代码一样管理。我自己维护了一套目录结构每类系统、每个版本单独建目录变更历史用版本管理工具记录。每次上线新机器前先把ks文件跑一遍ksvalidator再检查文件里的密码哈希、分区大小这些高风险项。另外建议在ks文件头部写清注释这套配置最初的适用场景是什么、改过哪些内容、最后更新时间是谁。团队协作时这份注释能节省大量沟通成本。6.3 和其他自动化工具的关系Kickstart并不是唯一的答案Kickstart天然跟PXE搭配用于裸机安装但如果你已有虚拟化平台或者需要更复杂的编排比如装完系统后还要执行配置管理、应用部署那可以把Kickstart当成“基础系统安装阶段”的解决方案后续再接配置管理工具。我所在的团队就是这样做的Kickstart负责把操作系统装好、网络调通、基础工具就位接着由配置管理工具比如Ansible或者Salt任意选一个即可接管负责业务软件部署与持续配置同步。两段分工明确各管一段流程非常清晰。Kickstart负责“生”系统配置管理工具负责“养”系统这个分层思想要比试图用一套工具搞定所有事情靠谱得多。6.4 安全关注点别在Kickstart里留明文敏感信息最后想专门提醒一下安全。Kickstart文件里可能涉及root密码、网络配置、分区信息等敏感内容这些文件如果放在HTTP服务器上要注意访问权限。我在生产环境里会这样做HTTP服务器上ks文件目录设置访问控制只允许部署网段的IP访问密码一律使用加密哈希禁止明文如果ks文件通过外部网络传输建议用更安全的传输通道不过一般内网部署没有这个顾虑定期排查HTTP访问日志看看有没有陌生IP在拉取ks文件。毕竟ks文件一旦泄露等于别人拿到了你所有服务器的初始登录凭据还是要谨慎对待。写在最后我的一些体会Kickstart这套东西定位其实很小它只解决“把操作系统装好”这一件事。但就是这一件事被它理顺之后整个运维的地基就稳了。从最初一台台手动装机到后来一份ks文件配合PXE几十台机器批量搞定这种前后对比带来的震撼是我一直想把这些细节整理成文的原因。如果看完这篇你想从零开始搭建一套无人值守安装环境建议按这个顺序走先手写一份最小Kickstart文件用KVM或VMware虚拟机试装确认它能在纯文本非交互模式下跑通然后再搭DHCPTFTPHTTP把PXE引导弄通最后再慢慢加%post段把个性化定制加进去。每走一步都用ksvalidator和虚拟机测试去验证别直接拿生产机试错。Kickstart的语法并不复杂但它藏了很多细枝末节。你踩过的每一个坑最后都会变成部署脚本里的最佳实践。希望这篇文章能让你少走一些弯路。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。