balena Fin是一款树莓派CM3/3+ 的载板,它是专为利用Balena提供车队管理服务的工业应用而设计的。我在2019年3月的时候收到过一套balenaFin 开发者套件。当时我进行了详细的评测,在评测的第一部分我展示了如何组装该套件。
在19年4月的时候我又花了一些时间来评测balenaFin套件、BalenaOS以及balenaCloud 。BalenaOS是经过优化的Linux操作系统,它可在嵌入式设备上运行Docker容器,而balenaCloud服务则可从web仪表板管理一组设备。
我本文的评测主要按照 balenaOS和 balenaFin的入门指南中的说明进行操作,同时我也说明了我在准备镜像时必须要做的工作,以及如何将镜像烧录到开发板上。当然我也说明了如何在本地和通过 balenaCloud 加载示例 docker 应用程序。
为 balena Fin 下载和配置 BalenaOS
你们可以在下载页面中找到 BalenaOS 。注意当使用基于树莓派的计算模块硬件时,请确保选择“Fin”而不是“Raspberry Pi”。

我最初下载的是“Production”版本而不是“Development”版本。但在后来我评测之后,我得出一个经验最好先下载“Development”版本。等一下我给大家解释原因。
获得文件后,我们就可以解压缩固件:
1 |
unzip balena.img.zip |
下一步是安装 Balena CLI,这是一个基于 node.js 的命令行工具,用于开发基于 balenaOS 的应用程序容器。首先,我们需要最新版本的 node.js 和 npm,然后使用 nvm(节点版本管理器)脚本安装它们:
1 |
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash |
退出当前终端,然后重启一个终端来安装node.js:
1 |
nvm install node |
最后我们就可以安装 balena-cli:
1 2 3 |
sudo chown -R $USER:$GROUP ~/.npm sudo chown -R $USER:$GROUP ~/.config npm install --global --production --unsafe-perm balena-cli |
请注意,在这里必须要运行两次chown 命令从而避免以下类型的权限问题:
1 |
Unhandled rejection Error: EACCES: permission denied, open '/home/jaufranc/.npm/_cacache/tmp/6f8b51b1' |
我最开始尝试通过 apt 安装 npm,但遇到了各种问题,所以我个人建议使用 nvm。
对于大多数嵌入式设备,你要烧录镜像,然后启动设备,并在设备上配置所有内容。但使用 BalenaOS 则有点不同,我们可以先配置 balenaOS 镜像从而连接到 WiFi 网络,接着配置板主机名,然后从主机禁用持久日志记录来延长 eMMC flash的寿命:
1 2 3 4 5 6 7 |
$ sudo env "PATH=$PATH" balena local configure balena.img ? Network SSID CNX-SOFTWARE-ZTE ? Network Key superSecretPassword ? Do you want to set advanced settings? Yes ? Device Hostname cnxsoft-balena ? Do you want to enable persistent logging? No Done! |
在这里必须要在命令行中添加env “PATH=$PATH”,否则 sudo 会找不到 balena 命令。另外,需要注意,以普通用户身份运行也会失败。
使用 balena Etcher 刷写 balena.img 镜像
现在我们的镜像已经准备好了,可以使用balena Etcher GUI 程序通过 USB 来烧录镜像。我们可以通过 apt 来安装balena etcher程序:
1 2 3 4 |
echo "deb https://deb.etcher.io stable etcher" | sudo tee /etc/apt/sources.list.d/balena-etcher.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 379CE192D401AB61 sudo apt update sudo apt install balena-etcher-electron |
但后来我意识到现在安装的是 balena Etcher v1.4.9 版,而烧录树莓派CM3+ 需要1.5.0以上的版本。因此,我手动下载了最新的 Linux x64 的v1.5.19版本的软件安装到了我的系统上。
通过 micro USB 端口和提供的 USB 线将开发板连接到你的计算机上(此时不需要连接板子的电源)。

我们可以选择镜像(balena.img),并且在balena Etcher中选择Compute Module。这时该板确实被正确检测到了。
1 2 3 4 5 6 |
[43548.078939] usb 1-2.1: new high-speed USB device number 8 using xhci_hcd [43548.279965] usb 1-2.1: config index 0 descriptor too short (expected 55, got 32) [43548.281093] usb 1-2.1: New USB device found, idVendor=0a5c, idProduct=2764, bcdDevice= 0.00 [43548.281096] usb 1-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [43548.281098] usb 1-2.1: Product: BCM2710 Boot [43548.281100] usb 1-2.1: Manufacturer: Broadcom |
所以我决定打开一个终端,并使用 sudo 启动该工具:
1 |
sudo ./balenaEtcher-1.5.19-x64.AppImage |
并且……成功了!

