
机房里刚到了一批新机器四十二台裸机堆在机架上网线一根没接硬盘全空。上一次遇到这种场面我是一台一台插 U 盘、点下一步、选时区、划分区折腾了整整两天中间还因为手抖把两台机器的分区格式选错返工重来。所以这次我决定不再干这种体力活直接把 Cobbler 拉出来用。Cobbler 是一套裸机批量装机服务它把 DHCP、TFTP、HTTP、DNS、Kickstart 这些原本要手工拼接的环节打包成一套对象化的管理接口让你用几条命令就能定义哪台机器装哪个系统、用什么分区、装完执行什么脚本。它适合手上管着几十上百台物理机、需要反复重装、又不想每次动手的运维同学也适合实验室、教学机房、私有云底座这类需要快速交付大量同构机器的场景。这篇东西我把从装包到第一次成功 PXE 引导的全过程拆开讲包括我踩过的坑和最后沉淀下来的配置模板。1. 批量装机的老麻烦Cobbler 能替你扛下什么1.1 从四十二台裸机说起先把场景摆清楚。手上这批机器配置完全一致双路 CPU、256G 内存、两块 960G 的企业级 SSD 做系统盘、十二块 4T 机械盘做数据盘网卡是双口万兆。需求也很统一全部装同一个内核版本的 Linux系统盘做 RAID1数据盘做 RAID5装完自动配置内网软件源、注入监控 Agent、写好主机名和 IP。这种完全同构的批量需求恰恰是 Cobbler 最舒服的地带。如果用传统方式做流程是这样的插 U 盘进 BIOS 改启动顺序进安装界面手动选语言时区键盘手动划分区手动选软件包手动设网络等半小时装完再登进去跑一堆配置脚本。四十二台机器就算每台只花四十分钟也是二十八个小时而且人不可能全程不出错。Cobbler 把前面这些步骤全部固化成模板机器只要通电、网线插好、BIOS 里把网络启动打开剩下的事情它自己跑完你只需要回去喝杯咖啡回来批量验收。这里有个关键认知Cobbler 本身不装系统它是个调度中枢和配置生成器。真正干活的还是 PXE 引导加 Kickstart 应答文件这套底层机制Cobbler 的价值在于把散落各处的配置文件统一成数据库里的对象你改一个 profile背后几十个配置文件和目录会被自动重新生成。理解了这一层后面遇到问题你就知道该往哪个方向查。1.2 Cobbler 与其他方案的横向比较装机这件事方案不少我在不同项目里都用过这里做个实在的对比方便你判断自己该不该上 Cobbler。方案上手难度适合规模主要短板手工 U 盘极低1 到 5 台完全不可重复出错率高手搓 PXE 加 Kickstart中等偏高10 到 50 台配置文件散落改一处要动三四个文件Cobbler中等30 到上千台概念多初期调试链路长Ansible 加 PXE中等50 台以上Ansible 只管装完之后的配置管不了引导MAAS中等偏高100 台以上依赖组件重适合大规模标准化集群我自己的判断标准很简单如果你一年之内重装机器的次数超过二十次或者单次重装数量超过十台Cobbler 的投入产出比就划算了。它的学习成本主要集中在前期把 PXE 链路打通那一两天一旦跑通后面每加一台机器就是一条cobbler system add命令的事。另一个容易被忽略的点是 Cobbler 的可审计性。所有装机配置都存在/var/lib/cobbler/config/下的 JSON 文件里谁改了哪个 profile、什么时候改的翻文件时间戳就能看出来。相比之下手搓 PXE 的时候有人偷偷改了一下pxelinux.cfg/default排查半天都找不到人。这个特性在多人协作的运维团队里价值很高。1.3 我的实验环境规划讲实操之前先把我的环境交代清楚你照着复现的时候可以等比缩放。服务端我用的是一台旧的一路服务器Linux 发行版是 Rocky Linux 9IP 规划为192.168.60.10这张网卡兼做 Cobbler 服务、DHCP 服务和 TFTP 服务。为什么要把这几个角色放在一台机器上因为在隔离的装机网段里一台机器就能扛住 DHCP 和 TFTP 的并发机器数量上了三百台再考虑拆分。客户端机器统统接在一台二层交换机上交换机上联到服务端这块网卡整个网段用192.168.60.0/24。DHCP 地址池我规划成192.168.60.100到192.168.60.200正好一百零一个地址够用。为什么预留这么多因为 PXE 引导过程中机器会先用临时地址引导装完之后按 Kickstart 里写死的静态 IP 重新配置网络所以地址池只需要覆盖同时开机但还没装完的机器数量不需要覆盖总数。我这批四十二台机器分批开机每批十台池子留一百个绰绰有余。网关和 DNS 我统一指向192.168.60.1这是一台单独的路由设备。时间同步指向内网的 NTP 服务器因为装机过程中签名校验和日志时间戳都依赖准确的系统时间。域名后缀我用了lab.local纯粹是内部使用不涉及任何外部解析。先把这些参数记在一张纸上后面填配置的时候你会反复用到。2. 安装前的功课系统、网络与依赖梳理2.1 服务端系统选型与硬件底线Cobbler 服务端对系统版本比较挑官方支持的主流是 RHEL 系 8/9 和 Debian 系 11/12。我选 Rocky Linux 9 的原因很实在Cobbler 在 RHEL 系上的打包最完整dnf源里直接就有签名和目录布局都经过大量验证。Debian 系也能装但部分依赖包的版本需要手动对齐早期版本还有 Python 版本冲突的坑新手不建议从那边起步。硬件底线其实很低。Cobbler 自己几乎不吃 CPU 和内存真正占资源的是它托管的安装镜像和软件包仓库。我给它留了 4 核 CPU、8G 内存、200G 系统盘另外挂了一块 2T 的独立盘专门放镜像和仓库。为什么要把镜像单独放一块盘因为导入一个完整的发行版 ISO 展开后大概 8 到 12G如果你还要托管多个发行版加多个软件仓库系统盘很容易被撑爆/var/www/cobbler一满整个服务就写不进去了。网络方面有一张千兆以上的网卡是必须的。为什么强调带宽装机的数据流全是服务端往外发一个 8G 的镜像被十台机器同时拉取就是 80G 的流量千兆网卡跑到 100MB/s 出头十台机器同时跑就得排队装一台的时间会被拉长到让人怀疑人生。如果有条件上万兆体验会舒服很多尤其是导入镜像和同步仓库的时候。2.2 网络规划DHCP 段、TFTP 与 HTTP 三件事Cobbler 的 PXE 链路本质上是三个协议各管一段TFTP 负责把引导程序送到客户端DHCP 负责告诉客户端去哪儿找引导程序HTTP 负责在系统真正开始安装后把内核、initrd 和 Kickstart 文件递过去。任何一环断了机器就卡在黑屏或者 No boot filename received 这类提示上。这里有个非常容易踩的坑你的装机网段里绝对不能有第二个 DHCP 服务在跑。我见过最典型的情况是机房上联的路由器自带 DHCP客户端一开机会同时收到两个 OFFER谁的响应先到就听谁的结果就是十台机器里随机有三四台拿不到正确的引导信息。部署前一定要确认装机网段是隔离的二层环境或者把上游设备的 DHCP 关掉。TFTP 的配置也有讲究。默认的块大小是 512 字节传输一个 50M 的内核镜像会慢得让人抓狂。可以在 DHCP 的选项里加上option tftp-server-name和调整 TFTP 的块大小参数来加速但要注意不是所有网卡的 PXE 固件都支持大块传输老网卡可能会因为协议不兼容直接失败。我的做法是先按默认参数跑通链路确认能装了再逐步调优不要一开始就把参数拉到极限。HTTP 这段相对简单Cobbler 自己会启动一个基于 Apache 或者它自带 Web 服务的 HTTP 端点默认监听 80 端口。需要注意的是这个 80 端口同时承担了 Web 管理界面和安装文件分发的职责如果你在同一台机器上还跑了别的 Web 服务端口冲突就来了趁早改掉或者干脆别装。2.3 防火墙端口、SELinux 与时间同步端口这一块我列一张表照着开就行别偷懒直接关防火墙后期要过安全审计的时候你会后悔。协议端口用途UDP67、68DHCP 服务端与客户端UDP69TFTP 引导文件传输TCP80HTTP 安装源与 Kickstart 分发TCP443Web 管理界面 HTTPSTCP25151Cobbler 自身的 API 通信Rocky Linux 9 上开端口用firewall-cmd开完之后一定要加--permanent再--reload只跑一次不写永久规则的话重启就全没了我为此白排查过一次。SELinux 这块建议先设成 permissive 模式跑通而不是直接关掉。原因是装完之后你还要在 enforcing 模式下长期运行如果一开始就 disabled后面切回来会冒出一堆权限问题不如一开始就用 permissive把audit.log里的拒绝记录当成排查线索。时间同步这个细节经常被忽略。Cobbler 生成配置、签名校验、日志时间戳都依赖系统时间如果服务端时间和客户端差了超过一定范围Kickstart 里的某些校验环节会直接失败。我的做法是在服务端配好 chrony 指向内网 NTP然后在 Kickstart 模板里也带上时间同步配置让客户端装完自动对齐。2.4 依赖安装依赖这块我把 Rocky 9 上的完整命令贴出来你可以直接抄。dnf install -y epel-release dnf install -y cobbler cobbler-web dhcp-server tftp-server xinetd pykickstart dnf install -y httpd rsync bind bind-utils syslinux syslinux-tftpboot systemctl enable --now cobblerd httpd tftp这里解释几个容易困惑的地方。cobbler-web是 Web 管理界面可选装但装上有好处排查配置的时候图形界面能一眼看到对象关系。pykickstart是 Kickstart 语法校验工具装它是因为 Cobbler 在生成应答文件时会调用它做校验缺了会报错。syslinux和syslinux-tftpboot提供 PXE 引导文件这两个包在不同版本的仓库里名字可能略有差异找不到的时候用dnf provides */pxelinux.0反查一下。装完之后先别急着改配置跑一下systemctl status cobblerd看服务起没起来。这时候它多半会报一些配置缺失的警告属于正常现象因为我们还没填基础参数。记住这个顺序先装包再看服务状态再改配置再看状态。瞎改配置之前不知道服务本身有没有问题会让排查变得很混乱。3. Cobbler 服务端安装与初始化调教3.1 三种安装方式与版本选择Cobbler 的安装方式主要有三种我把它们的适用场景说清楚。第一种是发行版官方仓库直接装也就是上面那条dnf install cobbler。这种最省事版本通常是 3.3 或 3.4配置文件格式已经是 YAML 了跟官方文档基本对得上。新手强烈建议走这条路不要一上来就折腾源码编译。第二种是 EPEL 仓库装版本可能比官方仓库新或者旧取决于你的发行版。好处是更新及时坏处是依赖版本有时候会和系统自带的冲突。如果你的发行版官方仓库里已经有 cobbler就没必要绕这一圈。第三种是从源码或者项目提供的仓库装能拿到最新的特性比如对某些新发行版的签名支持、改进的 Web 界面。代价是升级要靠自己维护出问题的时候没有包管理器的依赖保护。我自己的选择是官方仓库版本。原因很简单这套东西是要长期无人值守跑在机房里的比起新特性我更在意依赖关系的确定性。装机服务一旦挂了新机器就全部交付不了这个风险不值得为了某个新功能去冒。版本确认用cobbler --version顺便记下来后面查文档的时候要对得上版本号。3.2 关键配置项逐条拆解Cobbler 3.x 的主配置文件是/etc/cobbler/settings.yaml这个文件是 YAML 格式缩进敏感改之前先备份一份。下面这几个参数是必改的我逐条说为什么。server: 192.168.60.10 next_server: 192.168.60.10 manage_dhcp: 1 manage_tftp: 1 manage_dns: 0 pxe_just_once: 1 default_password_crypted: $1$随机盐$加密后的密码串 allow_duplicate_macs: falseserver是客户端在安装阶段访问 HTTP 源时用的地址填服务端 IP。next_server是 DHCP 告诉客户端的 TFTP 服务器地址通常和 server 相同但在多网卡或者有 NAT 的环境里可能不一样这里必须填客户端能直接访问到的那个地址填错了客户端就会一直卡在获取引导文件。manage_dhcp设成 1 表示让 Cobbler 接管 DHCP 配置的生成它会根据模板渲染出 dhcpd.conf这个开关打开后你就不要手动改/etc/dhcp/dhcpd.conf了改了也会被覆盖。pxe_just_once这个参数值得单独讲。设成 1 之后客户端完成一次安装会自动把 PXE 引导标记取消避免机器装完后重启又进引导循环。我第一年用 Cobbler 的时候没开这个开关结果有一台机器装完重启三次又回到安装界面运维小哥以为镜像坏了查了一下午。这个参数在 3.x 里默认值可能不同务必显式写上。default_password_crypted是默认 root 密码的加密串生成方式如下openssl passwd -1 -salt $(openssl rand -base64 6) YourPassword把输出原样填进配置。为什么要用加密串而不是明文因为 Kickstart 文件最终是通过 HTTP 明文传输的如果里面写明文密码同网段抓包就能拿到这在安全审计里是硬伤。3.3 cobbler check 的每一条告警怎么消配置改完跑cobbler check你会看到一串告警这是 Cobbler 最贴心的设计它把常见问题都替你检查了。我把最常出现的几条列出来讲清楚每条背后的原因。告警内容原因处理方式server and next_server 字段未配置默认值还是 localhost改成服务端实际 IPdefault_password_crypted 未设置默认密码是占位符用 openssl 生成后填入缺少引导加载程序文件tftpboot 目录下没有 pxelinux.0跑cobbler mkloaders或从 syslinux 目录复制dhcpd 未安装或未启动manage_dhcp 打开但服务没跑安装 dhcp-server 并 enable需要 rsync 支持某些发行版导入依赖 rsync安装 rsync 包SELinux 可能阻止访问permissive 之外的策略先切 permissive 观察新版 Cobbler 获取引导文件的方式变了早期版本用cobbler get-loaders从一个固定的在线源拉取新版改成了cobbler mkloaders直接从本地已安装的 syslinux 包里生成。如果你的环境不能访问外网get-loaders会直接卡住然后超时这是很多人第一次装就卡住的根本原因。用mkloaders就不依赖网络我强烈推荐这条路径。cobbler check每修一条就重跑一次直到只剩一两条无害的提示为止。这里的心态要摆正不要追求零告警有些告警是针对你没用到的功能比如 DNS 管理发出的只要你不用那个功能忽略它完全没问题。3.4 cobbler sync 干了什么cobbler check是自检cobbler sync是真正把配置落到磁盘上并重启相关服务。这个命令值得单独讲清楚因为不理解它的行为你会经常遇到我明明改了配置怎么不生效的问题。执行cobbler sync的时候它会做这几件事根据模板渲染出 dhcpd.conf 并放到/etc/dhcp/然后重启 dhcpd把引导文件、内核、initrd 同步到/var/lib/tftpboot/下对应的目录生成pxelinux.cfg/default引导菜单如果有 DNS 管理还会生成 named 的 zone 文件最后把 HTTP 服务下的安装树索引刷新一遍。整个过程是幂等的重复执行不会出问题所以你可以放心地改一次配置 sync 一次。理解它的工作原理对排查特别重要。比如有次我改了 Kickstart 模板但装机还是老样子原因就是没 sync客户端拉到的是旧的 HTTP 路径缓存。还有次 DHCP 不生效是因为 dhcpd 重启失败了cobbler sync的输出里其实有报错但我没仔细看。所以养成习惯每次 sync 之后把它的输出从头到尾看一遍有红色报错就立刻处理别攒着。4. 发行版导入与 Profile 定制把装机变成选择题4.1 distro、profile、system 三层对象模型Cobbler 最核心的设计就是这三个对象理解它们的关系是后面所有操作的基础。distro是发行版对应一份内核加 initrd 加安装树的组合代表一套可以安装的系统。profile是配置档它建立在某个 distro 之上附加了 Kickstart 文件、软件源、内核参数代表一种安装方式。system是具体机器它绑定某个 profile再叠加自己的 MAC、IP、主机名代表这一台特定的机器。用生活化的比方distro 是菜谱里的食材清单profile 是这道菜怎么做system 是今天中午给我做一份。一台机器引导时DHCP 根据 MAC 找到对应的 systemsystem 指向 profileprofile 指向 distro链路就串起来了。如果 MAC 没匹配到 systemCobbler 会退回到默认 profile这是很多配置了 system 但没生效问题的根源。这三个对象都是可以继承和覆盖的。比如你可以在 profile 里定义一组内核参数在具体 system 上再加一条inst.vnc开启远程安装覆盖行为是叠加而不是替换。搞懂这个继承关系你就能用很少的模板覆盖很多差异化需求。4.2 import 导入 ISO 的完整过程导入发行版就是把 ISO 或者安装树塞进 Cobbler让它认识这个发行版。我以导入一个通用 Linux 发行版为例把完整流程走一遍。先把 ISO 挂载到本地目录mkdir -p /mnt/iso mount -o loop,ro /data/iso/linux-server-dvd.iso /mnt/iso然后执行导入cobbler import --path/mnt/iso --namelinux-server-9 --archx86_64这里有个参数计算和选择的细节。--name我建议带上版本号和架构因为后面你可能会导入多个版本名字里不带版本几个月后自己都分不清哪个是哪个。导入过程会复制大约 8 到 12G 的数据机器慢的话要等几分钟期间不要中断中断了会留下半截目录得手动清理/var/www/cobbler/distro_mirror/。导入完成后用cobbler distro list和cobbler profile list确认。正常情况下一次 import 会自动生成一个 distro 和一个同名的 profileprofile 用的是默认的 Kickstart 模板。这时候你已经可以直接用这个默认 profile 装机了只不过用的是通用配置分区和软件包都不是你想要的。导入过程中容易卡住的一个点是签名匹配。Cobbler 会根据安装树里的文件特征判断这是什么发行版判断不出来就报unknown distribution。遇到这种情况先跑cobbler signature update更新特征库如果还是不行可能就是你的发行版太新或者太偏需要手动指定--breed参数告诉它这是哪一类。4.3 Kickstart 模板改造默认模板只能保证装得上去离装得符合要求还差得远。我的做法是复制一份默认模板出来改。cp /var/lib/cobbler/kickstarts/sample_end.ks /var/lib/cobbler/kickstarts/lab-server.ks然后编辑这个文件重点改这几块。分区方案我用的是固定写法因为所有机器硬件一致没必要用自动分区。系统盘做 RAID1 的写法大致是把两块 SSD 分别指定为 RAID 成员然后定义根分区和 boot 分区落在 RAID1 设备上。数据盘做 RAID5 需要至少三块盘十二块盘可以做成一个 RAID5 加一个热备。这里要注意 RAID 的元数据版本和 chunk 大小机械盘做 RAID5 我用 512K 的 chunkSSD 做 RAID1 用默认值就可以具体参数要结合你的阵列卡或者软件 RAID 的实际能力来定。网络配置我全部写死静态地址因为装机的机器 IP 是规划好的。模板里用变量占位network --bootprotostatic --ip$ip_address --netmask255.255.255.0 --gateway192.168.60.1 --hostname$hostname --nameserver192.168.60.1这些变量会从 system 对象里取值这就是为什么前面强调要把 system 对象的信息填全。如果 system 里没填 IP这里就会渲染成空值装完网络直接不通。%post段是最能体现功夫的地方。我把内网软件源配置、监控 Agent 安装、SSH 密钥注入、基础安全加固脚本全塞在这里。写法上要把脚本内容先拉下来再执行而不是直接把一大段脚本写在 Kickstart 里因为 Kickstart 的语法校验对特殊字符比较敏感写在文件里更容易维护。4.4 repo 与 snippet 的复用当你有多个 profile 的时候重复的配置片段就该抽出来。Cobbler 提供了 snippet 机制可以把一段 Kickstart 片段单独存成文件在多个模板里用$SNIPPET(名字)引用。我把配置内网软件源和安装基础工具包这两段抽成了 snippet。好处是多台机器、多个发行版的模板可以共用改一处全部生效。当你的内网源地址变了只需要改一个 snippet 文件不用挨个模板去搜替换这个维护成本的差别在环境多了之后非常明显。repo 对象则是用来托管软件仓库的。比如你有一个内网的包仓库可以cobbler repo add把它注册进来然后在 profile 里引用。这样客户端安装过程中就能直接从内网拉包速度和可控性都比走外部源好得多。注意 repo 的镜像同步会用 rsync第一次同步数据量大的时候要留足磁盘和时间。5. 全流程实战从按下 PXE 到远程登录5.1 DHCP 接管与 PXE 引导链路配置 DHCP 模板是打通链路的关键一步。Cobbler 的 DHCP 模板在/etc/cobbler/dhcp.template你需要根据实际网段改这几处subnet 192.168.60.0 netmask 255.255.255.0 { option routers 192.168.60.1; option domain-name-servers 192.168.60.1; option subnet-mask 255.255.255.0; range dynamic-bootp 192.168.60.100 192.168.60.200; filename pxelinux.0; next-server $next_server; }这里最容易出错的是$next_server这个变量。它是 Cobbler 在渲染模板时替换的值来自settings.yaml里的next_server。如果你在模板里直接写死了 IP 而没有用变量那就绕过了 Cobbler 的管理两者不一致的时候会很难查。我的建议是模板里一律用变量把实际值统一放在 settings 里维护。filename这一行指定客户端加载哪个引导程序。传统 BIOS 机器用pxelinux.0UEFI 机器要用grubx64.efi或者shimx64.efi。如果你的机器混着新旧两种固件就必须在 DHCP 里做条件判断按客户端的架构声明返回不同的 filename。我这次的机器全是 UEFI所以直接配 UEFI 的路径如果你的环境混合这块要额外处理否则老机器会引导失败。改完模板跑cobbler sync然后确认 dhcpd 起来了。用ss -ulnp | grep 67看端口有没有监听用journalctl -u dhcpd -f跟踪日志。客户端开机进网络引导之后日志里会出现 DISCOVER、OFFER、REQUEST、ACK 四个阶段的记录看到 ACK 说明地址分配成功接下来就是 TFTP 拉引导文件了。5.2 添加 system 对象与 MAC 绑定机器第一次开机的时候我还不知道它的 MAC 地址这时候有两个做法。一是先在交换机或者服务器的 DHCP 日志里看客户端请求的 MAC二是直接让机器用默认 profile 装装完再登记。我倾向前者因为绑定 MAC 之后能精确控制每台机器的 IP 和主机名装完直接就能用。拿到 MAC 之后添加 system 对象的命令长这样cobbler system add --namenode01 \ --profilelinux-server-9-x86_64 \ --mac00:11:22:33:44:55 \ --ip-address192.168.60.101 \ --hostnamenode01.lab.local \ --static1 \ --netmask255.255.255.0 \ --gateway192.168.60.1 \ --dns-namenode01.lab.local这里每一个参数都有讲究。--static1告诉 Cobbler 这台机器用静态地址Kickstart 渲染的时候会走静态那段逻辑。--dns-name是给系统内部记录用的如果开了 DNS 管理它会自动生成正向解析记录。--mac的格式必须是冒号分隔的小写十六进制大写或者横杠分隔在某些版本上匹配不上我因为这个小写问题排查过一次。批量添加的时候不要手敲四十二条命令用脚本生成再执行。我一般是从一份 CSV 表格里读 MAC 和 IP 规划用 shell 循环拼出命令。这里提醒一句cobbler system add之后必须cobbler sync才生效批量添加完最后统一 sync 一次就行不用每加一台 sync 一次。5.3 验证、抓包与日志定位链路跑通之后验证是有方法的不要靠猜。我在客户端开机之后会在服务端同时开三个窗口一个tail -f /var/log/messages看 DHCP 相关日志一个tail -f /var/log/cobbler/cobbler.log看 Cobbler 自身的处理记录一个tcpdump -i 网卡 -n port 69看 TFTP 有没有实际传输。这三个窗口的组合能快速定位问题出在哪一段。如果 DHCP 日志里连 DISCOVER 都没有说明客户端的网络启动没开或者网线有问题。如果有 DISCOVER 但没有 ACK说明地址池空了或者配置有误。如果 DHCP 走完了但 TFTP 没有流量说明 filename 或者 next_server 配错了。如果 TFTP 有流量但客户端报错多半是引导文件本身不对比如 BIOS 机器拿到了 UEFI 的文件。装完之后Cobbler 的日志还会记录这台机器什么时候开始装、用的哪个 profile。翻/var/log/cobbler/下的日志是排查这台机器为什么和别人装得不一样的第一手材料。养成把日志路径记在脑子里的习惯比到处问人快得多。5.4 koan 重装与批量下发机器已经装好系统在后面跑着现在需要重装怎么办重新开机进 PXE 太麻烦Cobbler 提供了 koan 工具可以在系统内部直接触发重装。koan --server192.168.60.10 --systemnode01 --replace-self这条命令会让客户端拉取对应的引导文件然后重启进入安装流程。--replace-self表示替换当前系统自己。这个机制在需要把一台机器从 A 系统换成 B 系统的时候特别有用不用跑到机房插 U 盘。批量场景下可以用 Ansible 或者简单的 SSH 循环去推这条命令实现几十台机器的统一重装。这里有个安全提醒--replace-self会直接覆盖当前系统执行前一定要确认 IP 规划、主机名、数据盘挂载策略都是对的尤其是数据盘如果没在 Kickstart 里排除重装的时候可能被清空。我的做法是在 Kickstart 的分区段里把数据盘明确排除只动系统盘这样重装不影响数据。6. 踩过的坑与排查速查表6.1 常见问题速查表装机这活儿出问题是常态我把这些年积累的高频问题整理成一张表遇到的时候先查表。现象可能原因定位方法处理客户端提示 No boot filename receivedDHCP 下发参数缺失看 dhcpd 日志和抓包检查 filename 和 next_server卡在 TFTP 传输不动引导文件缺失或权限不对看 TFTP 日志和端口流量重跑 mkloaders 并检查目录权限装机界面反复出现pxe_just_once 未开启查 settings.yaml设为 1 并 sync装完网络不通system 对象 IP 未填或静态标记缺失检查 system report补全参数并 sync拉包很慢或失败软件源指向了外部地址看 Kickstart 渲染结果换成内网 repo改模板不生效没有执行 sync对比渲染后文件执行 cobbler sync机器装到一半失败磁盘命名和模板不匹配看安装日志用磁盘标识而非固定设备名6.2 五个独家避坑技巧第一个技巧是磁盘设备名不要写死成/dev/sda这种。不同批次的机器、不同的阵列卡、甚至固件版本不同磁盘枚举顺序都可能变。我现在的做法是用/dev/disk/by-id/或者 RAID 控制器给出的标识来指定磁盘虽然模板看起来复杂一点但换一批硬件不用改模板。这个教训来自一次换供应商之后新机器的系统盘变成了/dev/sdb导致 Kickstart 分区失败。第二个技巧是给装机日志留够空间。大批量装机的时候日志量很大/var/log如果和系统盘在同一个分区很容易被写满写满之后服务就开始各种诡异报错。我把日志目录单独挂了一个 20G 的分区并且配了 logrotate避免历史日志把空间吃光。第三个技巧是在正式装机之前先用一台测试机把全流程跑三遍。第一遍验证引导链路第二遍验证分区和软件包第三遍验证 post 脚本。为什么是三次而不是一次因为这三类问题的排查思路完全不同分开验证能让你精确知道问题出在哪一层。三遍都过之后再批量跑返工的风险大大降低。第四个技巧是给 Kickstart 里的关键步骤加日志输出。%post段里的脚本我习惯每执行一步就往一个固定文件里写一行带时间戳的记录装完之后登进去看这个文件一眼就知道哪个环节没跑成。没有日志的装机脚本排查起来跟开盲盒没区别。第五个技巧是留一份最小可用配置的备份。Cobbler 的整套配置集中在/etc/cobbler/和/var/lib/cobbler/两个目录我会定期把这两个目录打包备份到另一台机器上。为什么强调这个因为一旦服务端这台机器挂了重建 Cobbler 的配置是很费时间的而且有些参数是当时调试出来的记不住。有备份的话新机器装好系统、还原这两个目录、导入镜像半小时就能恢复服务。6.3 服务端日常维护与后续扩展跑起来之后日常维护其实不多但有几点要定期做。第一是定期跑cobbler check有时候系统更新会改变某些路径或者依赖提前发现比装机当天发现好。第二是定期清理不再使用的 distro 和 profilecobbler distro remove的时候注意是否要一并删除镜像文件命名不对可能会留下大量废弃目录占着磁盘。第三是注意 Web 服务日志的轮转装机高峰期访问量大日志涨得很快。后续如果要扩展方向有几个。一是接入自动化流程把 Cobbler 的对象管理封成 API 调用新机器入库的时候自动创建 system 对象实现真正的零手工。二是把装机完成后的配置管理交给专门的工具让 Cobbler 只负责把系统装起来装完之后的软件配置、服务编排交给上层工具处理职责更清晰。三是做装机结果的可观测把每次装机的结果汇总到一个面板上哪些成功哪些失败一目了然而不是靠人一台台去登。我自己的体会是Cobbler 这种工具的价值不在于它多先进而在于它把一件重复度极高的事情变得可控。第一次调通链路那一两天是有点折磨尤其是 DHCP 和 TFTP 那几段一旦配错报错信息又很含糊。但只要把主流程跑通一次并且把配置备份好、把日志看明白后面几十上百台机器就是批处理的事。真正花时间的从来不是装机本身而是那些没被记录下来的隐性配置。