你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

增量更新(预览版)

通过使用增量更新功能,可以生成一个小型更新,它仅表示两个完整更新(源映像和目标映像)之间的更改。 此方法非常适合用于减少将更新下载到设备的带宽,尤其是在源更新和目标更新之间只有少量更改的情况下。

注意

Azure Device Update for IoT Hub 中的增量更新功能目前为公共预览版

使用 Device Update for IoT Hub 增量更新的要求

  • 源和目标更新文件必须采用 SWUpdate (SWU) 格式。
  • 在每个 SWUpdate 文件中,必须有一个使用 Ext2、Ext3 或 Ext4 文件系统的原始映像。

增量生成过程使用 gzip 压缩重新压缩目标 SWU 更新,以达到最佳增量。 将重新压缩的目标 SWU 更新与生成的增量更新文件一起导入到 Device Update 服务。

增量处理器组件的 Device Update 代理配置

若要从 Device Update 服务下载和安装增量更新,设备需要使用安装和配置了更新处理程序和增量处理器组件的 Device Update 代理。

设备更新代理

设备更新代理协调设备上的更新过程,包括下载、安装和重启操作。 若要将 Device Update 代理添加到设备中,并对其进行配置以供使用,请参阅 Device Update 代理预配。 使用代理版本 1.0 或更高版本。

更新处理程序

更新处理程序与设备更新代理集成以执行实际的更新安装。 对于增量更新,如果还没有要修改的 SWUpdate 更新处理程序,请从microsoft/swupdate:2 更新处理程序开始。

增量处理器

下载增量文件后,Azure/iot-hub-device-update-delta 中的增量处理器会在设备上重新创建原始 SWU 映像文件,以便更新处理程序可以安装 SWU 文件。 若要将增量处理器组件添加到设备映像并对其进行配置以供使用,可以从 https://github.com/Azure/iot-hub-device-update-delta/tree/main/preview/2.0.0 下载适用于 Ubuntu 20.04 及更高版本的 Debian 包。

如果使用其他发行版,请按照 README.md 中的说明,转而使用 CMAKE 从源生成增量处理器。 在那里,通过将共享对象 libadudiffapi.so 复制到 /usr/lib 目录来直接安装它,如下所示:

sudo cp <path to libadudiffapi.so> /usr/lib/libadudiffapi.so
sudo ldconfig

将源 SWU 映像文件添加到设备

增量更新文件下载到设备后,它会与以前缓存在设备上的有效 <source_archive> 进行比较。 此过程会启用增量更新来重新创建完整的目标映像。

填充此缓存映像的最简单方法是,通过 Device Update 服务将完整的映像更新导入部署到设备。 如果设备已配置 Device Update 代理版本 1.0 或更高版本和增量处理器,该代理就会自动缓存已安装的 SWU 文件,便于以后使用增量更新。

如果想要直接在设备上预填充源映像,则映像的预期路径为 <BASE_SOURCE_DOWNLOAD_CACHE_PATH>/sha256-<ENCODED HASH>。 默认情况下,<BASE_SOURCE_DOWNLOAD_CACHE_PATH> 是 /var/lib/adu/sdc/<provider> 路径。 provider 值是源 SWU 文件的 updateIdprovider 部分。

ENCODED_HASH 是二进制的 SHA256 的 base64 十六进制字符串,但在对 base64 十六进制字符串进行编码后,它会对字符进行如下编码:

  • + 编码为 octets _2B
  • / 编码为 octets _2F
  • = 编码为 octets _3D

使用 DiffGen 工具生成增量更新

可以使用差异生成 (DiffGen) 工具创建增量更新。

环境先决条件

在使用 DiffGen 创建增量之前,需要在环境计算机上下载并安装多个项。 理想情况下,请使用 Ubuntu 20.04 Linux 环境,如果使用 Windows,则使用适用于 Linux 的 Windows 子系统。

下表显示了所需的内容、获取位置和建议的安装(如有必要)。

二进制名称 获取位置 如何安装
DiffGen Azure/iot-hub-device-update-delta GitHub 存储库 下载与要用于生成增量更新的计算机上的 OS 或发行版匹配的版本。
.NETCore 运行时,版本 8.0.0 通过终端或包管理器 在 Linux 上安装 .NET。 只需要运行时。

使用 DiffGen 创建增量更新

DiffGen 工具使用以下必需参数和语法运行:

DiffGenTool <source_archive> <target_archive> <output_path> <log_folder> <working_folder> <recompressed_target_archive>

上述命令运行创建 recompress_tool.py 脚本,该脚本会创建 <recompressed_target_file> 然后,DiffGen 使用 <recompressed_target_file> 而不是 <target_archive> 作为创建差异的目标文件。 <recompressed_target_archive> 中的图像文件使用 gzip 进行压缩。

