[架构实战] 别再用 git pull 更新了!如何用 RAUC 构建“永不因断电变砖”的工业 OTA 系统?
2026-01-31 14:50:00
#OTA #RAUC #A/B分区 #边缘网关 #嵌入式Linux #运维安全
一、 场景痛点:一次失败的升级,赔了 20 万差旅费
去年,我们接手了一个光伏电站运维项目的“烂摊子”:
现状:前任集成商在 2000 台网关上部署了一个 Python 采集脚本。
事故:为了修复一个 Bug,运维人员写了一个 Shell 脚本:systemctl stop app && git pull && systemctl start app,并通过 SSH 批量下发。
灾难:
网络中断:偏远山区信号差,git pull 拉到一半断网了,文件损坏。
断电:有 50 台设备在写入文件时现场突然停电,文件系统损坏。
结果:150 台设备无法启动(Boot Loop)。工程师不得不开车几千公里,一台台拆机重刷固件。
工业级 OTA 必须满足 “Atomic (原子性)” 和 “Rollback (自动回滚)”。如果升级失败,系统必须能自动切回旧版本继续运行。
二、 架构设计:A/B 对称分区 (Dual-Bank)
我们采用 RAUC (Robust Auto-Update Controller) 框架,配合 U-Boot 实现双系统分区机制。
磁盘布局:
Slot A (System 0): 当前运行的系统。
Slot B (System 1): 闲置分区,用于接收 OTA 包。
Data Partition: 独立的数据分区,存放配置和数据库(升级时不擦除)。
流程:
设备运行在 Slot A。
OTA 进程将新镜像写入 Slot B。
设置 Bootloader 标记:“下次尝试从 B 启动”。
重启。
关键点:如果 Slot B 启动成功,标记为“Good”;如果启动失败(看门狗超时),Bootloader 自动切回 Slot A。
[Bootloader] --> [Slot A (Active)] / [Slot B (Standby)] <-- RAUC 写入
三、 核心实施步骤 (Copy & Paste)
假设你正在使用基于 Debian/Yocto 的 Linux 网关(如 RK3568/imx6ull)。
1. 定义系统配置 (/etc/rauc/system.conf)
这是 RAUC 的核心,告诉它怎么识别分区。
Ini[system] compatible=my-gateway-v1 # 硬件兼容性标识,防刷错包 bootloader=uboot # 对接 U-Boot [keyring] path=/etc/rauc/keyring.pem # 用于验证升级包签名的公钥 [slot.rootfs.0] device=/dev/mmcblk0p2 # A 分区 type=ext4 bootname=A [slot.rootfs.1] device=/dev/mmcblk0p3 # B 分区 type=ext4 bootname=B
2. 制作升级包 (Bundle Generation)
在开发机上,将做好的根文件系统 (RootFS) 打包并签名。
Bash# 1. 准备目录结构 mkdir -p update-bundle cp rootfs.img update-bundle/ # 编写 manifest (描述文件) echo '[update] compatible=my-gateway-v1 version=2.0.0 [image.rootfs] filename=rootfs.img' > update-bundle/manifest.raucm # 2. 签名并打包 (使用你的私钥) rauc bundle --cert cert.pem --key key.pem update-bundle/ update-2.0.0.raucb
结果:生成了一个 update-2.0.0.raucb 文件。这就是你要分发的固件。
3. 边缘端执行更新
将 .raucb 文件下载到网关(或通过 USB 插入),执行安装:
Bash# 安装升级包 rauc install update-2.0.0.raucb # 检查状态 rauc status # 输出示例: # System Name: my-gateway-v1 # ... # [slot.rootfs.0] # state=booted (当前运行) # [slot.rootfs.1] # state=active (已写入新系统,等待重启) # 重启生效 reboot
四、 踩坑复盘 (Red Flags)
1. 忽略了“数据持久化”
现象:升级完系统后,所有 MQTT 配置、Wi-Fi 密码、本地数据库全没了。
原因:RootFS 升级是全量覆盖。
对策:必须划分独立的 /data 分区,并将其挂载到 /etc/config 或 /var/lib 等目录。应用程序只能向 /data 写数据,严禁向 / (RootFS) 写数据。
2. U-Boot 环境未集成
现象:rauc install 成功了,但重启后还是进入了旧系统,或者卡死在 U-Boot。
原因:U-Boot 缺少 bootstate 相关的脚本逻辑,不知道如何切换分区。
对策:需要修改 U-Boot 的 bootcmd 脚本,引入 RAUC 提供的 bootchooser 逻辑。如果你买的是成品网关,务必确认厂家 BSP 是否已经适配了 RAUC。
3. 签名证书过期
风险:由于工业设备往往不连网,系统时间可能不准(回到1970年)。如果你在打包时证书有效期设置不当,会导致设备认为“升级包已过期”而拒绝安装。
对策:在 manifest 中显式关闭时间检查,或者确保设备有 RTC 电池。
五、 关联资源与选型
要跑这套 A/B 系统,硬盘空间得够大(两倍 RootFS),且 Bootloader 要开源。
硬件推荐:
米尔/飞凌 RK3568 核心板 (8GB eMMC):如果你不仅要跑系统,还要装 Docker,8GB eMMC 是不够的(两个系统就占 6GB)。建议选配 16GB eMMC 或 32GB 版本。
树莓派 Compute Module 4 (CM4):官方支持 tryboot 机制,配合 RAUC 非常顺滑。
一键配置脚本
不会配 U-Boot?
我们提供了一个 "RAUC 快速集成工具箱"。