初始化计算模块需要花几秒钟,之后就会显示为7.82 GB的存储设备,我们终于可以点击Flash开始烧录了,完成烧录大约需要4分钟。
该板不会通过 USB 端口供电运行,因此我们需要将其连接到附带的电源上从而使其启动并运行,然后我们就可以在几秒钟后尝试 ping 它:
1 2 3 4 5 6 7 8 9 10 11 |
ping cnxsoft-balena.local PING cnxsoft-balena.local (192.168.1.7) 56(84) bytes of data. 64 bytes from cnxsoft-balena (192.168.1.7): icmp_seq=1 ttl=64 time=85.0 ms 64 bytes from cnxsoft-balena (192.168.1.7): icmp_seq=2 ttl=64 time=3.91 ms 64 bytes from cnxsoft-balena (192.168.1.7): icmp_seq=3 ttl=64 time=1.91 ms 64 bytes from cnxsoft-balena (192.168.1.7): icmp_seq=4 ttl=64 time=1.93 ms 64 bytes from cnxsoft-balena (192.168.1.7): icmp_seq=5 ttl=64 time=1.92 ms ^C --- cnxsoft-balena.local ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4003ms rtt min/avg/max/mdev = 1.914/18.941/85.022/33.049 ms |
好的,这就意味着开发板可以自动连接到 WiFi 路由器了。其实理论上,我们应该也可以通过 ssh 直接连接到板子:
1 |
sudo env "PATH=$PATH" balena local ssh mydevice.local --host |
但ssh却连接不上:
1 |
root@cnxsoft-balena.local: Permission denied (publickey). |
所以我尝试了一个没有 sudo 的替代命令:
1 |
ssh root@cnxsoft-balena.local -p22222 |
但结果还是一样。经过一些研究,我发现ssh 大概只能在 BalenaOS 的Development版本中使用。
于是我下载了Development版本并烧录到了板子里,重新通过ssh连接开发板,终于可以登录系统了。于是我运行了几条命令查看了下系统信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
sudo env "PATH=$PATH" balena local ssh cnxsoft-balena.local --host root@cnxsoft-balena:~# uname -a Linux cnxsoft-balena 4.14.98 #1 SMP Fri Mar 22 07:02:01 UTC 2019 armv7l armv7l armv7l GNU/Linux root@cnxsoft-balena:~# balena-engine version Client: Version: 17.12.0-dev API version: 1.35 Go version: go1.9.7 Git commit: fe78e2c9a69313007c53c83fff4b5525fbc2ba45 Built: Mon Mar 11 15:28:35 2019 OS/Arch: linux/arm Experimental: false Orchestrator: swarm Server: Engine: Version: 17.12.0-dev API version: 1.35 (minimum version 1.12) Go version: go1.9.7 Git commit: fe78e2c9a69313007c53c83fff4b5525fbc2ba45 Built: Mon Mar 11 15:28:35 2019 OS/Arch: linux/arm Experimental: true root@cnxsoft-balena:~# |
我原以为安装镜像很容易,可实际上并不是,还好一番折腾之后终于把系统装好了。
在 balena Fin 中运行docker
现在我们可以在我们的主机上克隆一个演示项目:
1 |
git clone https://github.com/balena-io-projects/multicontainer-getting-started.git |
进入该目录,并发出命令来构建演示并将其加载到板中:
1 2 |
cd multicontainer-getting-started/ balena push 192.168.1.7 |
请注意,我们需要使用 IP 地址而不是主机名(即 cnxsoft-balena.local)。
这是我第一次尝试的输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[Info] Starting build on device 192.168.1.7 [Info] Compose file detected [Build] [data] Step 1/7 : FROM balenalib/fincm3-debian-node:10-stretch-run [Build] [frontend] Step 1/12 : FROM balenalib/fincm3-debian-node:10-stretch-run [Build] [proxy] Step 1/3 : FROM arm32v6/haproxy:1-alpine [Build] [proxy] ---> 4e28d48faf2e [Build] [proxy] Step 2/3 : COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg [Build] [proxy] ---> bb68b59f16e3 [Build] [proxy] Step 3/3 : LABEL "io.resin.local.image"='1' "io.resin.local.service"='proxy' [Build] [proxy] ---> Running in 598214b13ea1 [Build] [proxy] Removing intermediate container 598214b13ea1 [Build] [proxy] ---> 6b45ce51a36e [Build] [proxy] Successfully built 6b45ce51a36e [Build] [proxy] Successfully tagged local_image_proxy:latest Some services failed to build: frontend: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout data: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout Additional information may be available in debug mode. Prefix the command line with DEBUG=1, i.e.: DEBUG=1 balena ... If you need help, don't hesitate in contacting our support forums at https://forums.balena.io For bug reports or feature requests, have a look at the GitHub issues or create a new one at: https://github.com/balena-io/balena-cli/issues/ |
似乎由于网络问题引起的超时,运行并没有成功,于是我使用 DEBUG=1 重新启动命令:
1 |
DEBUG=1 balena push 192.168.1.7 |
这次它就完成了:
1 2 3 4 5 6 7 8 9 10 11 |
[Logs] [4/10/2019, 8:00:37 PM] [frontend] [Logs] [4/10/2019, 8:00:37 PM] [frontend] > resin-websocket@1.0.0 start /usr/src/app [Logs] [4/10/2019, 8:00:37 PM] [frontend] > node index.js [Logs] [4/10/2019, 8:00:37 PM] [frontend] [Logs] [4/10/2019, 8:00:37 PM] [data] [Logs] [4/10/2019, 8:00:37 PM] [data] > resin-websocket@1.0.1 start /usr/src/app [Logs] [4/10/2019, 8:00:37 PM] [data] > node index.js [Logs] [4/10/2019, 8:00:37 PM] [data] [Logs] [4/10/2019, 8:00:38 PM] [frontend] server is listening on port 80 [Logs] [4/10/2019, 8:00:40 PM] Started service 'proxy sha256:6b45ce51a36e917161594bf5ed5b307012c0ee6516e4abadfb451183cb674ef9' [Logs] [4/10/2019, 8:00:39 PM] [proxy] [NOTICE] 099/130039 (1) : New worker #1 (7) forked |
所以这可以证明我们之前真的只是遇到了网络问题,其他都是正常的。单击此处可以获得完整日志。
该应用程序创建了我们设备的 CPU 平均负载和内存使用情况的图表,只需在网络浏览器中输入 IP 地址或在地址栏中输入主机名即可访问该图表。