如果 SWU 文件已签名,它们还需要 DiffGen 命令中的 <signing_command> 参数:

DiffGenTool <source_archive> <target_archive> <output_path> <log_folder> <working_folder> <recompressed_target_archive> "<signing_command>"

具有签名命令字符串参数的 DiffGenTool 运行 recompress_and_sign_tool.py 脚本。 此脚本会创建 <recompressed_target_file>。 此外,此脚本还对存档中的 sw-description 文件进行签名,以创建 sw-description.sig 文件。

可以使用 Azure/iot-hub-device-update-delta GitHub 存储库中的示例 sign_file.sh 脚本在输入源文件与重新压缩且重新签名的目标文件之间创建差异。 打开脚本并对其进行编辑,以将路径添加到私钥文件,然后保存该脚本。 有关示例用法,请参阅示例部分。

下表更加详细地描述了参数:

参数 说明
<source_archive> DiffGen 用作创建增量的起点的基本映像。 重要提示:此映像必须与设备上已存在的映像(例如从上一次更新中缓存的映像)相同。
<target_archive> 增量将设备更新到的映像。
<output_path> 主机上增量文件创建后所在的路径,包括生成的增量文件所需的名称。 如果路径不存在,该工具将创建它。
<log_folder> 主机上创建日志的路径。 最好将此位置定义为输出路径的子文件夹。 如果路径不存在,该工具将创建它。
<working_folder> 计算机上在增量生成期间放置附件和其他工作文件的路径。 最好将此位置定义为输出路径的子文件夹。 如果路径不存在,该工具将创建它。
<recompressed_target_archive> 主机上创建 <recompressed_target_file> 的路径。 使用 <recompressed_target_file> 而不是 <target_archive> 作为差异生成的目标文件。 如果在调用 DiffGen 工具之前存在此路径,则路径会被覆盖。 最好在输出路径的子文件夹中定义此文件。
"<signing_command>"(可选) 用于对 <recompressed_target_archive> 中的 sw-description 文件进行签名的可自定义命令。 重新压缩存档中的 sw-description 文件用作签名命令的输入参数。 DiffGen 希望签名命令使用追加了 .sig 的输入的名称创建新的签名文件。

必须用双引号将参数引起来,才能将整个命令作为单个参数传入。 此外,请避免在用于签名的密钥路径中使用 ~ 字符,并改用完整的主路径。 例如,使用 /home/USER/keys/priv.pem 而不是 ~/keys/priv.pem。

DiffGen 示例

在适用于 Linux 的 Windows 子系统中,以下示例在 /mnt/o/temp 目录下运行。

以下代码会在输入源文件和重新压缩的目标文件之间创建一个差异:

sudo ./DiffGenTool  
/mnt/o/temp/<source file>.swu
/mnt/o/temp/<target file>.swu
/mnt/o/temp/<delta file to create>
/mnt/o/temp/logs
/mnt/o/temp/working
/mnt/o/temp/<recompressed target file to create>.swu

如果还使用签名参数(如果 SWU 文件已签名,则必须使用此参数),可以使用前面提到的示例 sign_file.sh 脚本。 打开脚本并对其进行编辑,以将路径添加到私钥文件,保存该脚本,然后按如下所示运行 DiffGen。

以下代码会在输入源文件与重新压缩且重新签名的目标文件之间创建一个差异:

sudo ./DiffGenTool  
/mnt/o/temp/<source file>.swu
/mnt/o/temp/<target file>.swu   
/mnt/o/temp/<delta file to create>  
/mnt/o/temp/logs  
/mnt/o/temp/working  
/mnt/o/temp/<recompressed target file to create>.swu  
/mnt/o/temp/<path to script>/<sign_file>.sh

导入生成的增量更新

将增量更新导入到 Device Update 服务的基本过程与任何其他更新的过程相同。 如果还未导入,请务必查看如何准备要导入到 Azure Device Update for IoT Hub

生成导入清单

若要将更新导入 Device Update 服务,必须具有或创建导入清单文件。 有关详细信息,请参阅将更新导入到 Device Update

导入增量更新的清单文件必须引用 DiffGen 工具创建的下列文件:

  • <recompressed_target_file> SWU 映像
  • <delta file>

增量更新功能使用名为相关文件的功能,该功能需要版本 5 或更高版本的导入清单。 若要使用相关文件功能,必须在导入清单中包含 relatedFilesdownloadHandler 对象。

使用 relatedFiles 对象指定增量更新文件的相关信息,包括文件名、文件大小和 sha256 哈希。 最重要的是,还必须指定对增量更新功能来说唯一的下列两个属性:

"properties": {
      "microsoft.sourceFileHashAlgorithm": "sha256",
      "microsoft.sourceFileHash": "<source SWU image file hash>"
}

