批量部署裸金属时网络PXE常失败?香港服务器如何配合Cloud-Init构建稳定启动流程?

批量部署裸金属时网络PXE常失败?香港服务器如何配合Cloud-Init构建稳定启动流程?

在香港IDC做裸金属大规模上线部署时,PXE自动化装机是常规操作,但我多次遇到 PXE 网络引导过程中出现 TFTP 超时、initrd 卡死、kickstart 渲染失败等问题,尤其在服务器厂商异构、交换网络多跳复杂的环境下更是频繁。为了构建一个更稳定、可恢复且适用于异构服务器环境的启动流程,我最终选择将传统的 PXE + Kickstart 方案升级为 PXE 引导 + Cloud-Init 自动初始化 组合方案,并结合本地 HTTP 镜像仓库、元数据服务及分段 YAML 模板实现高可用部署体系。

这篇文章将从我在香港部署数十台物理机的实践出发,详解如何搭建 Cloud-Init + PXE 的自动化启动系统,并解决 PXE 引导过程中的各种稳定性问题。

一、问题复现:PXE 引导失败的常见场景

在部署过程中,我遇到以下典型的失败模式:

TFTP timeout / Retransmission failed

交换机端口没有开启 fast-forwarding,或中间设备不支持 UDP 大包,导致 TFTP 文件传输失败。

initramfs 获取不到 ks.cfg/kickstart 文件

DNS 不通、HTTP 源未准备好或网络切换后未自动更新路由,initramfs 卡在安装前步骤。

Kickstart 模板参数不适配硬件

相同模板无法同时支持 HPE、Dell 和 Supermicro,不同 RAID 卡、接口名等需要区分处理。

这类问题在传统 kickstart 里难以做动态判断和适配,最终我决定全面切换为 Cloud-Init 驱动自动化配置,并通过元数据服务灵活下发参数。

二、部署架构:PXE + iPXE + Cloud-Init 多层自动化

为了构建一个高可用的自动引导部署体系,我将整个流程拆解为:

  • PXE/iPXE 网络引导阶段:统一内核与initrd加载
  • 预安装阶段:装系统基础镜像(Cloud-Init Ready)
  • 初始化阶段:Cloud-Init 拉取配置并执行初始化流程
  • 后续交付阶段:加入配置管理平台(如 Ansible、SaltStack)

PXE 引导只是完成了系统基础安装,真正的灵活配置和业务适配都由 Cloud-Init 完成。

三、PXE 引导配置优化

我使用 dnsmasq 同时提供 DHCP + TFTP 功能,并配置如下:

# /etc/dnsmasq.d/pxe.conf
port=0
dhcp-range=192.168.100.10,192.168.100.200,12h
dhcp-boot=undionly.kpxe
enable-tftp
tftp-root=/var/lib/tftpboot
log-queries

iPXE 脚本加载方式:

#!ipxe
dhcp
set base-url http://192.168.100.1/images/ubuntu
kernel ${base-url}/vmlinuz boot=casper netboot=nfs ip=dhcp cloud-config-url=http://192.168.100.1/user-data/${mac}
initrd ${base-url}/initrd
boot

注意事项:

  • cloud-config-url 指定每台机器的 Cloud-Init 配置源(支持按 MAC 或主板 SN 分发)
  • 使用 HTTP 提供 kernel/initrd,比 TFTP 更快更可靠
  • 所有引导文件统一挂载在本地 nginx,避免公网依赖

四、制作 Cloud-Init 镜像模板

我使用 cloud-image 作为基础,并内置 Cloud-Init:

# 下载 Ubuntu 镜像
wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img

# 转为裸金属支持的 raw 镜像
qemu-img convert -f qcow2 -O raw focal-server-cloudimg-amd64.img /var/www/images/ubuntu.img

制作镜像后,通过自动化预设 seed.img:

cloud-localds user-data.img user-data.yaml meta-data.yaml

也可以通过网络元数据服务器(如 cloud-init-meta-server)动态生成。

五、构建 Cloud-Init 配置服务端(动态 user-data 分发)

我搭建了一个简单的 Flask 服务,通过请求中携带的 MAC 地址返回对应配置:

from flask import Flask, request, send_file
app = Flask(__name__)

@app.route('/user-data/<mac>')
def user_data(mac):
    filename = f"/var/cloud-init-profiles/{mac}.yaml"
    return send_file(filename, mimetype='text/yaml')

示例 user-data.yaml:

#cloud-config
hostname: node-${MAC}
users:
  - name: devops
    ssh-authorized-keys:
      - ssh-rsa AAAAB3...
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    shell: /bin/bash

runcmd:
  - apt update && apt install -y docker.io
  - echo "Node ready." >> /var/log/init-success.log

部署好该服务后,iPXE 引导中的 URL 会自动拉取对应配置文件并执行。

六、处理常见 Cloud-Init 问题

配置拉取失败,Cloud-Init 停滞:

  • 保证 network-online.target 正确配置
  • 确认 DHCP 后可解析并连通配置服务器

Cloud-Init 被禁用(常见于非官方 ISO):

  • 检查 /etc/cloud/cloud.cfg.d/ 目录下是否存在 disable-cloudinit.cfg
  • 必要时重打包 initrd 添加 Cloud-Init 支持

MAC 与主机匹配混乱:

  • 优化 BIOS 引导顺序,避免 PXE+非PXE多路径混淆
  • 使用 iDRAC / IPMI 接口绑定 MAC 地址管理

七、部署总结与延伸

通过将传统 PXE 安装流程从单一 kickstart 模板转变为 PXE + Cloud-Init 解耦架构,我在香港裸金属服务器大规模部署中显著提高了稳定性和适配性:

  • PXE 引导只负责系统安装,避免复杂逻辑堆叠
  • Cloud-Init 完成全部配置初始化,实现跨平台统一初始化逻辑
  • 通过 MAC 地址路由配置,实现“同构差异化”管理
  • 结合 Ansible 做最终收敛,如加入 K8s 集群、注册监控平台

后续还可以对接如 MAAS、Foreman、Metal3 等更完善的 BareMetal 自动化管理平台,在香港机房内部署私有化裸金属控制面。

组件 版本或类型
Cloud-Init 23.1
PXE 引导工具 iPXE + dnsmasq
操作系统 Ubuntu 20.04 / 22.04
HTTP 文件服务 Nginx
元数据服务 自研 Flask 服务 / cloud-localds
目标服务器型号 Supermicro X12 / Dell R640 等

这种方案在我管理的香港三层网络架构中已稳定运行,成功将部署失败率从最初的 20% 降至低于 1%。对于部署频繁的 SaaS 平台、云边混合架构尤其适用。

未经允许不得转载:A5数据 » 批量部署裸金属时网络PXE常失败?香港服务器如何配合Cloud-Init构建稳定启动流程?

相关文章

contact