驱动数字化 质变

从权威的技术洞察,到精准的软硬配置,为企业的每一次转型提供决策支持。

架构师笔记
[架构实战] 别再用 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 批量下发。

  • 灾难

  1. 网络中断:偏远山区信号差,git pull 拉到一半断网了,文件损坏。

  2. 断电:有 50 台设备在写入文件时现场突然停电,文件系统损坏。

  3. 结果: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: 独立的数据分区,存放配置和数据库(升级时不擦除)。

流程

  1. 设备运行在 Slot A。

  2. OTA 进程将新镜像写入 Slot B。

  3. 设置 Bootloader 标记:“下次尝试从 B 启动”。

  4. 重启

  5. 关键点:如果 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 快速集成工具箱"