从 balenaCloud 管理 balenaFin
balenaCloud 是可选的,它真的很方便,因为你可以轻松地将应用程序推送到云端,并通过无线方式将其推送到你所有的设备当中。我接下来讲解怎么使用balenaCloud 管理 balenaFin。
首先,注册balenaCloud账号(最多有10台设备能免费)。注册后,开始创建应用,点击Create application按钮,填写应用名称(如multicontainer),选择Balena Fin (CM3)设备类型,以及Starter应用类型,然后单击“创建新应用程序”按钮。

接着,单击Add Device,启用以太网+WiFi(如果你打算使用 WiFi),输入 WiFi 凭据,定制Development镜像版本。然后单击下载 balenaOS按钮,把定制的Development镜像下载到电脑。下载完成后,我们就可以像之前一样将它刷到板子上。还有一个下载配置文件的选项,在我们的示例中这可能是一个更好的选择,因为我们之前已经刷新了操作系统。我认为我们可以通过 SSH将文件推送到 /boot/config.json从而来更新开发板。
现在我们可以回到我们在上一节中从 Github 下载的 multicontainer -getting-started的目录,将其上传到我们的 balenaCloud 帐户:
1 |
git remote add balena <username>@git.balena-cloud.com:<username>/<applicationname>.git |
其中 <username> 是你 balenaCloud 帐户的用户名,applicationname 是你在仪表板中定义的应用程序名称,在本例中为“multicontainer”。该命令花了一分钟多一点,最终成功了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
[Success] Successfully uploaded images [Success] Release successfully created! [Info] Release: 89ae9a1f756843db93cf0fa02ce7f2c4eb4db6ea (id: 868612) [Info] ┌──────────┬────────────┬────────────┐ [Info] │ Service │ Image Size │ Build Time │ [Info] ├──────────┼────────────┼────────────┤ [Info] │ frontend │ 191.04 MB │ 50 seconds │ [Info] ├──────────┼────────────┼────────────┤ [Info] │ proxy │ 16.95 MB │ 5 seconds │ [Info] ├──────────┼────────────┼────────────┤ [Info] │ data │ 191.66 MB │ 14 seconds │ [Info] └──────────┴────────────┴────────────┘ [Info] Build finished in 1 minute, 8 seconds \ \ \\ \\ >\/7 _.-(6' \ (=___._/` \ ) \ | / / | / > / j < _\ _.-' : ``. \ r=._\ `. <`\\_ \ .`-. \ r-7 `-. ._ ' . `\ `, `-.`7 7) ) \/ \| \' / `-._ || .' \\ ( >\ > ,.-' >.' <.'_.'' <' To git.balena-cloud.com:cnxsoft/multicontainer.git * [new branch] master -> master |
过了一会儿,我们应该就会在仪表板中看到我们的 balena Fin 板正在更新我们的 docker 应用程序。

完成后,我们可以点击设备名称“ancient-tree”,访问更多信息,并启用“PUBLIC DEVICE URL”。

单击它旁边的上升蓝色箭头,可以打开一个新的浏览器窗口,就能看到显示的 CPU 平均负载和内存使用情况。

使用balenaCloud 时,你可以根据需要添加车队中所有的设备并将它们链接到特定的应用程序上。一旦初始配置完成,你就可以轻松地更新它们了。
如要你们还想更进一步地研究,他们的文档可以帮助你使用 Balena 生态系统开发、部署和管理 Docker 应用程序。
我本文测评的 balena Fin 开发套件售价是199美元,运费需要另外付。如果你不需要 DIN 导轨外壳,你可以选择“no case”选项,这样会便宜 20 美元。

文章翻译者:Taylor Lee,瑞科慧联(RAK)高级嵌入式开发工程师,有丰富的物联网和开源软硬件经验,熟悉行业主流软硬件框架,对行业发展动向有着敏锐的感知力和捕捉能力。