keelOS:没有硬件 IPMI?那我给你弄出一个来!
keelOS 在 hypervisor 底下多跑了一台几 MB 的小虚拟机,叫 keelRM。它独占主机的管理网卡,用主机自己的 IP 和 MAC 说话。宿主重启、死机、网络配错的时候,打开 https://主机地址:8623/ 照样能看屏幕、敲串口控制台、按复位和关机,还能把配错的地址改回来。没有 BMC 的机器,也有了一个自己的“IPMI”。
2026 年 10 月 8 日,这套东西在一台 Supermicro 开发机上从头到尾跑通了。
先用两段话交代 keelOS。keelOS 是给家里或小办公室那一台服务器用的虚拟化系统,基于 FreeBSD 和 bhyve。UEFI 先加载一个约 100 KB 的 keel hypervisor(hyp),它常驻内存,保管虚拟机的内存、vCPU 状态和 IOMMU;FreeBSD 宿主(root)跑在它上面,是一个只读镜像,可以升级、重启。
宿主重启时,虚拟机先挂起,内存留在 hyp 里;新的宿主起来以后把它们恢复,虚拟机只暂停几十秒,然后原地继续。hyp 不跟着宿主重启:这个位置,正好能放一个“宿主不在时也在”的东西。
为什么需要带外管理
服务器有 BMC。宿主死了、装错了、网络配丢了,管理员打开 BMC 的网页,看屏幕、敲键盘、按电源,人不用去机房。
家里和小办公室的机器大多没有 BMC:小主机、二手工作站、自己攒的 NAS。宿主一出问题,就只能搬一台显示器和键盘过去。keelOS 自己还多了一种情况:宿主 reload 的那几十秒里,主机的地址上什么都不答,网页打不开、ping 不通,看起来和死机一样。
我们的目标很直接:任何一台装了 keelOS 的 x86 机器,不管有没有 BMC,宿主不在的时候,主机的地址上也有人答,而且答的人能把宿主救回来。
别家怎么做
带外管理并不新鲜,只是都要硬件配合。我们的实验室里三种都有,下表是我们自己用下来的情况:
| 做法 | 哪里有 | 宿主重启时 | 我们碰到的问题 |
|---|---|---|---|
| BMC(IPMI、Redfish) | 服务器主板 | 一直在:独立的芯片、独立的网口 | 消费级机器没有;老主板的虚拟光驱只能走网页、Redfish 的虚拟媒体要另买许可证 |
| Intel AMT(vPro) | Intel 商用机 | 一直在:管理引擎和系统共用网口和 IP | 只有 vPro 机型;要先在 MEBx 里开通;远程桌面是 16 位色的 VNC |
| AMD DASH | AMD PRO 商用机 | 固件在网卡里 | FreeBSD 的网卡驱动一接管网卡,DASH 就应答不了;开关远程桌面会把主机复位 |
| 外接 IP-KVM 盒子 | 自己买 | 一直在 | 多一台设备、一根 HDMI、一根 USB,每台主机一个 |
Intel AMT 和 AMD DASH 那两行来自实验室里的 ThinkCentre P340 Tiny(AMT 14)和 M75q Gen 5(DASH 1.2),BMC 一行来自几台 Supermicro 开发机。
最接近我们想法的是 AMT 的共享 IP 模式:同一个网口、同一个 IP,管理引擎只截自己的几个端口,其余的包照常给系统。但它绑在 Intel 的芯片组上。而且,没有哪一家让同一台机器里的主机地址,在它自己重启的时候还有人应答。
keelOS 怎么做:一台不跟宿主重启的小虚拟机
hyp 开机先起一台很小的 Linux 虚拟机(1 个 CPU,64 MiB 内存,没有磁盘),再起宿主。它和宿主并列跑在 hyp 上,不是宿主的虚拟机,宿主 reload、死机,它都不停。主机的管理网卡整块交给它;宿主看不到这块网卡,换成一块叫 keelmgmt0 的 virtio 网卡,经这台小虚拟机上网,IP 和 MAC 都还是主机的。
宿主在跑的时候,小虚拟机只是一个透明的转发器,只截一个端口 8623 归自己,keel 的网页、ssh、DHCP 和以前一样。宿主不在的时候,它用主机的地址自己答 ARP、ping 和 8623。我们给它上的管理程序起名 keelRM(keel Remote Management)。
打开 https://主机地址:8623/,用 keel 的管理员密码登录:
- 状态:宿主在跑、reload 第几秒、多久没有心跳、崩溃原因;现在是哪个系统槽。
- 屏幕:主机显示器上的画面,每 2 秒一张。
- 串口控制台:可以打字。loader 的菜单、内核信息、
login:、shell 都在这里,和 BMC 的 SOL 一样。 - hyp 的日志:宿主之下那一层发生了什么。
- 按钮:reload 宿主、复位、关机、重启 keelRM、下次启动从哪个槽起一次。
- 救援:把管理口的地址改回来、重置管理员密码、进安全模式(不自动开虚拟机、不绑直通设备)。下一个起来的宿主先应用这些修改。
安全上,8623 只说 TLS,证书就是 keel 网页那张,浏览器对 keel 网页的例外也适用。默认只让管理网段连,可以在 keel 的网页上关掉或改网段。登录失败 3 次就限速。每次登录和每个操作都进 keel 的审计日志。
和真正的 BMC 比,它少三样东西:
- 机器关着时不能开机,要靠 BIOS 的 Wake-on-LAN。
- 图形屏幕只能看不能操作,要敲键盘走串口控制台。
- 没有虚拟光驱。
hyp 自己死了,它也一起没了。反过来,它不挑硬件:只要机器有 Intel VT-d,任何一块宿主认得的网卡都行。
怎么做到的
小虚拟机和宿主都跑在 hyp 上,网卡只归小虚拟机;宿主重启时,右边那一块换了,左边那条路一直通。
几个关键的地方:
- 网卡藏起来。 hyp 在宿主读 PCI 配置空间时把这块网卡藏掉,IOMMU 把它的 DMA 指向小虚拟机的内存。多口网卡的第一个口(PCI 功能 0)给了小虚拟机时,宿主看到的是一个占位设备,否则它会把同一块卡的其他口也跳过。
- 宿主不写新驱动。
keelmgmt0是一块标准的 virtio-net,驱动就是 FreeBSD 自带的 vtnet。设备那一侧在小虚拟机里(和 vhost-user 一个思路),hyp 只转发门铃和中断。 - 串口控制台。 hyp 拦下宿主对串口的 I/O,自己模拟一个 16550:宿主写的字符进一个共享环,小虚拟机把它送到页面上;页面上打的字反过来送进宿主。loader 、内核、getty 都在这条路上。
- 宿主卡死也能 reload。 hyp 给宿主的 CPU 发一个 NMI,就算宿主关了中断、卡在一个循环里,也会退出到 hyp,由 hyp 接着做 reload。
- 跨复位的请求。 “下次从槽 B 起一次”和救援里的修改,在复位前由 hyp 写进 UEFI 变量,开机时的 hyp.efi 读了就删;reload 的路上,它们放在 hyp 保管的一块内存里。所以不管下一个宿主是怎么起来的,都能拿到。
- 小虚拟机自己挂了。 hyp 有看门狗,它崩溃或不动了就从镜像重新起一个,实测 1.4–5.5 秒。宿主和虚拟机不受影响。
实测
2026 年 10 月 8 日,在一台 Supermicro X11DPU 开发机上(Xeon Silver 4110,Intel X710 四口网卡),把管理口 ixl0 交给 keelRM,宿主上开着三台虚拟机(一台 Windows、两台 Debian,其中一台 Debian 直通了同一块 X710 的另一个口)。
| 测什么 | 结果 |
|---|---|
| 宿主 reload 时主机地址还答不答 | 3 次 reload,每秒 5 个 ping:816 个一个没丢,最慢 149 ms;三台虚拟机都挂起、恢复;ssh 34–36 秒后重新连上 |
| 经 keelRM 上网的带宽(1G 口,iperf3 单流) | 宿主发 842 Mbit/s、收 938 Mbit/s;同一个口直接给宿主是 941 / 941 |
| 延迟 | 平时 1.31 ms,直接给宿主是 0.083 ms(转发器空闲时会睡一下,先不优化) |
| 管理页面 | TLS 握手 2–3.5 ms;1024×768 的屏幕截图 40–48 ms;串口控制台能登录、能敲命令 |
| 重启 keelRM 本身 | 断 2.54 秒 |
| 关机按钮 | ACPI 关机,1.36 秒后 BMC 报告电源已关 |
| “下次从槽 B 起一次” | 复位后起了槽 B,再复位回到槽 A |
| 救援:把地址改错 | 宿主换到 10.99.0.5 以后,原来的地址由 keelRM 接着答 ping 和 8623,在页面上改回来、复位,恢复正常 |
| 救援:重置密码 | 复位后 keel 网页、ssh、keelRM 都只认新密码 |
| 救援:安全模式 | 自动启动的虚拟机没开、直通设备留给宿主;在页面上退出以后虚拟机开起来 |
| 换了 hyp 或 keelRM 的升级 | 要经固件重启,主机和 keelRM 都断约 96 秒 |
路上找到的毛病也不少:PCI 功能 0 藏掉以后宿主跳过了同一块卡的其他口;网卡藏掉一块以后剩下的口改了名;Supermicro 的 SOL 是 COM2 而我们只拦了 COM1;“从槽 B 起一次”变成了永久。都修了,并在这台机器上重新验过。
还有一个是用户用的时候发现的:页面上的串口控制台只有 1.6 KB/s。原因是 FreeBSD 的串口驱动在轮询模式下每次只送 16 个字节、每秒轮询 100 次:100 × 16 = 1600,和实测一字不差。修了以后,在 QEMU 里页面输出到了 39.5 KB/s,按键到回显从 116 ms 降到 20 ms;真机上的数字还没测。
还没做完的
- AMD 机器还不行:hyp 的 AMD 后端还没有给这台小虚拟机的接口,配了也会被忽略,宿主照常跑。
- 要有 Intel VT-d:没有 IOMMU 的机器,安装时不开它,和以前一样。
- 只在一台真机上跑过:就是上面那台多网口的 Supermicro。只有一个网口的小主机上,虚拟机的流量也要经过 keelRM,这种用法设计上可以,在 ThinkCentre P340 上的实测还没做。
- 串口控制台提速后的真机数字:只有 QEMU 里的。
- “reload 宿主”按钮不是任何时候都能按:它要用宿主上次关机时留下的新内核,平时页面上写着“不能 reload”,这时只能用复位。
- 屏幕不能操作、没有虚拟光驱:计划里有“从网络下载一个干净的 keelOS,直接在内存里起来”,等于不插 U 盘的重装,还没做。
- 只在 Chrome 里试过页面。
结语
BMC 之所以好用,是因为它和系统互不依赖。keelOS 里本来就有一层不跟着宿主重启的东西:hyp。我们在它上面放了一台小虚拟机,把管理口交给它,一台没有 BMC 的机器就有了一个软件做的带外管理口。它不靠特定的芯片组,代码是我们自己的,宿主 reload 的时候主机地址上也一直有人答。