这两个属性都特定于在创建增量更新时用作 DiffGen 工具输入的 <source image file>。 即使实际上不导入源映像,导入清单也需要与源 SWU 映像相关的信息。 下载增量更新后,设备上的增量组件使用此有关源映像的元数据在设备上查找映像。

使用 downloadHandler 对象指定 Device Update 代理如何使用“相关文件”功能来协调增量更新。 除非要为增量功能自定义自己的 Device Update 代理版本,否则请使用以下 downloadHandler

"downloadHandler": {
  "id": "microsoft/delta:1"
}

可以使用 Azure CLI az iot du update init v5 命令为增量更新生成导入清单。 有关详细信息,请参阅创建基本导入清单

--update-provider <replace with your Provider> --update-name <replace with your update Name> --update-version <replace with your update Version> --compat manufacturer=<replace with the value your device will report> model=<replace with the value your device will report> --step handler=microsoft/swupdate:2 properties=<replace with any desired handler properties (JSON-formatted), such as '{"installedCriteria": "1.0"}'> --file path=<replace with path(s) to your update file(s), including the full file name> downloadHandler=microsoft/delta:1 --related-file path=<replace with path(s) to your delta file(s), including the full file name> properties='{"microsoft.sourceFileHashAlgorithm": "sha256", "microsoft.sourceFileHash": "<replace with the source SWU image file hash>"}' 

使用文件扩展名 .importmanifest.json 保存生成的导入清单 JSON。

使用 Azure 门户导入

创建导入清单后,按照将更新添加到 Device Update for IoT Hub 中的说明导入增量更新。 导入中必须包含以下项:

  • 前面步骤中创建的 *importmanifest.json 文件
  • DiffGen 工具创建的 <recompressed_target_file> SWU 映像
  • DiffGen 工具创建的 <delta file>

对设备的增量更新部署

Azure 门户中的增量更新部署体验与部署常规映像更新相同。 有关详细信息,请参阅使用 Device Update 部署更新

为增量更新创建部署后,Device Update 服务和客户端会自动确定部署到的每台设备是否存在有效的增量更新。 如果找到有效的增量,会在该设备上下载并安装增量更新。

如果未找到有效的增量更新,则将下载完整的映像更新(重新压缩的目标 SWU 映像)。 此方法可确保要将更新部署到的所有设备都达到相应的版本。

增量更新部署有三种可能的结果:

  • 已成功安装增量更新,并且设备采用新版本。
  • 增量更新不可用或安装失败,但成功完成了完整映像的回退安装,并且设备采用新版本。
  • 增量和回退安装都失败,并且设备仍采用旧版本。

要确定产生了哪种失败结果,可通过选择处于失败状态的任何设备来查看带有错误代码和扩展错误代码的安装结果。 如果需要,还可以从多台失败设备收集日志

  • 如果增量更新成功,设备显示“成功”状态。

  • 如果增量更新失败,但成功回退到完整映像,设备会显示以下错误状态:

    • resultCode:<值大于 0>
    • extendedResultCode:<非零值>

排查“失败”更新问题

失败更新会显示一个错误状态,你可按照使用以下说明进行解释。 从 result.h 中的 Device Update 代理错误开始。

Device Update 代理中特定于增量更新下载处理程序功能的错误以 0x9 开头:

组件 十进制 Hex 注意
EXTENSION_MANAGER 0 0x00 指示扩展管理器下载处理程序逻辑中的错误。 示例: 0x900XXXXX
PLUGIN 1 0x01 指示使用下载处理程序插件共享库时出现的错误。 示例: 0x901XXXXX
RESERVED 2 - 7 0x02 - 0x07 保留用于下载处理程序。 示例: 0x902XXXXX
COMMON 8 0x08 指示增量下载处理程序扩展顶级逻辑中的错误。 示例: 0x908XXXXX
SOURCE_UPDATE_CACHE 9 0x09 指示增量下载处理程序扩展源更新缓存中的错误。 示例: 0x909XXXXX
DELTA_PROCESSOR 10 0x0A 增量处理器 API 中的错误的错误代码。 示例: 0x90AXXXXX

如果 result.h 中不存在错误代码,则可能是增量处理器组件(与 Device Update 代理分开)中的错误。 如果是,则 extendedResultCode 是采用十六进制格式 0x90AXXXXX 的负十进制值。

  • 9 表示“增量设备”
  • 0A 表示“增量处理器组件”(ADUC_COMPONENT_DELTA_DOWNLOAD_HANDLER_DELTA_PROCESSOR)
  • XXXXX 表示 Field Installation Tool (FIT) 增量处理器中的 20 位错误代码

如果无法根据错误代码信息解决问题,请提交 GitHub 问题以获取进一步的帮助。