Kickstart 无人值守装机实战:从镜像源到批量交付

重复装机是最容易被低估的时间黑洞:同样的镜像、同样的分区、同样的软件包,靠人盯着安装界面一步步点,一台要半个多小时,还经常因为漏勾一个包组、时区选错而返工。Kickstart 是 RHEL 系自带的自动化安装机制,一份文本文件把安装器要问的问题全部预先答好,配合本地安装源,一批机器挂上引导介质就可以自己装完。本文以 Rocky Linux 9 为口径,把引导方式、ks.cfg 结构、本地源搭建和装后验证串成一套可直接落地的流程;Ubuntu 22.04 的对应方案是 autoinstall(cloud-init 风格的 YAML),思路相通但文件格式不同,本文不展开。

整体流程:两种引导方式怎么选

Kickstart 安装分两个阶段:先让目标机进入安装环境并拿到 ks.cfg,再让安装器从安装源读软件包。引导方式有两条路线。第一条是 DHCP + PXE 网络引导:目标机网卡 PXE 启动,从 DHCP 拿到地址和下一跳文件,TFTP/HTTP 拉起引导与内核,全自动程度最高,适合机房里几十上百台的规模化交付,代价是要维护 DHCP/PXE 基础设施,还要处理 UEFI 与 Legacy 两种固件的引导文件差异。第二条是直接挂 ISO:把官方 ISO 挂到虚拟光驱(物理机走 iDRAC/iLO 虚拟介质、虚拟机直接挂载),在引导菜单里追加内核参数指向 ks 文件。单台或小批量时这条路线更省事,不用碰网络基础设施。本文以第二条为主线讲解,PXE 场景下 ks 的写法完全一致,差别只在文件怎么送达。

前置条件

  • Rocky Linux 9 官方 ISO 镜像一份,建议同时备好校验和文件并核对 SHA256。
  • 一台提供 HTTP 服务的机器做安装源(可以是任意一台内网 Linux),与目标机网络可达。
  • 目标机的磁盘容量、网卡数量、目标 IP 规划清单(静态地址要在 ks 里写死时尤其重要)。
  • 一份基线要求:分区方案、时区、要装的软件包组、装后要做的初始化动作。

第一步:搭建本地 HTTP 安装源

把 ISO 内容放到 HTTP 服务器上,安装器就能通过仓库方式拉取软件包,比让每台机器直接挂 ISO 更灵活。

mkdir -p /var/www/html/rocky9
mount -o loop Rocky-9.x-x86_64-dvd.iso /mnt/iso
cp -a /mnt/iso/. /var/www/html/rocky9/
systemctl enable --now httpd
curl -I http://192.0.2.10/rocky9/.treeinfo

能取到 .treeinfo 就说明仓库根目录对了。生产环境建议把 ISO 内容放到独立数据盘并做校验,源目录被人改动过一个文件,整批机器都会装到一半报错。

第二步:编写 ks.cfg,逐段拆解

下面是一份服务器场景的最小可用模板,逐段说明关键项的含义和易错点。

#version=RHEL9
text
reboot
lang zh_CN.UTF-8
keyboard us
timezone Asia/Shanghai --utc
rootpw --lock
user --name=ops --groups=wheel --iscrypted --password=<加密后的口令>

repo --name="local" --baseurl=http://192.0.2.10/rocky9/BaseOS
url --url=http://192.0.2.10/rocky9

network --device=ens192 --bootproto=static --ip=192.0.2.21 --netmask=255.255.255.0 \
  --gateway=192.0.2.1 --nameserver=192.0.2.53 --hostname=node-01 --activate

bootloader --location=mbr
clearpart --all --initlabel
part /boot --fstype=xfs --size=1024
part /boot/efi --fstype=efi --size=600
part pv.01 --grow --size=1
volgroup vg0 pv.01
logvol / --vgname=vg0 --name=root --fstype=xfs --size=51200
logvol swap --vgname=vg0 --name=swap --size=8192

%packages
@^minimal-environment
@core
vim-enhanced
%end

