随着手里的服务器越来越多,我发现自己陷入了一种很尴尬的状态:机房里躺着七八台不同品牌的GPU服务器,有的支持Redfish,有的只有IPMI,还有两台老掉牙的机器只能靠IPMI over LAN访问。每次要装机、查硬件状态、远程开关机,我都得在好几个管理界面之间来回切,命令行工具也攒了一大堆。后来我干脆自己动手,把一套叫 openrig 的开源项目完整部署了起来,用一套系统统一接管了所有机器。这篇文章就把我这次折腾的完整过程写出来,包括核心设计、部署步骤、踩过的坑,以及一些常规文档里不会写的细节,给同样被设备管理折磨的朋友做个参考。
1. openrig到底解决什么问题:从“设备多了管不过来”说起
先交代一下背景。我之前所在的小团队大概维护着两类资源:一类是机房里的物理服务器,用来跑模型训练和离线任务;另一类是散落在各个办公区的边缘盒子,用来做推理验证和数据采集。数量不算夸张,加起来二三十台,但麻烦的地方在于品牌和型号特别杂。
1.1 多品牌设备带来的管理碎片化
最痛苦的就是管理入口不统一。戴尔的机器可以用 Redfish API 拉传感器数据,超微的机器用 ipmitool 操作,还有一些定制的工控机只有厂家给的简易网页管理界面。每台机器都有自己的“脾气”。
我整理了一下当时的管理方式,大致是这样:
- 查CPU温度和风扇转速:依次 SSH 到每台机器,执行
ipmitool sdr或者看 Redfish 接口; - 检查磁盘健康:依赖部分机器自带的 RAID 管理工具,其余的需要进系统看 smartctl;
- 远程开关机和重启:靠 IPMI/BMC 网页,偶尔还得物理进机房按电源键;
- 重新装系统:通常是接显示器、插U盘,或者是用一套自建的 PXE 环境,但配置非常脆弱。
熟悉这类场景的人应该能感觉到,这根本不是技术门槛的问题,而是“脏活累活”太多,占据了本该用来调优和写脚本的时间。openrig 的目标就是把这些操作收拢到一个统一的平台上,让我可以对所有异构裸金属设备做同样的操作,不用关心底层是 Redfish 还是 IPMI。
1.2 openrig 的定位:不是又一个监控面板
第一次接触 openrig 的时候,我下意识把它当成另一种“监控大屏”。但实际上,它的重点并不是画图表给领导看,而是管理和控制。
用一句话概括:openrig 是一个面向裸金属设备的开源管理平面。它通过带内 Agent 采集操作系统的详细信息(CPU型号、内存插槽、磁盘型号等),同时通过带外接口(IPMI/Redfish)获取硬件层面的状态和控制能力,然后把这两类数据统一关联到同一台设备上。
为什么我特别强调关联?举个例子:以前我查一台机器的“准确配置”,得先 IPMI 查到 Service Tag,再去系统里看 CPU 和内存信息,两边手动对账。openrig 会主动把同一台机器的带内信息、带外信息、IPMACSN 等身份信息拼在一起,形成唯一的硬件台账。后面不管是做资产盘点还是巡检告警,都直接从这个台账里读数据。
1.3 适合什么样的团队使用
根据我这几个月在 openrig 上的实操经验,它最适合下面这几类场景:
- 维护的物理机数量超过 10 台,且品牌型号不统一;
- 经常要远程装机、重启、查硬件健康状态;
- 需要给设备建立统一的资产台账,但又不想采购商业网管软件;
- 手上有一定 Linux 基础,愿意花时间折腾部署。
如果你是个人开发者,家里只有一台小主机,那 openrig 确实有点大材小用。但如果你的团队正在经历“设备越来越多、管理越来越乱”的阶段,这个项目值得一试。
2. openrig的核心设计:设备抽象层才是灵魂
真正让我决定把 openrig 落地部署的,是它内部的架构设计。和那些“一把梭”的管理脚本不同,openrig 把设备接入和业务逻辑做了解耦。理解这个设计思路,后面用起来会底气足很多。
2.1 带内与带外两条数据通道
openrig 在每台受管设备上装了一个 Agent,在控制端装了一个 Controller。Agent 负责从系统内部收集数据,Controller 负责汇总并提供 API。
但这里有个关键点:Agent 能拿到的信息只限于操作系统层面。如果系统崩了或者机器关机了,Agent 就算装得再好也无济于事。所以 openrig 同时保留了带外通道。
带内和带外各司其职:
| 通道 | 作用 | 对应信息 |
|---|---|---|
| 带内(Agent) | 获取操作系统内部状态 | CPU温度、内存使用率、进程列表、系统日志 |
| 带外(BMC/IPMI/Redfish) | 获取物理硬件状态 | 电源状态、风扇转速、背板传感器、BIOS信息 |
| 带外控制 | 进行物理操作 | 开机、关机、重启、启动到PXE |
通过这两条通道,openrig 就能做到:机器正常运行时,我能看完整系统状态;机器“挂”了,我还能看硬件信息、远程开机、进入救援环境。
2.2 设备抽象层的技术细节
openrig 最值得称道的是它的设备抽象层(Device Abstraction Layer)。简单说,它把不同厂商的带外接口差异封住了,向上提供一个统一的数据模型。
同样是“读取服务器功耗”,戴尔的机器走 Redfish 的/redfish/v1/Chassis/.../Power,超微的机器走 IPMI 的ipmitool sensor。openrig 里接入了一堆适配器,比如 redfish-adapter、ipmi-adapter、snmp-adapter。适配器把各种协议转换成标准的 JSON 结构,Controller 再消费这些 JSON。
我第一次看这些代码的时候,最大的感受是:它把“设备型号”和“管理协议”两个维度拆开了。这样即使以后买了一台只支持 Redfish 的新机器,我只需要在 openrig 里配置 Redfish 连接,不需要为这个品牌定制任何逻辑。
2.3 任务下发与执行:怎么做到异步可控
远程开机、关机、装机这些操作,不可能同步等待完成。因为断电、启动、装系统都是耗时操作,网络还可能中断。
openrig 采用任务队列的形式:我在界面上点“重启并进入PXE”之后,Controller 会创建一个任务,由执行器调用对应的带外接口,然后把结果写回。任务状态包括 pending、running、succeeded、failed。如果中途网络断了,任务不会直接消失,而是保留现场,方便排查。
这里有一个很实用的细节:openrig 会在执行“进入PXE”动作前,先设置好下一次启动设备的启动项,再执行重启。这样就不需要人蹲在服务器面前按 F11 选择启动设备,对于机房里的无人值守机器非常有用。
3. 手把手把openrig跑起来:从空机器到接管第一台GPU服务器
前面讲完设计,下面进入实操环节。我会按自己的部署顺序来说,尽量把关键步骤写细一点,方便照做。
3.1 部署环境和准备工作
openrig 的 Controller 其实不挑环境,官方推荐用 Docker 部署。我自己用的是三台虚拟机组成的节点,配置不高,每台 4C8G,硬盘 100GB。如果你只是测试,一台 2C4G 的小机器也能跑明白。
需要准备的东西:
- 一台 Linux 主机作为 Controller(我用的 Ubuntu 22.04 LTS);
- Docker 和 Docker Compose 插件;
- 一个网段专门用于受管设备,比如 192.168.10.0/24;
- 一台待管理的物理机,这里强烈建议先用一台你不太忙的旧服务器试水,别一上来就接管生产环境。
3.2 安装 Controller 并初始化
先拉取 openrig 的部署包,然后改配置。
git clone https://github.com/your-local-mirror/openrig.git cd openrig/deploy cp .env.example .env.env里几个核心配置项需要注意:
OPENRIG_BIND_ADDR=0.0.0.0 OPENRIG_PORT=8020 OPENRIG_DATABASE_URL=postgresql://openrig:openrig_password@postgres:5432/openrig OPENRIG_AGENT_PORT=6789我一开始用了默认的数据库密码,结果被局域网里扫端口的脚本尝试弱口令连接。后来改了密码,并且把 PostgreSQL 端口限定在 Docker 内部网络,不暴露到宿主机。这个细节很建议你直接抄走。
然后启动:
docker compose up -d docker compose ps正常情况下能看到 controller、postgres、redis 等容器是 running 状态。这时打开http://<controller-ip>:8020,设置管理员账号,就能进入 Web 界面。
3.3 导入第一台设备:手动添加和自动发现
设备录入是接管机器的第一步。openrig 提供了两种方式:
- 手动添加:输入设备的 IP、BMC 管理地址、IPMI/Redfish 账号密码,直接关联;
- 自动发现:提供一个网段,openrig 通过 SNMP/扫描识别在线设备。
我先用手动方式添加了第一台机器。配置项大致如下:
| 配置项 | 我的填写值 | 说明 |
|---|---|---|
| 设备名称 | lab-node-01 | 自定义名称,建议有业务含义 |
| 带外管理地址 | 192.168.10.10 | BMC 的 IP |
| 带外协议 | Redfish | 先选 Redfish,不支持再换 IPMI |
| 带内管理地址 | 192.168.10.11 | 系统网卡 IP,Agent 上报用的 |
| 登录凭据 | 单独创建的用户 | 不要把 root 密码直接填进去 |
填完之后,openrig 会自动执行一次带外探测。如果 Redfish 连接和传感器采集都正常,设备状态会从“unknown”变成“online”。
3.4 在受管设备上安装 Agent
这一步的目标是把带内数据接入 openrig 闭环里。openrig 的 Agent 是一个安装脚本,我直接在目标服务器上执行:
curl -fsSL http://<controller-ip>:8020/agent/install.sh | sudo bash安装脚本会做三件事:
- 安装 openrig-agent 作为 systemd 服务;
- 生成 agent id 并写入配置文件;
- 和 Controller 建立 WebSocket 长连接。
装完后,到 Web 界面的设备详情页刷新,正常情况下能看到 CPU、内存、磁盘、网卡等信息刷新出来。如果 Agent 一直显示离线,最可能的原因是 Controller 的端口没放通,或者目标机器上的证书校验没过。这些我在后面“踩坑”部分会细说。
3.5 首次远程开机和电源控制
当设备状态正常后,我做了个简单的电源开关测试。openrig 在设备详情页里提供了 Power State、Power On、Power Off、Reboot 这些按钮。
我从页面上触发了一次冷启动:Power Off,等半分钟看设备从 online 变成 offline,再 Power On。这个过程中,openrig 会先在 Controller 日志里记录“下发 Power On 指令”,然后通过 Redfish 请求 BMC 执行操作。实测下来,整个过程大概 10 秒内完成指令下发,状态刷新略有延迟,但和控制端直连 BMC 的速度基本相当。
个人经验:如果你的机器支持 Redfish,优先用 Redfish 做电源控制。实测中 Redfish 的响应速度通常比 IPMI 更快,而且在部分新机型上 IPMI 的 raw 命令会被管理员禁用。
4. 实测中的三场硬仗:PXE误伤、Agent掉线、Redfish超时
部署和基础使用的过程还算顺利,但越往后越发现“坑”都藏在细节里。下面这几场硬仗,我一个个说,大家后面遇到类似问题,可以直接照思路排查。
4.1 PXE装机会误伤同网段的其它主机
openrig 支持“启动到 PXE”这个动作,意思是下一次重启时自动从网络启动,进入装机环境。配置好 TFTP 和 HTTP 服务后,pxelinux 配置会指向 openrig 的启动镜像。
但我第一次执行时就翻了车:同网段里另外两台机器也同时进入了 PXE 安装流程。
原因很简单,PXE 本身靠 DHCP 广播工作,只要网卡支持 PXE 启动,无论机器是不是我想装的那台,DHCP 都会下发启动文件。openrig 的 PXE 记录默认没有做 MAC 地址过滤。
解决办法:在 DHCP 配置里做“基于 MAC 地址的启动策略”。openrig 的 PXE 服务支持一个 mactable 文件,配置了允许启动的 MAC 列表;不在列表里的机器,DHCP 只分配 IP,不下发启动文件。
/etc/dhcp/dhcpd.conf里的关键片段:
subnet 192.168.10.0 netmask 255.255.255.0 { option routers 192.168.10.1; option broadcast-address 192.168.10.255; class "openrig-pxe" { match if substring (option dhcp-client-identifier, 0, 6) = "00:e0:4c:68:00:11"; filename "pxelinux.0"; next-server 192.168.10.20; } }上面这段只是示范,实际操作时要调整 MAC 匹配方式。总而言之:在你把日常 PXE 跑顺之前,一定先把 MAC 白名单加上。别问我是怎么知道的,那次误伤导致我整个下午都在给其他机器重装系统。
4.2 Agent 上线后又掉线:systemd OOM 问题
有一台 32G 内存的机器,Agent 装好之后状态显示 online。但跑了一个多小时的特诊任务后,Agent 掉线了。我 SSH 上机器看进程和日志:
systemctl status openrig-agent journalctl -u openrig-agent --since "1 hour ago"日志里出现了killed字样,再查看系统日志,确认是 OOM Killer 把 Agent 相关进程杀了。
原因:那台机器在做数据批处理,内存几乎占满。openrig-agent 默认没有设置内存上限,系统内存耗尽时被 OOM Killer 当成“可牺牲进程”处理了。
解决方案有两步:
- 为 Agent 服务设置合理的内存限制;
- 提高 OOM 免疫能力。
我在/etc/systemd/system/openrig-agent.service.d/override.conf里写了:
[Service] MemoryLimit=512M OOMPolicy=continue然后重载守护进程配置并重启服务:
systemctl daemon-reload systemctl restart openrig-agent注意OOMPolicy=continue的意思是:当进程触达内存限制时,不直接杀掉,而是让它继续运行,等自身处理。对于 Agent 这种轻量守护进程,512M 通常够用。设置完后,后续跑批量任务时 Agent 就没再掉线过。
另外提醒一个坑:openrig 官方安装脚本生成的 systemd 服务文件在/etc/systemd/system/openrig-agent.service,重写配置时不要覆盖原文件,最好放在 override.conf 里,这样升级 Agent 时不容易被覆盖。
4.3 Redfish 数据采集“假死”:超时设置太短
我管理的一台戴尔服务器,openrig 的设备详情页里传感器数据有时能刷出来,有时转圈半天然后报“timeout”。
排查思路是先绕开 openrig,直接测 Redfish API:
curl -k https://192.168.10.10/redfish/v1/Systems curl -k https://192.168.10.10/redfish/v1/Chassis/1U/Thermal两条命令都能返回数据,但温度接口明显比较慢,接近 3 秒才给响应。而 openrig 的 Redfish 适配器默认超时时间是 1.5 秒。
于是我去改 openrig 的 Redfish 适配器配置:
redfish: timeout: 5 retry_policy: max_attempts: 3 backoff: 1.2把超时从 1.5 秒调到 5 秒,并且增加重试。改完再刷新页面,传感器数据稳定出现了。
为什么会慢?因为那个机型的 Thermal 接口会一次性返回包括所有插槽、电源、风扇在内的完整传感器树,数据量大,BMC 本身处理也慢。这类问题在很多带外管理接口里都常见,遇到超时先别急着怪适配器,先用 curl 确认接口本身的耗时。
4.4 一个容易被忽略的 BIOS 设置:安全启动导致 PXE 失败
另一个非常隐蔽的坑和前面 PXE 相关。有的机器网卡支持 UEFI 网络启动,但 BIOS 开了 Secure Boot,并且 PXE 镜像没有签名,启动流程直接就被拒了。
现象是:openrig 任务日志显示“启动设备已切换为 Network”,机器确实重启了,但几分钟后还是回到了原系统。手动进 BIOS 把启动模式从 UEFI 改成 Legacy,或者关闭 Secure Boot 后,PXE 才能正常进入装机环境。
所以如果遇到“任务显示执行成功、机器没反应”的情况,优先检查两项:
- 是否设置了一性次启动项(one-shot boot device);
- 安全启动是否挡住了网络启动。
这两类问题不会在 openrig 日志里显示失败,因为它们属于硬件层行为。
5. 把openrig当平台用:API、插件与后续演进
设备接进来之后,openrig 的价值远不止在页面上点按钮。它提供了一个比较清晰的 API,还有一套插件机制,可以跟现有的监控、告警和自动化体系串起来。
5.1 通过 OpenAPI 做设备状态巡检
openrig 的控制器暴露了一个 REST API,接口风格是 OpenAPI 规范。我在 Crontab 里写了一个脚本,每天凌晨把所有设备的状态和关键传感器拉一遍,生成一份资产健康报告。
最简单的调用方式:
curl -s -H "Authorization: Bearer $OPENRIG_TOKEN" \ http://<controller-ip>:8020/api/v1/devices | jq .返回的 JSON 里包含每台设备的id、name、status、health、last_seen,我再用 Python 脚本汇总成摘要。
有件事提醒一下:默认管理员账号在页面登录后拿到的 Token 有效期不长,建议在设置里创建一个专用的 API Token,并限制作用域只读。openrig 支持按 Token 控制权限范围,具体路径在“设置-访问令牌”里。
5.2 让 openrig 把硬件告警推送给已有监控
我们团队已经搭了 Prometheus + Alertmanager,所以我不想让 openrig 再成为一座孤岛。openrig 内置 Webhook 通知能力,当设备状态变化时,可以往 Webhook 地址推送 JSON 事件。
我在 Alertmanager 的 Webhook 接收端里写了一个简单的 HTTP handler,逻辑大致是:收到 openrig 推送的设备离线事件后,自动在告警通道里创建一条对应服务的中等级别告警。这样硬件层的故障能第一时间进入自己的告警流,而不是靠人工盯着 openrig 页面。
下面是 Webhook payload 的一个示例结构:
{ "event_type": "device.offline", "device_id": "a1b2c3d4-xxxx", "device_name": "lab-node-01", "reported_at": "2025-01-15T08:30:00Z" }如果你不想自己写接收端,可以先用钉钉、飞书或者 Slack 的机器人 Webhook 接一下,然后再做事件字段映射。
5.3 尝试写一个自定义插件:从“用”到“改”
openrig 的插件机制是我后期才认真研究的。它允许你在设备详情页自定义操作项,通过插件执行脚本或调用外部接口。
我写过一个很简单的插件,作用是批量修改所有设备的 BMC 密码。功能本身很普通,但体现了一种思路:在 openrig 平台上对设备做“组合操作”。插件脚本里做的事情是:
- 读取选中设备的 BMC 地址和旧凭据;
- 调用该品牌 BMC 的命令行工具执行修改;
- 将修改后的状态返回给 openrig。
插件在 openrig 里以 Python 脚本形式运行,入口函数接收设备上下文,返回结果。这个写法不复杂,但把 openrig 从“管理状态”扩展成“执行运维操作”的平台,自由度一下子高很多。
在动手写插件前,我的建议是先看官方仓库里的 example plugin,照着模板改。插件运行环境本身没有太多魔法,重点是你能否接入每个厂商 BMC 的命令。
5.4 后续演进:把 openrig 纳入自服务入口
现在我已经把 openrig 接到团队内部的“开发自服务”平台上:开发同学想申请一台测试机,不需要再找人开障工单,直接在自服务页面勾选设备类型,平台调用 openrig API 给它开机、装系统、配置网络。
这算是 openrig 比较高阶的用法。它本质上把“裸金属管理能力”变成一个可编程的基础设施层。无论是做内部云控制台、硬件调度器,还是自动化巡检平台,openrig 都能作为底层的执行引擎。
根据我个人这段时间的实际体会,openrig 这样的开源管理平面,最大的价值不是省掉那点“手工操作”,而是让所有硬件层操作变得可追踪、可编程、可自动化。当你的环境规模到了某个程度,手点 IPMI 网页的次数越少,出错的概率就越低。
最后分享一个小细节:在设置 openrig 管理网段的时候,建议单独划一个 Vlan 给带外管理,不要和业务网络混在一起。这样既安全,也避免带外流量影响业务网络。如果你也是从“设备管理混乱”的状态里走出来,希望这篇东西帮你少走点弯路。