使用 AMT + PXE + Alpine 抢救一台远程 Proxmox VE 服务器
试图给一台远程的非空的 Proxmox VE 主机改名,改完名重启。然而 Proxmox VE 的配置文件目录是跟主机名强绑定的,于是不出意料的炸了。现在是 web 页面访问不了,ssh 连不上去(提示密钥错误),非常崩溃。
这个问题修起来也不是很容易。Proxmox VE 已经不能正常启动了,得想办法用其他启动盘启动,然后挂载主机硬盘把主机名改回去。可惜机器在 1000 公里外的家里,没法自己去操作,也很难让家里人帮忙操作……
好消息是,家里另外一台机器我还能连上,挂掉的这台机器开启了 Intel AMT 主动管理功能。那么,如果我通过 AMT 连接到挂掉的这台机器上,让她以网络启动,那么是不是就能救活她了?
远程救援的理论基础
在开始实操救援之前,先让我们理一理救援的理想过程,看看都需要配置哪些服务、解决哪些问题。
- 使用 Intel AMT 将被救援主机重启到网络引导(PXE)模式
- PXE 程序发送 DHCP 请求,获得 IP 地址、下一步服务器地址
next-server
、引导程序文件名filename
- PXE 程序使用 TFTP 协议从
next-server
下载filename
指定的引导程序(iPXE),然后运行 iPXE - iPXE 通过 TFTP 协议从
next-server
下载autoexec.ipxe
脚本,根据脚本通过 HTTP 下载 Alpine 的 Linux 内核、initramfs,启动内核并传递指定的内核参数 - Alpine 根据内核参数配置 ssh 密钥、软件包仓库镜像地址,并下载并加载 modloop(打包好的额外的内核模块),最终完成初始化进入登录界面
- 通过 Intel AMT Serial over LAN 或者 SSH 连入 Alpine
- 安装 zfs 工具,导入 Proxmox VE 的启动池,挂载相关数据集,修改罪魁祸首
/etc/hosts
- 卸载数据集,导出池,关机,重启后 Proxmox VE 恢复正常。
使用 Intel AMT 连接到被救援服务器
之前部署这台服务器的时候,专门进 BIOS 里打开了 AMT 功能,现在想来真是有先见之明。这里简要介绍下 AMT 的启用流程:
- 在启动菜单中,选择进入 BIOS 设置(Computer Setup),找到 Advanced、Remote Management Options,确保 Active Management(AMT)被打开
- 在启动菜单中,选择进入 Intel Management Engine 设置
- 默认密码是 admin,登录后修改密码,要求必须是带有数字、字母、符号的强密码
- 启用需要的功能,应该不需要改太多
首先我们尝试用 AMT 连接到服务器。可以直接用浏览器访问服务器的 16992 端口外,还可以使用使用开源的 Intel AMT 客户端 MeshCommander。我们后续都使用后者。输入服务器 IP 和密码,顺利连上。
坏消息是,我的这台 HP 机器上没有 KVM(键盘、视频、鼠标)的选项,远程管理仅能用 Serial over LAN(SoL)远程串口功能。我在互联网上翻了一圈,大概是因为这台机器原装是 i3 处理器,不具备 Intel vPro 功能,于是 HP 直接在主板 BIOS 里干掉了 KVM 功能,后面再换 i5、i7 处理器也用不了 KVM 了。这个可以通过修改 BIOS 芯片数据来实现(参考1,参考2),只不过当时没时间搞了……
对 SoL 进行了一系列探索,发现 Reset to BIOS 时能够让 SoL 有正常输出,可惜是乱码。盲操修改了语言,这下能看到正常的启动菜单了。
启动菜单可以选择 Network (PXE) Boot,也可以在电源操作里选择 Reset to PXE 。
配置 dnsmasq(DHCP 和 TFTP)
我们已经能够用 AMT 让服务器从 PXE 引导,接下来配置 PXE 启动所需的 DHCP 和 TFTP 服务。在 PXE 启动中,DHCP 用于下发 next-server
、filename
等启动参数,TFTP 用于传输引导文件。
这里的 DHCP 就是那个自动分配 IP 地址的 DHCP,那么就有个问题:在家庭网络环境中,路由器往往仅提供了基础 DHCP 服务,无法扩展 PXE 所需的配置项;若禁用路由器的 DHCP 功能、部署独立的 DHCP 服务器,则可能有网络全面断联的风险。为解决这一问题,我们使用 Proxy DHCP 技术:当客户端发出 DHCP 请求时,原有 DHCP 服务器仍下发 IP 地址,Proxy DHCP 服务器补充下发 PXE 所需的附加参数,两者协同工作。现代 PXE 网卡应该都支持 Proxy DHCP。
我准备了一台全新的 Ubuntu 24.04 虚拟机用来提供网络启动所需的一切服务,使用 dnsmasq 来同时提供 DHCP 和 TFTP 服务。
# 安装 dnsmasq
apt-get install dnsmasq
# 查看 dnsmasq 服务状态
systemctl status dnsmasq
配置 dnsmasq,以启用 proxy DHCP 和 TFTP。将下面的配置文件保存到 /etc/dnsmasq.d/pxe.conf
。
# Disable DNS Server
port=0
# Enable TFTP server, setup root path
enable-tftp
tftp-root=/var/ftpd
# Enable DHCP logs
log-dhcp
# Enable Proxy DHCP Server
# proxy enables Proxy DHCP mode
# 192.168.230.0 and 255.255.255.0 are my subnet and mask
dhcp-range=192.168.230.0,proxy,255.255.255.0
# setup pxe for x86-64 EFI, load ipxe.efi from TFTP server
pxe-service=X86-64_EFI,"Network Boot UEFI x86_64",ipxe.efi
这里我只为 UEFI 做了配置(因为我的服务器就是 UEFI 启动的)。更多配置项可以仔细阅读 /etc/dnsmasq.conf
或者 dnsmasq 的 man 页面。
接下来创建 TFTP 根目录、让 dnsmasq 检查配置文件、重启 dnsmasq 服务。
# 创建 TFTP 根目录 /var/ftpd
mkdir -p /var/ftpd
# 检查 dnsmasq 配置文件
dnsmasq --test
# 重启 dnsmasq 服务
systemctl restart dnsmasq
# 再次检查 dnsmasq 服务状态
systemctl restart dnsmasq
然后就可以在虚拟机尝试进行 PXE 启动了!虚拟机的 BIOS/PXE 会抱怨找不到 ipxe.efi 文件(这个我们下一步去搞),但它已经知道了要去哪里找引导文件。也可以再去看看 dnsmasq 的日志,应该也能找到它类似的抱怨。
一定要先在虚拟机尝试 PXE 启动,确保所有组件部署完成、一切无误后再去救援实体机。
把虚拟机的磁盘、光盘设备都删光,它自然会去尝试 PXE 启动。
配置 iPXE
iPXE 是一个更高级的网络启动固件,能够直接通过 HTTP 协议下载引导文件,比 TFTP 要快许多。我们用 PXE 引导 iPXE,然后再让 iPXE 启动 Linux 内核。
除了 iPXE,还可以选择 pxelinux 来启动 Linux 内核,具体参考 Ubuntu 的网络启动指南。我选择 iPXE 单纯是我参考的博客选择了 iPXE,实际上 pxelinux 使用更广泛一点)
我们从源码构建 iPXE,并把编译好的 iPXE 放到 TFTP 根目录。
# 安装必要的工具
apt-get install git make binutils mtools perl libc-dev gcc
# 获取源码
git clone https://github.com/ipxe/ipxe.git
cd ipxe/src
# 为 x86-64 EFI 构建
make bin-x86_64-efi/ipxe.efi
# 把编译好的 ipxe.efi 复制到 TFTP 根目录
cp bin-x86_64-efi/ipxe.efi /var/ftpd/
接下来就又可以在虚拟机尝试启动了!你应该能看到 iPXE 的输出,并且它在抱怨找不到任何可以启动的东西。
iPXE 会尝试从 TFTP 服务器获得 autoexec.ipxe,它抱怨的就是找不到这个文件。跟前面一样,这里也可以去看看 dnsmasq 的日志。稍后我们在配置 Alpine 时会去搞这个文件。
配置 HTTP 服务器
前面我们提到 iPXE 可以通过 HTTP 服务器来下载引导文件,实际上 Alpine Linux 启动过程中也需要从 HTTP 下载文件。我们需要部署一个 HTTP 服务器,这里选择最简单的 Apache2.
# 安装
apt-get install apache2
Ubuntu 的 Apache2 开箱即用,不需要什么配置。其默认根目录是 /var/www/html
,稍后我们就会把 Alpine Linux 的各种文件丢进去。现在,打开浏览器访问服务器地址,应该能看到它的默认页。
配置 Alpine Linux
Alpine Linux 是一个新兴的 Linux 发行版,主打轻小、简单、安全,挺适合当救援系统的。
选其他发行版来搞救援也行,比如 Ubuntu。这里选 Alpine 单纯是看到了相关的博客。
获取 Netboot 文件
Alpine Linux 本身就提供了 Netboot 的版本,从它的下载页下载,直接解压到 HTTP 服务器根目录里。
# 下载 Alpine v3.21 netboot 版
wget https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/x86_64/alpine-netboot-3.21.3-x86_64.tar.gz
# 直接解压到 HTTP 服务器根目录 /var/www/html
tar -xzf alpine-netboot-3.21.3-x86_64.tar.gz -C /var/www/html
解压后应该能得到如下文件:
.
└── boot
├── config-6.12.13-0-lts # 内核配置
├── config-6.12.13-0-virt
├── dtbs-lts # 设备树(对于 x86 没用)
├── dtbs-virt
├── initramfs-lts # 初始内存文件系统
├── initramfs-virt
├── modloop-lts # 额外的内核模块
├── modloop-virt
├── System.map-6.12.13-0-lts # 内核符号表
├── System.map-6.12.13-0-virt
├── vmlinuz-lts # 内核
└── vmlinuz-virt
所有文件都有 lts
和 virt
结尾的两份,lts
是标准版,virt
是针对虚拟机裁剪的版本,我们后面总是使用前者。这些文件中,我们实际上只使用下面 3 个:
vmlinuz-lts
initramfs-lts
modloop-lts
记得检查所有文件的权限,确保它们都能通过浏览器下载。
ls -l
# total 275M
# -rw-r--r-- 1 ceba ceba 265K Feb 13 23:06 config-6.12.13-0-lts
# -rw-r--r-- 1 ceba ceba 146K Feb 13 23:06 config-6.12.13-0-virt
# drwxr-xr-x 2 ceba ceba 4.0K Feb 13 23:06 dtbs-lts
# drwxr-xr-x 2 ceba ceba 4.0K Feb 13 23:06 dtbs-virt
# -rw------- 1 ceba ceba 24M Feb 13 23:06 initramfs-lts <-- 权限不足
# -rw------- 1 ceba ceba 8.6M Feb 13 23:06 initramfs-virt <-- 权限不足
# -rw-r--r-- 1 ceba ceba 189M Feb 13 23:06 modloop-lts
# -rw-r--r-- 1 ceba ceba 20M Feb 13 23:06 modloop-virt
# -rw-r--r-- 1 ceba ceba 6.3M Feb 13 23:06 System.map-6.12.13-0-lts
# -rw-r--r-- 1 ceba ceba 5.7M Feb 13 23:06 System.map-6.12.13-0-virt
# -rw-r--r-- 1 ceba ceba 12M Feb 13 23:06 vmlinuz-lts
# -rw-r--r-- 1 ceba ceba 12M Feb 13 23:06 vmlinuz-virt
# 补足权限
chmod 644 initramfs-lts initramfs-virt
另外,往 HTTP 服务器根目录下丢一个公钥文件 ssh_key
,用于稍后 SSH 登录。
配置 iPXE 启动脚本
创建 autoexec.ipxe
文件,放在 TFTP 根目录 /var/ftpd
下。
#!ipxe
# Init networking
dhcp
# Server address
set server http://192.168.230.12
echo server is ${server}
# Set command line
set cmdline modules=loop,squashfs quite
echo cmdline is ${cmdline}
# Kernel file
set vmlinuz ${server}/boot/vmlinuz-lts
echo vmlinuz is ${vmlinuz}
# Initramfs file
set initramfs ${server}/boot/initramfs-lts
echo initramfs is ${initramfs}
# Modloop file
set modloop ${server}/boot/modloop-lts
echo modloop is ${modloop}
# Repository for apk
set mirror http://mirrors.ustc.edu.cn/alpine
set branch v3.21
set repo ${mirror}/${branch}/main
echo repo is ${repo}
# Set SSH key
set ssh_key ${server}/ssh_key
# Uncomment this if you want to see the information before continuing
# prompt Press any key to continue
#Kernel, initrd
kernel ${vmlinuz} ${cmdline} alpine_repo=${repo} modloop=${modloop} initrd=initramfs-lts ssh_key=${ssh_key}
initrd ${initramfs}
#Boot
boot
#Pause if errors
prompt Some error occurred, press any key to continue
对于 ZFS 的额外处理
我的 Proxmox VE 是装在两块 NVME 盘组的 zfs 阵列上的,我的救援系统就必须有 zfs 支持,包括 zfs 内核模块和 zfs 工具。然而,netboot 版的 Alpine Linux 并没有自带 zfs 内核模块,我在启动后尝试用 apk 安装会报莫名其妙的错误,救援一下子陷入了僵局。
机缘巧合下,我发现 Alpine Linux 的 Extended 版带有 zfs 模块,那么把 Extended 和 Netboot 整合一下是不是就可以了?我注意到:
- 两者的 lts 内核完全一致(通过比较 config 和 md5sum)
- 两者的 initramfs 各有千秋(通过
lsinitramfs
) - Extended 比 Netboot 的 modloop 多了一些模块,其中包括 zfs (通过
unsquashfs -l
)
那么可以试着用 Extended 的 modloop 替换掉 Netboot 的 modloop,具体如下:
- 下载 Extended 的 ISO,挂载到文件系统,找到
boot/modloop-lts
,替换掉原来的文件; - 在
autoexec.ipxe
作以下可选修改command
的modules
选项修改为modules=loop,squashfs,zfs
,以自动加载 zfs 内核模块kernel
命令中添加modloop_verify=no
,关闭 modloop 校验
这下 Alpine 就有 zfs 模块了。
启动!
现在,可以在虚拟机上做最后的测试了。经过漫长的启动后,如果没有意外,应该能看到这样的登录画面。用户名是 root,没有密码。
Alpine 默认开启了 ssh 服务器,可以用 ssh 连接,前面添加的 ssh 公钥此时派上用场了。
到此,一切就绪,可以尝试在物理服务器上进行 PXE 启动了。
救援 ZFS
通过 ssh 连接到被救援服务器,安装相关工具,挂载 zfs 文件系统,进行必要的修改。
# 安装 zfs 命令行工具
apk add zfs
# 查看 zfs 状态
zfs status
# 搜寻磁盘上的 zpool
zpool import
# 导入指定的 zpool
zpool import rpool
# 查看 zfs 文件系统信息
zfs list
# 挂载文件系统
mkdir -p /root/rpool
mount -F zfs rpool/ROOT/pve-1 /root/rpool
# 做修改
vi /root/rpoll/etc/hosts
# 卸载文件系统
umount /root/rpool/
# 导出 zpool
zpool export rpool
# 关机
poweroff
用 Intel AMT 再次启动服务器,web、ssh 全部恢复正常,救援成功!
结语
这次远程救援花了好几天时间,最终省下了 1000 块钱的车票,总是值得的。
Intel AMT 还是好用的,不过我下次回家一定得把 KVM 功能恢复了,SoL 的可用性实在堪忧啊。另外,从 MeshCommander 的网站上看到,它的开发者在 2022 年的时候被 Intel 裁掉了,真是令人唏嘘。
希望这篇文章对你有所帮助~
参考
- 这两篇文章是我 PXE 启动 Alpine Linux 的主要参考,感谢 apalrd。
- 有关 Alpine Linux 网络启动的官方文档
- 有关 dnsmasq 的配置
- 有关 Alpine Linux + ZFS 的文章
- 有关 ZFS 操作的材料
本作品采用知识共享署名 4.0 国际许可协议进行许可。
本文链接:https://blog.ceba.tech/2025/02/Rescue-a-Proxmox-VE-Server-with-AMT-PXE-Alpine/