%post --log=/root/ks-post.log
systemctl disable --now firewalld
sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
echo "install done: $(date)" > /root/INSTALL_OK
%end

分区段是最容易翻车的部分。clearpart --all 会清掉目标盘全部数据,模板里务必配合 ignoredisk --only-use= 指定安装盘,避免多盘机器误伤数据盘;用 LVM 的好处是装后扩缩容方便,/ 的大小给固定值而不是 --grow,剩余空间留给后续按需划分,运维上更可控。UEFI 机器必须有 /boot/efi 分区,Legacy 机器则不需要,两套模板要分开维护。

网络段每个 network 行对应一块网卡,多网卡时写多行;--activate 保证装机阶段就启用这块网卡,否则安装器拉不到仓库。静态地址模板适合逐台派生(一台一份 ks,只改 IP 与主机名),网段内机器多时也可以 DHCP 分配、装后再用配置管理工具收敛。

软件包段里 @^ 表示环境组、@ 表示包组、裸名字是单个包、减号前缀是排除。原则是装机只给最小集加运维基线包,后续软件交给 Ansible 这类工具,ks 越瘦,装机越快、失败面越小。

%post 段在系统首次启动前、以 chroot 进新系统的方式执行,适合做改配置文件、放 SSH 公钥、打标记文件这类静态动作;它跑的时候网络栈和系统服务并不完整,不要在里面做依赖完整运行环境的动作(比如启动服务验证、拉远程仓库装一堆包),那些应该留给首次启动脚本或配置管理工具。务必加 --log 把日志留下来,装后排查全靠它。

第三步:引导参数指向 ks 文件

把 ks.cfg 同样放到 HTTP 服务器上,ISO 启动到引导菜单时按 Tab(Legacy)或 e(UEFI GRUB)编辑内核参数,追加:

inst.ks=http://192.0.2.10/ks/node-01.cfg inst.repo=http://192.0.2.10/rocky9

inst.ks 是 ks 文件地址,inst.repo 是安装源;模板文件里已经写了 url/repo 时,inst.repo 可以省略,但命令行显式写出更便于同一镜像适配不同源。用 systemd 单元或脚本批量生成「一台一份」的 ks 时,注意文件名与机器一一对应,串台会把 IP 装重。

验证

  • 装机过程全程无人干预,结束后自动重启进入登录界面。
  • 登录后检查 /root/INSTALL_OK 与 /root/ks-post.log 存在且无报错。
  • df -h、lsblk 核对分区与 LVM 尺寸和模板一致;ip a、cat /etc/hostname 核对网络与主机名。
  • rpm -qa | wc -l 与同模板机器对比数量量级一致,关键包(vim 等基线包)在列。

常见问题

分区段报错、安装中途红屏退出。多半是分区指令与实际盘型对不上:UEFI 缺 efi 分区、盘符写错(NVMe 是 nvme0n1 而非 sda)、或 LVM 的 size 总和超过 VG 容量。先在模板机上手动走一遍同方案分区,再把数值落回模板。

提示找不到 ks 文件。先在本机 curl 一下 ks 的 URL 是否可达;再检查引导参数拼写,inst.ks 写成 ks= 是 RHEL 7 时代的老写法,RHEL 9 已不认。还有一种情况是网卡没起来导致安装环境没网络,回到 network 段确认 --activate 与设备名。

装后网卡名与预期不一致。模板里写死的 ens192 在另一种机型上可能是 eno1 或 ens33。跨机型交付时,要么按机型分模板,要么在 ks 中用 MAC 地址绑定网卡(--mac= 参数),不要靠猜名字。

小结

Kickstart 的价值不在「省了点鼠标」,而在于把装机变成一份可审阅、可版本管理、可批量派生的文本资产:ks 模板进 Git,每次变更有记录;装后用 /root/ks-post.log 和验收清单收口。它解决的是「裸机到基线」这一段,后续的软件与配置收敛交给 Ansible 等工具分工完成,边界清楚,整批交付的质量才稳得住。

发表回复

后才能评论