Azure IoT Edge 常见问题的解决方案
适用于: IoT Edge 1.1
重要
IoT Edge 1.1 终止支持日期为 2022 年 12 月 13 日。 请查看 Microsoft 产品生命周期,了解此产品、服务、技术或 API 的受支持情况。 有关更新到最新版本的 IoT Edge 的详细信息,请参阅 更新 IoT Edge。
使用本文可识别并解决使用 IoT Edge 解决方案时的常见问题。 如需了解如何从 IoT Edge 设备查找日志和错误,请参阅对 IoT Edge 设备进行故障排除。
预配和部署
IoT Edge 模块部署成功后,会从设备中消失
症状
为 IoT Edge 设备设置模块后即表示已成功部署模块,但几分钟后,它们将从设备以及 Azure 门户中的设备详细信息中消失。 除了定义的模块外,其他模块也可能会出现在设备上。
原因
如果针对某个设备进行自动部署,则自动部署的优先级高于为单个设备手动设置模块。 Azure 门户中的“设置模块”功能或 Visual Studio Code 中的“为单个设备创建部署”功能会暂时生效。 你会看到定义的模块在设备上启动。 然后,自动部署的优先级开始生效,并覆盖该设备的所需属性。
解决方案
每个设备仅使用一种类型的部署机制,即自动部署或单设备部署。 如果你有针对某个设备的多个自动部署,则可以更改优先级或目标说明,以确保正确的部署应用于给定的设备。 还可以更新设备孪生,使其不再与自动部署的目标描述匹配。
有关详细信息,请参阅了解单个设备或大规模的 IoT Edge 自动部署。
无法在 Windows 上获取 IoT Edge 运行时日志
症状
在 Windows 上使用 Get-WinEvent
时,会收到 EventLogException。
原因
Get-WinEvent
PowerShell 命令依赖于存在的注册表项来按特定 ProviderName
查找日志。
解决方案
设置 IoT Edge 守护程序的注册表项。 创建包含以下内容的 iotedge.reg 文件,再双击该文件或使用 reg import iotedge.reg
命令将其导入到 Windows 注册表中:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\iotedged]
"CustomSource"=dword:00000001
"EventMessageFile"="C:\\ProgramData\\iotedge\\iotedged.exe"
"TypesSupported"=dword:00000007
DPS 客户端错误
症状
IoT Edge 无法启动并出现错误消息 failed to provision with IoT Hub, and no valid device backup was found dps client error.
原因
已使用组注册将 IoT Edge 设备预配到 IoT 中心。 已将 IoT Edge 设备移到其他中心。 已在 DPS 中删除注册。 在 DPS 中为新中心创建了新的注册。 设备未重新预配。
解决方案
- 验证 DPS 凭据是否正确。
- 使用
sudo iotedge apply config
应用你的配置。 - 如果未重新预配设备,请使用
sudo iotedge system restart
重启设备。 - 如果未重新预配设备,请使用
sudo iotedge system reprovision
来强制重新预配。
若要自动重新预配,请在设备配置文件中设置 dynamic_reprovisioning: true
。 将此标志设置为 true 可以选择启用动态重新预配功能。 IoT Edge 通过监视自身的 IoT 中心连接是否存在某些错误,来检测设备似乎已在云中重新预配的情况。 IoT Edge 通过关闭所有 Edge 模块和自身来进行响应。 下次启动守护程序时,它会尝试使用 Azure 重新预配此设备,以接收新的 IoT 中心预配信息。
使用外部预配时,守护程序还会在关闭之前将重新预配事件通知给外部预配终结点。 有关详细信息,请参阅 IoT 中心设备重新预配概念。
IoT Edge 运行时
IoT Edge 代理在一分钟后停止
症状
edgeAgent 模块会启动并成功运行大约一分钟,然后停止。 日志表明,IoT Edge 代理尝试通过 AMQP 连接到 IoT 中心,并且尝试使用 AMQP 通过 WebSocket 进行连接。 该操作失败时,IoT Edge 代理将会退出。
示例 edgeAgent 日志:
2017-11-28 18:46:19 [INF] - Starting module management agent.
2017-11-28 18:46:19 [INF] - Version - 1.0.7516610 (03c94f85d0833a861a43c669842f0817924911d5)
2017-11-28 18:46:19 [INF] - Edge agent attempting to connect to IoT Hub via AMQP...
2017-11-28 18:46:49 [INF] - Edge agent attempting to connect to IoT Hub via AMQP over WebSocket...
原因
主机网络上的某个网络配置阻止 IoT Edge 代理到达该网络。 代理首先会尝试通过 AMQP(端口 5671)进行连接。 如果连接失败,它将尝试 WebSocket(端口 443)。
IoT Edge 运行时会为每个模块设置要在其中进行通信的网络。 在 Linux 上,此网络是一个桥网络。 在 Windows 上,它使用 NAT。 此问题在其中的 Windows 容器使用 NAT 网络的 Windows 设备上更为常见。
解决方案
确保分配给此桥/NAT 网络的 IP 地址具有通向 Internet 的路由。 有时候,主机上的 VPN 配置会替代 IoT Edge 网络。
Edge 代理模块报告“配置文件为空”,且设备上不会启动任何模块
症状
设备在启动部署中定义的模块时出现问题。 只有 edgeAgent 在运行,但它持续报告“配置文件为空...”。
原因
默认情况下,IoT Edge 在模块自身的隔离容器网络中启动模块。 在此专用网络中,设备可能会遇到 DNS 名称解析方面的问题。
解决方案
选项 1:在容器引擎设置中设置 DNS 服务器
在容器引擎设置中为环境指定 DNS 服务器,该设置将应用于引擎启动的所有容器模块。 创建一个名为 daemon.json
的文件,然后指定要使用的 DNS 服务器。 例如:
{
"dns": ["1.1.1.1"]
}
此 DNS 服务器设置为可公开访问的 DNS 服务。 但是,某些网络(如公司网络)安装了自己的 DNS 服务器,不允许访问公共 DNS 服务器。 因此,如果边缘设备无法访问公共 DNS 服务器,请将其替换为可访问的 DNS 服务器地址。
将 daemon.json
放入平台上的适当位置:
平台 | 位置 |
---|---|
Linux | /etc/docker |
包含 Windows 容器的 Windows 主机 | C:\ProgramData\iotedge-moby\config |
如果该位置已包含 daemon.json
文件,请在其中添加 dns 密钥,然后保存该文件。
重启容器引擎以使更新生效。
平台 | 命令 |
---|---|
Linux | sudo systemctl restart docker |
Windows (Admin PowerShell) | Restart-Service iotedge-moby -Force |
选项 2:在每个模块的 IoT Edge 部署中设置 DNS 服务器
可以针对 IoT Edge 部署中每个模块的 createOptions 设置 DNS 服务器。 例如:
"createOptions": {
"HostConfig": {
"Dns": [
"x.x.x.x"
]
}
}
警告
如果使用此方法并指定错误的 DNS 地址,edgeAgent 将失去与 IoT 中心的连接,并且无法接收新部署来解决此问题。 若要解决此问题,可以重新安装 IoT Edge 运行时。 在安装新的 IoT Edge 实例之前,请务必从之前的安装中删除所有 edgeAgent 容器。
请确保也为 edgeAgent 和 edgeHub 模块设置此配置。
IoT Edge 代理无法访问某个模块的映像 (403)
症状
某个容器未能运行,edgeAgent 日志报告 403 错误。
原因
IoT Edge 代理模块无权访问某个模块的映像。
解决方案
确保设备部署清单中的容器注册表凭据正确。
IoT Edge 中心未能启动
症状
edgeHub 模块未能启动。 你可能会在日志中看到一条类似于以下错误的消息:
One or more errors occurred.
(Docker API responded with status code=InternalServerError, response=
{\"message\":\"driver failed programming external connectivity on endpoint edgeHub (6a82e5e994bab5187939049684fb64efe07606d2bb8a4cc5655b2a9bad5f8c80):
Error starting userland proxy: Bind for 0.0.0.0:443 failed: port is already allocated\"}\n)
或
info: edgelet_docker::runtime -- Starting module edgeHub...
warn: edgelet_utils::logging -- Could not start module edgeHub
warn: edgelet_utils::logging -- caused by: failed to create endpoint edgeHub on network nat: hnsCall failed in Win32:
The process cannot access the file because it is being used by another process. (0x20)
原因
主机上的其他某个进程绑定了 edgeHub 模块尝试绑定的端口。 用于网关方案的 IoT Edge 中心映射端口 443、5671 和 8883。 如果另一个进程已绑定了其中某个端口,则无法启动该模块。
解决方案
可通过两种方式解决此问题:
如果 IoT Edge 设备充当网关设备,则你需要查找并停止正在使用端口 443、5671 或 8883 的进程。 端口 443 的错误通常表示另一个进程是 Web 服务器。
如果不需要将 IoT Edge 设备用作网关,则可以从 edgeHub 的模块创建选项中删除端口绑定。 可以在 Azure 门户中更改创建选项,也可直接在 deployment 文件中进行更改。
在 Azure 门户中:
导航到 IoT 中心,然后在“设备管理”菜单下选择“设备”。
选择要更新的 IoT Edge 设备。
选择“设置模块”。
选择“运行时设置”。
在“Edge Hub”模块设置中,从“创建选项”文本框中删除所有内容。
保存更改并创建部署。
在 deployment.json 文件中:
打开应用到 IoT Edge 设备的 deployment.json 文件。
在 edgeAgent 所需属性部分找到
edgeHub
设置:"edgeHub": { "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.1", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" }, "type": "docker", "status": "running", "restartPolicy": "always" }
删除
createOptions
行,并删除其前面的image
行的尾随逗号:"edgeHub": { "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.1" }, "type": "docker", "status": "running", "restartPolicy": "always" }
保存该文件,然后再次将其应用到 IoT Edge 设备。
IoT Edge 模块未能将消息发送到 edgeHub 并出现 404 错误
症状
自定义 IoT Edge 模块未能将消息发送到 IoT Edge 中心并出现 404 Module not found
错误。 IoT Edge 运行时在日志中输出以下消息:
Error: Time:Thu Jun 4 19:44:58 2018 File:/usr/sdk/src/c/provisioning_client/adapters/hsm_client_http_edge.c Func:on_edge_hsm_http_recv Line:364 executing HTTP request fails, status=404, response_buffer={"message":"Module not found"}u, 04 )
原因
出于安全考虑,IoT Edge 运行时会强制对连接到 edgeHub 的所有模块执行进程识别。 它会验证某个模块发送的所有消息是否来自该模块的主进程 ID。 如果发送消息的模块的进程 ID 不同于最初建立的进程 ID,则守护程序会拒绝该消息并返回 404 错误消息。
解决方案
从版本 1.0.7 开始,所有模块进程都有权进行连接。 有关详细信息,请参阅 1.0.7 版本更改日志。
如果无法升级到 1.0.7,请完成以下步骤。 确保自定义 IoT Edge 模块始终使用相同的进程 ID 向 Edge 中心发送消息。 例如,请确保在 Docker 文件中使用 ENTRYPOINT
,而不使用 CMD
命令。 CMD
命令会导致为模块生成一个进程 ID,并为运行主程序的 bash 命令生成另一个进程 ID,但是 ENTRYPOINT
只会生成单个进程 ID。
小型设备上的稳定性问题
症状
你可能会在 Raspberry Pi 等资源受限设备上遇到稳定性问题,尤其是在这些设备用作网关时。 症状包括 IoT Edge 中心模块出现“内存不足”异常、下游设备无法连接或者设备在几小时后无法发送遥测消息。
原因
IoT Edge 中心是 IoT Edge 运行时的一部分,默认情况下已针对性能进行了优化,并尝试分配大块内存。 这种优化对于受限边缘设备并不理想,可能会导致稳定性问题。
解决方案
对于 IoT Edge 中心,请将环境变量 OptimizeForPerformance 设置为 false。 可以通过两种方式来设置环境变量:
在 Azure 门户中:
在 IoT 中心,选择 IoT Edge 设备,然后从设备详细信息页中依次选择“设置模块”>“运行时设置” 。 为 IoT Edge 中心模块创建名为“OptimizeForPerformance”、设置为“false”的环境变量。
在部署清单中:
"edgeHub": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.1",
"createOptions": <snipped>
},
"env": {
"OptimizeForPerformance": {
"value": "false"
}
},
安全守护程序无法成功启动
症状
安全守护程序无法启动,并且模块容器未创建。 edgeAgent
、edgeHub
和其他自定义模块未通过 IoT Edge 服务启动。 在 aziot-edged
日志中,会看到此错误:
- 守护程序无法成功启动:无法启动管理服务
- 原因:路径 /var/run/iotedge/mgmt.sock 出错
- 原因:权限被拒绝(操作系统错误 13)
原因
对于所有 Linux 发行版(CentOS 7 除外),IoT Edge 的默认配置是使用 systemd
套接字激活。 如果将配置文件更改为不使用套接字激活,而将 URL 保留为 /var/run/iotedge/*.sock
,则会发生权限错误,因为 iotedge
用户无法写入 /var/run/iotedge
,这也意味着它无法自己解锁和装载套接字。
解决方案
不需要在支持套接字激活的发行版上禁用套接字激活。 但是,如果不想使用套接字激活,请将套接字置于 /var/lib/iotedge/
。
- 运行
systemctl disable iotedge.socket iotedge.mgmt.socket
以禁用套接字单元,使 systemd 不会不必要地启动它们 - 将 iotedge 配置更改为在
connect
和listen
部分中同时使用/var/lib/iotedge/*.sock
- 如果已经有模块,则它们具有旧
/var/run/iotedge/*.sock
装载,因此docker rm -f
它们。
由于 OS 不匹配,无法启动模块
症状
edgeHub 模块无法在 IoT Edge 版本 1.1 中启动。
原因
Windows 模块使用的 Windows 版本与主机上的 Windows 版本不兼容。 需要使用 IoT Edge Windows 版本 1809 内部版本 17763 作为模块映像的基础层,但使用的是其他版本。
解决方案
在排查主机和容器映像不匹配问题中检查各种 Windows 操作系统的版本。 如果操作系统不同,请将其更新为 IoT Edge Windows 版本 1809 内部版本 17763,然后重新生成用于该模块的 Docker 映像。
网络
由于主机名无效,IoT Edge 安全守护程序失败
症状
尝试检查 IoT Edge 安全管理器日志失败,并输出以下消息:
Error parsing user input data: invalid hostname. Hostname cannot be empty or greater than 64 characters
原因
IoT Edge 运行时只支持短于 64 个字符的主机名。 物理计算机通常不具有长主机名,但此问题在虚拟机上更常见。 特别是为 Azure 中托管的 Windows 虚拟机自动生成的主机名,往往会很长。
解决方案
看到此错误时,可以配置虚拟机的 DNS 名称,然后在设置命令中将 DNS 名称设置为主机名。
在 Azure 门户中,导航到虚拟机的概述页面。
选择 DNS 名称下的“配置”。 如果你的虚拟机已配置 DNS 名称,则不需要再配置。
为“DNS 名称标签”提供一个值,然后选择“保存” 。
复制新的 DNS 名称,此名称应该为 <DNSnamelabel>.<vmlocation>.cloudapp.azure.com。
在虚拟机中使用下列命令,以 DNS 名称设置 IoT Edge 运行时:
在 Linux 上:
sudo nano /etc/iotedge/config.yaml
在 Windows 上:
notepad C:\ProgramData\iotedge\config.yaml
IoT Edge 模块报告连接错误
症状
直接连接云服务的 IoT Edge 模块(包括运行时模块)停止正常工作,并返回有关连接或网络故障的错误。
原因
容器依赖于 IP 数据包转发来连接到 Internet,以便可以与云服务通信。 默认情况下,在 Docker 中启用 IP 数据包转发,但如果禁用了它,则连接到云服务的任何模块都将无法按预期方式工作。 有关详细信息,请参阅 Docker 文档中的了解容器通信。
解决方案
使用以下步骤启用 IP 数据包转发。
在 Windows 上:
打开“运行”应用程序。
在文本框中输入
regedit
,然后选择“确定”。在“注册表编辑器”窗口中,浏览到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters 。
查找 IPEnableRouter 参数。
如果参数存在,则将参数的值设置为 1。
如果该参数不存在,请通过以下设置将其添加为新参数:
设置 值 名称 IPEnableRouter 类型 REG_DWORD 值 1
关闭“注册表编辑器”窗口。
重启系统以应用更改。
在 Linux 上:
打开 sysctl.conf 文件。
sudo nano /etc/sysctl.conf
将以下行添加到该文件。
net.ipv4.ip_forward=1
保存并关闭该文件。
重启网络服务和 docker 服务以应用更改。
后续步骤
认为在 IoT Edge 平台中发现了 bug? 提交问题,以便我们可以持续改进。
如果你还有其他问题,请创建支持请求以获取帮助。