meta-balena:实践指南
2026-09-12
2026-09-12 0
面对实际交付,我看meta-balena的重点不在星标,而在这项能力:用于构建 balenaOS 图像的 Yocto 层集合。团队若要把它用于图像与视觉生产,应先处理风格、尺寸和资源格式容易偏离预期,否则试用结果很容易失真。我建议拿一份明确的视觉参考完成小样,重点记录构图、尺寸、资源可用性和导出质量,再与现有方案比较。它更像给需要可复现视觉结果的设计与内容团队准备的可审查方案,是否长期使用应由试跑数据决定。
Yocto 的 Balena.io 层
描述
该存储库可以为各种设备构建 balenaOS。
层结构
依赖关系
版本控制
meta-balena 版本保存在 DISTRO_VERSION 变量中。 balena- 版本保存在位于 balena- 存储库根目录中名为 VERSION 的文件中,并在构建中作为变量 HOSTOS_VERSION 读取。
meta-balena 的版本采用 semver 格式,由点分隔的 3 个数字组成。补丁号可以有 beta 标签。 e.g。 1.2.3、1.2.3-beta1、2.0.0-beta1。meta-balena 版本 X.Y.Z 的第一个 balena- 版本将是 X.Y.Z,与 meta-balena 版本相同。示例:基于 meta-balena 1.2.3 的第一个 balena- 版本将为 1.2.3。balena- 版本是通过向 meta-balena 版本附加 rev 标签来构建的。例如,meta-balena 1.2.3 可以经历 3 个主板修订版,即 1.2.3 为初始修订版,1.2.3+revN 为后续修订版,最终版本为 1.2.3+rev2 。balena-中更新meta-balena版本时,版本将重置为meta-balena版本。例如: 1.2.3+rev4 将更新为 1.2.4 。我们将主机 OS 版本定义为 balena- 版本,并将该版本用作 HOSTOS_VERSION。
建立标志
在使用 meta-balena 支持进行 bitbake 之前,可以在构建目录中的 conf/local.conf 中更改一些标志。 local.conf 的编辑应在源码完成后进行。 有关此类构建标志的说明,请参阅下文。
配置自定义网络管理器
默认情况下,balena 使用主机 OS 上的 NetworkManager 来提供连接。如果您想更改并使用其他提供商,请使用 NETWORK_MANAGER_PACKAGES 列出您的软件包。您可以将此变量添加到 local.conf。这是一个例子:
NETWORK_MANAGER_PACKAGES =“mynetworkmanager mynetworkmanager-client”
自定义启动画面
我们将所有初始映像配置为在启动、关闭或重新启动时生成 balena 徽标。但我们鼓励任何用户用自己的徽标替换该徽标。
您所要做的就是用您自己的映像替换您在映像的第一个分区(启动分区)中找到的 splash/balena-logo.png 文件。
NOTE:按照目前的情况,普利茅斯希望该映像被命名为 balena-logo.png。在旧版本中,此文件称为 resin-logo.png。
Docker存储驱动
默认情况下,构建系统将设置 docker 能够使用 aufs 存储驱动程序所需的所有位。这可以通过在 local.conf 中定义 BALENA_STORAGE 来更改。它支持aufs和overlay2。
OS开发
要配置禁用安静启动并允许引导加载程序 shell 访问的开发版本,请编辑该版本的 local.conf 添加:
OS_DEVELOPMENT = "1"
这是仅用于开发的设置,不会部署 OS_DEVELOPMENT 配置的映像。
OS
SSH 和 Avahi 服务
OS 在端口 22222 上运行 SSH (openSSH)。运行此服务利用套接字激活 systemd 功能,因此 SSH 守护进程仅在存在到设备的 SSH 连接时运行,以这种方式节省空闲资源。为了连接到设备,可以使用已知的 IP 或通过 mDNS 解析主机名,因为其主机名是使用 avahi 服务通过网络公布的。当使用后者时,需要配置客户端(参见例如https://wiki.archlinux.org/index.php/Avahi#Hostname_resolution)。
时间同步
启动时,时间设置和同步如下:
构建时间
最初时间是根据映像构建时间时间戳设置的,存储在 /etc/timestamp 中,并在生成映像时由构建系统生成。
上次启动系统时间
然后,系统检查先前的引导系统时间是否存储在持久存储器中,并使用它来纠正时间。时间按每小时计时器以及系统重新启动或关闭时存储在持久存储器中。设置上次启动系统时间后开始记录。
RTC时间
当 RTC 可用 (/dev/rtc) 时,将启动 timeinit-rtc 服务,该服务使用从 RTC 读取的值更新系统时钟。如果没有可用的 RTC,该服务将不会执行任何操作。
HTTPs时间
在网络连接事件之后,假设之前尚未从 RTC 设置正确的系统时间,则使用 HTTPs 时间同步服务 timesync-https 来纠正 HTTP 标头时间戳中的时间。这保证了时间大致正确并且证书过期检查不会失败。其他网络服务将被保留,直到此时同步发生。默认情况下,时间同步使用 config.json 的 connectivity 部分中定义的 NetworkManager 连接 URL。要禁用 HTTPs 时间同步并允许其他服务运行,请将连接检查 URI 设置为“null”。这也将禁用 连接检查。
网络时间
chronyd 服务负责使用 NTP 管理之后的时间。它被配置为大约每 4 小时同步一次以节省带宽。如果 NTP 服务器变得无法访问,该服务将不断尝试更新时间。如果时间不同步,NTP 客户端服务将重新启动以纠正故障。
当 RTC 可用和不可用时,上面解释的时间保持框架都提供强大的时间初始化和管理。
引导装载程序
引导加载程序需要选择活动根文件系统、加载并启动 Linux 内核。它还管理启动计数和回滚。 BalenaOS 在受支持的设备系列中支持多个引导加载程序。
巴莱纳引导加载程序
支持的其他引导加载程序可用于启动 balena 引导加载程序(如果需要)或在不支持 kexec 的设备上:
U盘启动
蛴螬
启动程序
UEFI L4发射器
回滚框架
检查 docs/rollbacks.md 回滚文档
OS 更新锁
主机 OS 更新脚本(hostapp-update 中的 safe_reboot)在重新启动设备之前检查任何容器中 /tmp/balena/updates.lock 上的独占 flock()。如果进程在此文件上拥有独占的羊群,这些脚本将等到锁被释放后再继续重新启动。
这独立于 Supervisor 管理的应用程序更新锁定机制。 Supervisor 使用锁定文件(文件存在)来防止应用程序更新,而主机 OS 使用 flock() 来防止 OS 更新期间重新启动。
在关键操作期间,应同时使用两种机制以提供全面保护。有关应用程序更新锁定以及如何组合两者的详细信息,请参阅 Supervisor 更新锁定文档。
创建羊群
壳牌
使用 群 (Debian:util-linux 包):
flock /tmp/balena/updates.lock -c '... (command to run while locked)'
要在长时间运行的进程中保持锁定:
exec {FD}>/tmp/balena/updates.lock
flock -x $FD || exit 1
# ... critical section; safe_reboot will wait ...
exec {FD}>&-
蟒蛇
使用fcntl.flock(标准库):
import fcntl
import os
import time
LOCK_PATH = '/tmp/balena/updates.lock'
def with_update_lock(fn):
fd = os.open(LOCK_PATH, os.O_CREAT | os.O_EXCL | os.O_RDWR)
try:
fcntl.flock(fd, fcntl.LOCK_EX)
fn()
finally:
fcntl.flock(fd, fcntl.LOCK_UN)
os.close(fd)
try:
os.unlink(LOCK_PATH)
except OSError:
pass
with_update_lock(critical_function)
设备支持
WiFi 适配器
我们目前测试并提供对以下 WiFi 适配器的明确支持:
调制解调器
我们目前作为发布过程的一部分进行测试,并为以下调制解调器提供明确支持:
推荐 WiFi USB 加密狗
如何修复各种构建错误
Step 3 : RUN chmod 700 /entry.sh
---> Running in 445fe69866f9
operation not supported
这可能是因为 docker 错误,如果您更新内核并且不重新启动,docker 会感到困惑。修复方法是重新启动系统。 更多信息:http://stackoverflow.com/questions/29546388/getting-an-operation-not-supported-error-when-trying-to-run-something-while-bu
config.json
可以通过在引导分区中的 config.json 文件中设置以下键来配置 balenaOS 的行为。这个配置文件也被supervisor使用。
主机名
(字符串)设备的配置主机名,否则使用设备 UUID。
persistentLogging
(布尔值)启用或禁用设备上的持久日志记录 - 默认为 false。启用持久日志后,它们最终会作为设备上数据分区的一部分存储(在 SD 卡、eMMC、硬盘等上)。它位于设备上的 /var/log/journal/,其中 UUID 是可变的。
国家
(字符串)设备运行所在国家/地区的两个字母国家/地区代码。这用于设置 WiFi 监管域,您应该检查 WiFi 设备驱动程序以获取支持的国家/地区代码列表。
ntpServers
(字符串)用于时间同步的 NTP 服务器的空格分隔列表。默认为 resinio.pool.ntp.org 服务器:
0.resinio.pool.ntp.org1.resinio.pool.ntp.org2.resinio.pool.ntp.org3.resinio.pool.ntp.orgdnsServers
(字符串)用于名称解析的首选 DNS 服务器的空格分隔列表。
dnsServers 未定义或为空时,Google 的 DNS 服务器 (8.8.8.8) 将添加到通过 DHCP 获取或在 NetworkManager 连接配置文件中静态配置的 DNS 服务器列表中。dnsServers为“null”(字符串)时,Google的DNS服务器(8.8.8.8)将如上所述添加NOT。dnsServers 且不为“空”时,列出的服务器将添加到通过 DHCP 获取的服务器列表或通过 NetworkManager 连接配置文件静态配置的服务器列表中。balenaRootCA
(字符串)将安装到根信任存储中的 Base64 编码的 PEM CA 证书。这使得设备信任来自该机构的 TLS/SSL 证书。 当设备在重新加密的网络设备(例如透明代理或某些深度数据包检查设备)后面运行时,这非常有用。
"balenaRootCA": "4oCU4oCTQkVHSU4gQ0VSVElGSUNBVEXigJTi..."
developmentMode
要在运行时启用开发模式:
"developmentMode": true
默认情况下,开发模式允许未经身份验证的 SSH 登录,除非存在自定义 SSH 密钥,在这种情况下,将强制执行 SSH 密钥访问。
此外,开发模式提供串行控制台无密码登录以及暴露的 balena 引擎套接字以在本地模式开发中使用。
操作系统
包含在运行时自定义主机 OS 的设置的对象。
网络
无线网络
定义与 Wi-Fi 相关的配置的对象。
以下示例在扫描期间禁用 Wi-Fi 设备的 MAC 地址随机化:
"os": {
"network" : {
"wifi": {
"randomMacAddressScan": false
}
}
}
连接性
定义与网络连接检查相关的配置的对象。此功能基于 NetworkManager 的连接检查,该检查在连接部分 (此处为)中进行了进一步记录。
$API_ENDPOINT/connectivity-check。以下示例通过以 5 分钟间隔传递 balenaCloud 连接端点来配置连接检查。
"os": {
"network" : {
"connectivity": {
"uri" : "https://api.balena-cloud.com/connectivity-check",
"interval" : "300"
}
}
}
udevRules
包含一个或多个自定义 udev 规则(作为 key:value 对)的对象。
要将规则转换为可以轻松添加到 config.json 的格式,请使用以下命令:
cat rulefilename | jq -sR .
例如:
root@resin:/etc/udev/rules.d# cat 64.rules | jq -sR .
"ACTION!=\"add|change\", GOTO=\"modeswitch_rules_end\"\nKERNEL==\"ttyACM*\", ATTRS{idVendor}==\"1546\", ATTRS{idProduct}==\"1146\", TAG+=\"systemd\", ENV{SYSTEMD_WANTS}=\"u-blox-switch@'%E{DEVNAME}'.service\"\nLBEL=\"modeswitch_rules_end\"\n"
以下示例包含两个自定义 udev 规则,将创建 /etc/udev/rules.d/56.rules 和 /etc/udev/rules.d/64.rules。第一次添加规则或修改规则时,udevd 会重新加载规则并重新触发。
"os": {
"udevRules": {
"56": "ENV{ID_FS_LABEL_ENC}==\"resin-root*\", IMPORT{program}=\"resin_update_state_probe $devnode\", SYMLINK+=\"disk/by-state/$env{BALENA_UPDATE_STATE}\"",
"64" : "ACTION!=\"add|change\", GOTO=\"modeswitch_rules_end\"\nKERNEL==\"ttyACM*\", ATTRS{idVendor}==\"1546\", ATTRS{idProduct}==\"1146\", TAG+=\"systemd\", ENV{SYSTEMD_WANTS}=\"u-blox-switch@'%E{DEVNAME}'.service\"\nLBEL=\"modeswitch_rules_end\"\n"
}
}
sshKeys
(数组)包含公共 SSH 密钥列表的字符串数组,SSH 服务器将使用这些密钥进行身份验证。
"os": {
"sshKeys": [
"ssh-rsa AAAAB3Nza...M2JB balena@macbook-pro",
"ssh-rsa AAAAB3Nza...nFTQ balena@zenbook"
]
}
风扇
定义热相关配置的对象。适用于运行 Jetpack 6 或更高版本、balenaOS v6.1.24 或更高版本以及 Supervisor v16.10.0 或更高版本的 Jetson Orin 设备。
fan.profile
(字符串)用于选择所需冷却配置文件的字符串。支持的值为“quiet”和“cool”。在运行时,这 配置选项应通过 API 或从 balenaCloud 仪表板设置。
"os": {
"fan": {
"profile":"cool"
}
}
电源
定义功耗相关配置的对象。适用于运行 Jetpack 6 或更高版本、balenaOS v6.1.24 或更高版本以及 Supervisor v16.10.0 或更高版本的 Jetson Orin 设备。
power.mode
(字符串)用于选择所需电源模式的字符串。 Jetpack 6 及更高版本支持的值为“low”、“mid”和“high”,其中“low” 是最低功耗模式,而“高”对应于 MAXN 或您的设备类型的最高可用功耗模式。在运行时,这 配置选项应通过 API 或从 balenaCloud 仪表板设置,这将导致设备重新启动。
"os": {
"power": {
"mode":"high"
}
}
内核
允许配置内核设置的对象,这些设置在引导或运行时应用。
kernel.extraFirmwareVol
(字符串)用于指定用于存储附加固件的卷的名称的字符串。该卷用作 Linux 固件的附加搜索路径。 在运行时,此设置由 Supervisor 管理,默认卷名称为“extra-firmware”。
"os": {
"kernel": {
"extraFirmwareVol":"extra-firmware"
}
}
安装人员
配置 balenaOS 安装程序映像的行为的对象。
安全启动
(布尔值)选择安装安全启动和加密磁盘系统 支持的设备类型。
"installer": {
"secureboot": true
}
迁移
配置 balenaOS 安装程序迁移行为的对象 模块。
migrate.force
(布尔值)强制迁移运行。默认情况下,迁移仅在以下情况下运行:
安装程序在单磁盘系统或 migrate 参数中启动
在内核命令行中传递。
"installer": {
"migrate": {
"force": true
}
}
目标设备
(字符串)覆盖配置目标介质的默认列表。可能包含一个或多个 设备,用空格分隔。将使用第一个找到的。
"installer": {
"target_devices":"nvme0n1 sda"
}
Yocto 版本支持
支持以下 Yocto 版本: