结合OSTree和SW容器进行可靠的物联网设备更新

CNXSoft:这是Toradex技术解决方案架构师的Guest Post,通过Toradex技术解决方案架构师,解释了公司如何使用Ostree(AKA Libostree)开源操作系统构建和部署工具以及Docker软件容器更新Linux IoT设备固件。

每天都有越来越多的连接设备进入市场,对物联网(IoT)市场总规模的估计也越来越高<一个href="https://www.fortunebusinessinsights.com/industry-reports/internet-of-things-iot-market-100307">到2027年将达到1.5万亿美元.气泵、医疗设备和销售点系统越来越多地连接在一起,这使得几乎不可能避免与这些设备的交互,即使是完全的勒德主义者。在家庭中,电表、电灯开关和安全摄像头等设备通常都是联网的,从而实现了智能家庭功能。

这些设备的软件复杂度随着功能的增加而增加,并且该领域中存在软件缺陷的设备数量也在增加。在许多情况下,这些系统的设计、生产和交付都没有考虑到提供超出初始程序负载的软件更新。这是一个严重的问题,它可能会远远超出给设备所有者造成的问题,或增加制造商的保修或召回费用。在很多情况下,物联网设备可以被聚合成大型物联网僵尸网络,这些僵尸网络由于数量庞大,已经被用于大规模攻击基础设施的关键部分,如针对网络的分布式拒绝服务攻击(DDOS)<一个href="https://www.csoonline.com/article/3258748/the-mirai-botnet-explained-how-teen-scammers-and-cctv-cameras-almost-brought-down-the-internet.html">Dyn域名服务(DNS)提供商,导致Twitter和Github等大型组织的服务中断。

为什么要更新设备?<一个class="anchorlink dashicons-before" href="#why-update-devices">

在该领域为设备提供软件更新最明显的原因是为了解决软件漏洞。并不是所有的漏洞都会被利用,从而导致如上所述的大规模攻击,但这对您的品牌来说风险是很大的。随着用户家中的设备越来越多,可能会将多个设备的漏洞链在一起,以获得对用户数据的更广泛访问。在<一个href="https://www.businessinsider.in/Hackers-stole-a-casinos-high-roller-database-through-a-thermometer-in-the-lobby-fish-tank/articleshow/63769685.cms">一个值得纪念的事件在美国,一家不知名的赌场的豪赌客数据库被攻破,原因是一个联网鱼缸温度计的漏洞。大约有<一个href="https://codeinstitute.net/blog/how-many-lines-of-code-787/">1400万行代码(可能仅限于航空电子系统,不包括飞行中的娱乐系统等),而仅在Linux内核中就有大约2800万行代码(截至2020年1月)。亚博体育官下载请记住,Linux内核只是Linux系统的一部分,因此您可以开始感受这个问题的规模。这几行代码无疑将包含许多错误,需要在产品的整个生命周期中进行修复。

为您的设备提供更新功能还使您能够向用户交付新特性。根据你的商业模式,这可能有助于长期保留客户,或者只是提供追加销售能力和增加收入。考虑到更新功能的好处,您可能想知道为什么没有更新功能的设备会被发货。我努力定义一个完全不需要软件更新的用例。

OTA服务器<一个class="anchorlink dashicons-before" href="#ota-server">

任何完全自动化的OTA更新解决方案都需要一台服务器来管理车队,并允许您的操作人员管理设备。深入讨论服务器端已经超出了本文的范围,但是有很多选择。通常,您需要选择一个端到端解决方案,这意味着更新服务器和更新客户端都已开发为完整的解决方案,或者至少服务器和客户端的组合已经过良好的测试并相互集成。

更新方法<一个class="anchorlink dashicons-before" href="#update-methods">

有一些常见的方法允许软件更新。

  • 就地包更新:这是大多数桌面操作系统使用的机制。基本上,安装程序或打包系统运行在当前活动的操作系统镜像中。这可以安装系统所需要的任何东西,但可能很难确保你的机队中的所有设备都运行着与你在设计实验室中测试过的完全相同的二进制文件。
  • 不对称图像更新:这种方法通常使用一个独立的安装程序分区,能够下载适当的映像并覆盖主操作系统分区。这消除了部分安装的包集的问题,这些包集与就地更新一起发生,但会导致用户长时间的停机。直到最近,大多数手机更新都采用了这种方法,我敢肯定,我们都对这些更新所花费的时间感到恼火。
  • 对称图像更新(通常称为双A/B更新):该方法使用完全冗余分区,包括一个活动分区和一个被动分区。在活动分区中运行时,更新客户机可以下载完整的映像并将其安装到被动分区中。由于这一切都可能在应用程序代码处于活动状态时在后台发生,因此它消除了不对称图像带来的停机问题。但是,由于它使用完全冗余的分区,因此它通常比其他方法占用更多的块设备存储空间。
  • 基于OSTree更新:这是下一节的主题,它提供了多种功能,允许最小的设备停机时间,并且不需要额外的存储空间来容纳冗余分区。

OSTree<一个class="anchorlink dashicons-before" href="#ostree">

的<一个href="https://ostreedev.github.io/ostree/">文档对于OSTree项目定义如下:

Libostree是一个共享库和一套命令行工具,它结合了一个“类似git”的模型,用于提交和下载可引导的文件系统树,以及一个用于部署它们和管理引导加载器配置的层。

这有点模糊,所以让我们看一个例子。首先,我们将在开发工作站的子目录中创建一个空存储库。OSTree通常用于整个文件系统,但为了简单起见,我们将在本例中使用一个目录。


我们已经初始化了一个空存储库。您可以看到它已经创建了许多空目录和一个配置文件。存储库元数据与git有很多共同之处。您可以看到类似于refs/heads的熟悉目录。现在让我们向存储库添加一个文件:


我们看到已经创建了许多新的对象。.dirmeta、.dirtree和.commit文件是元数据,分别跟踪文件和目录元数据(权限、所有权等)、目录树结构和提交元数据。refs/heads/main文件包含了新的提交的提交哈希值:


还要注意,使用.file扩展名创建的对象与我们创建的文件相同。这通常被称为<一个href="https://yurichev.com/blog/CAS/">content-addressable存储这意味着对象存储库中的文件是根据其内容命名的。对象的名称(在本例中为92/d6c7afcaedabd4504d2e16de3ffc200cd156ac733306cf7b8991f56859bcd5.file)是由文件本身的sha256sum以及文件属性生成的。


需要注意的是,这些文件实际上是指向相同文件系统块的硬链接。这是OStree的一个重要原则,表明它将非常节省空间;在版本之间保持不变的任何文件都不会被复制,从而大大节省了设备上的块存储空间,以及在获取新版本时的下载带宽。


就像Git一样,我们可以删除文件,然后从存储库中退出。


现在,让我们向存储库添加一个完整的根文件系统。我为QEMU Arm设备创建了一个简单的文件系统<一个href="//ytpoint.com/news/buildroot">Buildroot


现在我们将创建文件系统的第二个版本。我已经使用了以前的Buildroot配置,并添加了bc实用程序,列在目标包\其他当运行make menuconfig。


现在,假设我们决定不再要bc二进制。不需要重新构建,我们可以简单地回滚到上一个版本。首先,我们检查bc是否存在于当前的文件系统中;然后我们回滚;最后,我们再次验证BC是一个指向busybox的符号链接:


对空中更新系统很重要的最后一个功能是远程存储库。类似于Git如何使用存储库,这些都是包含ostree元数据的远程访问数据存储。此示例在Toradex Verdin i.mx8m Mini系统运行时运行<一个href="https://www.toradex.com/torizon">Torizon这是一个<一个href="//ytpoint.com/2019/05/03/toradex-torizon-industrial-linux-windows-developers/">工业嵌入式Linux系统基于OSTree。我们把它连接到<一个href="https://developer.toradex.com/knowledge-base/ostree">toradex orizo​​ncore ostree存储库并查看最新的夜间发布。还有一些其他细节(这里没有介绍)与引导时切换到新版本的文件系统有关,因此它是一个原子操作。


有了OSTree所展示的功能集,我们就有了OTA更新系统所需的基本功能:

  • 存储整个文件系统的多个版本的能力。
  • 保留旧版本用于提供健壮的回滚功能。
  • 硬链接用于优化存储空间。
  • 远程存储库允许连接的设备通过“空中”下载更新。

OSTree物联网设备

容器<一个class="anchorlink dashicons-before" href="#containers">

容器是操作系统级虚拟化的一种形式,允许独立的环境运行应用程序。它们与虚拟机的不同之处在于,它们不会虚拟化整个硬件平台,也不会运行完整的操作系统。他们的主要用例是用应用程序需要运行的所有依赖项、库等来封装应用程序。在容器中设置应用程序可以确保满足所有依赖项,而无需在基本操作系统中安装其他软件包。例如,如果您正在运行一个NodeJS应用程序,您将把它打包到一个包含JavaScript运行时和所有其他所需组件的容器中。您可以指定每个依赖项的版本,一起测试所有内容,然后部署精确的组合;这消除了对基本操作系统映像可能具有不同版本的特定软件包的担忧。此外,如果需要,它允许不同的容器包含不同版本的组件;例如,您可以使用PythonV2运行一个运行python应用程序的包,使用需要PythonV3的包运行另一个容器。

除了依赖项管理之外,容器还可以与系统的其他组件隔离,从而潜在地提高安全性。使用基本操作系统内核的标准特性,容器可以被限制在文件系统的某些部分、某些设备,甚至被限制在多核系统中的特定CPU。根据您所使用的容器运行时,您可能能够限制单个容器的总体CPU或内存使用量,从而允许系统根据使用模式进行调整。

容器系统的第三个主要特征是其内置的交付机制。使用docker(最流行的容器引擎之一),您可以创建继承许多容器功能的新容器<一个href="https://hub.docker.com">基地图片由各种软件提供商提供。如果您有一个用Python V3编写的应用程序,并且希望在Debian样式环境中运行它,您可以创建一个如下所示的Dockerfile:


然后,您可以在包含应用程序的同一目录中创建MyApp.py文件。我们将使用以下内容作为我们的测试应用程序:


现在,您可以在构建系统上直接构建并运行此容器,步骤如下:


第一个命令以myapp和最新版本的名称构建图像和标记。第二个命令使用Dockerfile中指定的start命令和CMD语句运行容器。请注意,此时我们明确地不在嵌入式设备上运行。您可以使用容器在桌面上进行大量的开发和故障排除。对于许多应用程序开发任务来说,这比直接在嵌入式设备上进行开发更有效。当您准备在嵌入式设备上运行容器时,您可以将整个工作目录复制到您的设备并重新运行上述命令。当你在测试或处理少量设备时,这将起作用,但随着你的机队规模的增加,你需要一个更好的交付机制。码头工人提供<一个href="https://docs.docker.com/docker-hub/repos/">一种方便的机制分享图片。当我们在Dockerfile中指定FROM语句时,我们已经使用了这个。这指示docker将我们的映像基于docker hub上可用的python:buster映像。您还可以将映像推送到docker中心或任何其他docker存储库,这在希望保持容器私有时非常有用。一旦你创建了一个docker hub帐户,你可以为目标架构创建你的自定义映像,并使用以下方式发布它:


因为我们为Arm32、Arm64和AMD64创建了版本,所以你可以基于这些架构从任何系统运行你的映像,如下所示:


灵活、熟悉的软件环境以及内置的打包和交付机制的组合,使容器成为使用应用程序部署环境的有力理由。

OTA更新器<一个class="anchorlink dashicons-before" href="#ota-updater">

OStree和容器的结合提供了丰富的功能集,我们可以从中开发完整的OTA更新功能。综上所述,这两个项目提供了一个强大的系统,能够处理当前正在开发的连接设备的需求。

如上所述,OSTree提供:

  • 用于管理操作系统二进制文件的稳定、强大的容错机制。
  • 有效利用存储和下载带宽,能够重用任何未修改的文件。
  • 回滚功能以确保破坏更新不会使您的舰队无生命。

使用容器来容纳你的应用程序堆栈提供:

  • 灵活且熟悉的软件开发环境。您的开发人员可以继续在桌面Linux系统中使用他们已经熟悉的工具。
  • 内置的包装和交付。我们不需要在这里重新发明轮子,可以利用业界经验证的解决方案。
  • 活跃的开发者社区。可重用的文档、博客文章和现成容器的数量是巨大的,可以作为您开发工作的起点。

使用这样的系统可以更新系统中的任何组件,包括内核、设备树和应用程序代码。如果部署得当,您可以确保设备在其整个生命周期内运行良好。

对于最有用的更新能力,它需要自动,无人看管,并在某种网络连接上提供;通常称为空中(OTA),但这并不一定意味着无线连接。这些设备的用户不会将它们视为需要维护的计算机,而是他们将它们视为应该“只是工作”的设备。如果更新需要用户干预,则可能在船队中拥有许多过日期的设备。有用例,例如医疗设备,其中设备的连接可以故意限制,但即使在这些情况下,更新应该是可行的,例如当设备连接到其对接站时,更新应该自动化。

安全<一个class="anchorlink dashicons-before" href="#security">

虽然安全不是本文的重点,但如果我们至少没有讨论它,我们会被遗漏。对任何软件系统的最大威胁之一是运行任意代码的能力。由于OTA更新系统的整个点是要在系统上安装和运行的新代码,必须采取极端注意以确保已安装的代码尚未篡改,并且是系统的预期图像。

考虑以下几点:

  • 物理安全:您可能已经控制了服务器基础设施,所以要确保尽可能地锁定物理访问。但是请注意,这对于客户端设备不太可能。
  • 传输加密:必须确保客户端和服务器之间的传输是正确加密的。理想情况下,您将在两个端点上使用正确的TLS证书验证,以确保您正在与预期的设备进行通信。
  • 图像验证:您的客户端设备需要一种机制来验证正在安装的映像。加密验证应用于防止任意软件安装。
  • 安全密钥管理:任何安全架构都依赖于某种密钥。体系结构应该提供使旧键过期和旋转新键的机制,并提供适当的键保护。

有一些开源框架提供了非常安全的设计,您可以使用它们来实现OTA更新系统。的<一个href="https://theupdateframework.io">更新的框架和<一个href="https://uptane.github.io">uptane.如果你需要设计一个自定义更新系统,你应该考虑两个值得注意的项目。

有许多开源项目实现OTA更新系统,您可以集成到您的设计中,以避免设计系统的开销和风险。Torizo​​n平台是我目前参与的项目,并实现了本帖子中所述的完整OTA系统。OSTree提供有限的安全功能,如加密签名提交和Delta对象。Torizo​​n基于Uptane架构,为现成的高度安全的端到端OTA更新解决方案提供了一种。

结论<一个class="anchorlink dashicons-before" href="#conclusion">

我们已经讨论了如何将几个开源项目组合为基础设施,以创建一个完全自动化的端到端OTA更新解决方案。

在我们的主要操作系统存储中使用OSTree可以提供非常节省空间的解决方案,并且不需要使用完全冗余的分区。它提供原子的、事务性的更新,从而使设备用户的停机时间最小化。OSTree经过精心设计,对不可预测的电源周期具有弹性,并允许在更新检测到问题时进行回滚。

对应用程序堆栈使用容器提供了一种方便的打包和交付机制,可以独立于基本操作系统进行处理。容器相对容易使用,许多开发人员已经掌握了使用它们的技能。您可以选择与桌面Linux发行版相匹配的基本映像,它将允许您在熟悉的环境中使用丰富的工具集。或者您可以选择容器优化的基本映像(例如<一个href="https://alpinelinux.org/">高山Linux.),设计为小型,本质上更安全;毕竟最安全的软件是那些没有安装的软件

在为开发人员考虑构建的再现性、可维护性和灵活性时,将容器和OSTree组合在一起提供了最好的方法。使用一个系统,比如Torizon,可以提供一个使用这里描述的体系结构的现成解决方案。这允许您快速开始开发应用程序,而不必担心otree、容器和OTA更新的细节,同时您知道您有一个可靠的解决方案来管理您的设备舰队的生命周期。亚博体育官下载

为你的设备提供适当的更新应该被认为是任何现代连接设备设计的必要条件。这给你的用户和品牌带来的风险太大了,不容忽视。

分享这个:

支持CNX软件!www.yabo188.vip捐赠Via贝宝或者cryptocurrencies成为一个老板在Patreon,或购买评论样本

广告