适用于:
IoT Edge 1.5
重要
IoT Edge 1.5 LTS 是受支持的版本。 IoT Edge 1.4 LTS 于 2024 年 11 月 12 日终止。 如果使用的是早期版本,请参阅 Update IoT Edge。
使用本文可识别并解决使用 IoT Edge 解决方案时的常见问题。 有关如何查找 IoT Edge 设备中的日志和错误的信息,请参阅 解决 IoT Edge 设备的问题。
预配和部署
IoT Edge 模块部署成功后,会从设备中消失
症状
为IoT Edge设备设置模块后,模块会成功部署,但在几分钟后,它们会从设备中消失,从Azure门户中的设备详细信息中消失。 除了定义的模块外,其他模块也可能会出现在设备上。
原因
如果针对某个设备进行自动部署,则自动部署的优先级高于为单个设备手动设置模块。 Azure 门户中的“设置模块”功能或 Visual Studio Code 中的“为单个设备创建部署”功能会暂时生效。 你会看到定义的模块在设备上启动。 然后,自动部署的优先级开始生效,并覆盖该设备的所需属性。
解决方案
每个设备仅使用一种类型的部署机制,即自动部署或单个设备部署。 如果你有针对某个设备的多个自动部署,则可以更改优先级或目标说明,以确保正确的部署应用于给定的设备。 你还可以更新设备孪生,以便它不再符合自动部署的目标描述。
有关详细信息,请参阅了解单个设备或大规模的 IoT Edge 自动部署。
IoT Edge 运行时
IoT Edge 代理在一分钟后停止
症状
edgeAgent 模块会启动并成功运行大约一分钟,然后停止。 日志显示,IoT Edge代理尝试通过 AMQP 连接到 IoT Hub,然后尝试通过 WebSocket 使用 AMQP 进行连接。 当连接失败时,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。 在使用 NAT 网络的 Windows 容器中,此问题在 Windows 设备上更常见。
解决方案
请确保为分配给此网桥或 NAT 网络的 IP 地址建立一条到 Internet 的路由。 有时候,主机上的 VPN 配置会替代 IoT Edge 网络。
Edge 代理模块报告“配置文件为空”,且设备上不会启动任何模块
症状
设备在启动部署中定义的模块时出现问题。 只有 edgeAgent 正在运行,但报告 空的配置文件...。
在设备上运行
sudo iotedge check时,它会报告“容器引擎未配置 DNS 服务器设置,这可能会影响到 IoT 中心的连接”。有关最佳做法,请参阅 https://aka.ms/iotedge-prod-checklist-dns。
原因
- 默认情况下,IoT Edge 在模块自身的隔离容器网络中启动模块。 设备在此专用网络中可能会遇到 DNS 名称解析的问题。
- 如果使用IoT Edge的快照安装,Docker 配置文件位于其他位置。 请参阅解决方案选项 3。
解决方案
选项 1:在容器引擎设置中设置 DNS 服务器
在容器引擎设置中为环境指定 DNS 服务器。 这些设置适用于引擎启动的所有容器模块。 创建名为 daemon.json的文件,并指定要使用的 DNS 服务器。 例如:
{
"dns": ["1.1.1.1"]
}
此 DNS 服务器设置为可公开访问的 DNS 服务。 但是,某些网络(如公司网络)有自己的 DNS 服务器,不允许访问公共 DNS 服务器。 因此,如果边缘设备无法访问公共 DNS 服务器,请将其替换为可访问的 DNS 服务器地址。
将 daemon.json 放入设备的 /etc/docker 目录。
如果该位置已包含 daemon.json 文件,请在其中添加 dns 密钥,然后保存该文件。
重启容器引擎以使更新生效。
sudo systemctl restart docker
选项 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 模块设置此配置。
选项 3:传递 docker 配置文件的位置以检查命令
如果将IoT Edge作为快照安装,请使用 --container-engine-config-file 参数指定 Docker 配置文件的位置。 例如,如果 Docker 配置文件位于/var/snap/docker/current/config/daemon.json,请运行以下命令:iotedge check --container-engine-config-file '/var/snap/docker/current/config/daemon.json'。
目前,即使设置了配置文件位置,警告消息仍会显示在 iotedge 的输出中。 检查报告错误,因为 IoT Edge snap 没有 Docker snap 的读取权限。 如果在发布过程中使用iotedge 检查,可以使用--ignore container-engine-dns container-engine-logrotate参数禁止显示警告消息。
配置了 LTE 连接的 Edge 代理模块报告“Edge 代理配置为空”并导致“暂时性网络错误”
症状
配置了 LTE 连接的设备在启动部署中定义的模块时出现问题。 edgeAgent无法连接到IoT Hub,并报告发生了“空边缘代理配置”和“暂时性网络错误”。
原因
某些网络具有数据包开销,这使得默认 docker 网络的 MTU (1500)过高并导致数据包碎片化。 这种碎片化阻止了对外部资源的访问。
解决方案
检查 Docker 网络的 MTU 设置。
docker network inspect <network name>检查设备上的物理网络适配器的 MTU 设置。
ip addr show eth0
注意
docker 网络的 MTU 不能高于设备的 MTU。 有关详细信息,请联系 ISP。
如果你发现 Docker 网络和设备的 MTU 大小不同,请尝试以下解决方法:
创建新网络。 例如,
docker network create --opt com.docker.network.driver.mtu=1430 test-mtu在此示例中,设备的 MTU 设置为 1430。 将 Docker 网络的 MTU 设置为 1430。
停止并删除 Azure 网络。
docker network rm azure-iot-edge重新创建 Azure 网络。
docker network create --opt com.docker.network.driver.mtu=1430 azure-iot-edge删除所有容器并重启 aziot-edged 服务。
sudo iotedge system stop && sudo docker rm -f $(docker ps -aq -f "label=net.azure-devices.edge.owner=Microsoft.Azure.Devices.Edge.Agent") && sudo iotedge config apply
IoT Edge 代理无法访问某个模块的映像 (403)
症状
某个容器未能运行,edgeAgent 日志报告 403 错误。
原因
IoT Edge 代理模块无权访问某个模块的映像。
解决方案
确保设备部署清单中的容器注册表凭据正确。
IoT Edge 代理标识调用次数过多
症状
IoT Edge 代理对 Azure IoT 中心的标识调用次数过多。
原因
设备部署清单配置错误导致设备上的部署失败。 IoT Edge 代理重试逻辑继续重试部署。 每次重试都会进行身份调用,直到部署成功。 例如,如果部署清单指定了容器注册表中不存在或错误输入的模块 URI,则 IoT Edge 代理会重试部署,直到更正部署清单为止。
解决方案
在 Azure 门户中验证部署清单。 更正任何错误并将清单重新部署到设备。
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.json 文件中进行更改。
在 Azure 门户中:
转到 IoT 中心,然后在“设备管理”菜单下选择“设备”。
选择要更新的 IoT Edge 设备。
选择“设置模块”。
选择“运行时设置”。
在“Edge Hub”模块设置中,从“容器创建选项”文本框中删除所有内容。
选择“应用”以保存更改并创建部署。
在 deployment.json 文件中:
打开应用到 IoT Edge 设备的 deployment.json 文件。
在 edgeAgent 所需属性部分找到
edgeHub设置:"edgeHub": { "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.5", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}" }, "status": "running", "type": "docker" }删除
createOptions行,并删除其前面的image行的尾随逗号:"edgeHub": { "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.5", "status": "running", "type": "docker" }选择“创建”以再次将其应用于 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 发送消息,运行时将拒绝该消息并返回 404 错误消息。
解决方案
从版本 1.0.7 开始,所有模块进程都可以连接。 有关详细信息,请参阅 1.0.7 版本更改日志。
如果无法升级到版本 1.0.7,请执行以下步骤。 确保自定义IoT Edge模块始终使用相同的进程 ID 将消息发送到 edgeHub。 例如,使用 ENTRYPOINT 命令而不是 Docker 文件中的 CMD 命令。 该 CMD 命令生成模块的一个进程 ID,以及运行主程序的 bash 命令的另一个进程 ID。 该 ENTRYPOINT 命令生成单个进程 ID。
小型设备上的稳定性问题
症状
在资源受限设备(如 Raspberry Pi)上可能会遇到稳定性问题,尤其是在用作网关时。 症状包括 IoT Edge 中心模块出现“内存不足”异常、下游设备无法连接或者设备在几小时后无法发送遥测消息。
原因
IoT Edge 中心是 IoT Edge 运行时的一部分,默认情况下已针对性能进行了优化,并尝试分配大块内存。 这种优化对于受限边缘设备并不理想,可能会导致稳定性问题。
解决方案
对于 IoT Edge 中心,请将环境变量 OptimizeForPerformance 设置为 false。 可以通过以下两种方式之一设置环境变量:
在 Azure 门户中:
在你的IoT Hub中,选择你的IoT Edge设备。 在设备详细信息页中,选择“ 设置模块 > 运行时设置”。
为名为 OptimizeForPerformance IoT Edge 中心模块创建环境变量,其类型为 True/False 并将其设置为 False。
选择 “应用 ”以保存更改,然后选择“ 查看 + 创建”。
该环境变量现在位于部署清单的
edgeHub属性中:"edgeHub": { "env": { "OptimizeForPerformance": { "value": false } }, "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.5", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}" }, "status": "running", "type": "docker" }选择“创建”以保存更改并部署模块。
安全守护程序无法启动
症状
无法启动安全守护程序,也不会创建模块容器。 IoT Edge服务不会启动 edgeAgent、edgeHub 或其他自定义模块。 在 aziot-edged 日志中,您会看到以下错误消息:
- 守护程序无法成功启动:无法启动管理服务
- 原因:路径 /var/run/iotedge/mgmt.sock 出错
- 原因:权限被拒绝(操作系统错误 13)
原因
对于 CentOS 7 以外的所有 Linux 发行版,IoT Edge默认使用 systemd 套接字激活。 如果更改配置文件以禁用套接字激活,但保留 URL /var/run/iotedge/*.sock,则会收到权限错误。 用户 iotedge 无法写入 /var/run/iotedge,因此无法解锁和挂载套接字。 CentOS 已到生命周期终点(EOL)。 有关详细信息,请参阅 CentOS 生命周期结束指南。
解决方案
不要在支持套接字激活的分发版上禁用套接字激活。 但是,如果不想使用套接字激活,请将套接字放入/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以删除它们。
消息队列清理速度缓慢
症状
处理完消息后,消息队列不会自动清理。 消息队列随着时间推移而增长,最终会导致 IoT Edge 运行时内存不足。
原因
客户端消息 TTL(生存时间)和 EdgeHubMessageCleanupIntervalSecs 环境变量控制消息清理间隔。 默认消息 TTL 值为 2 小时,默认值 MessageCleanupIntervalSecs 为 30 分钟。 如果应用程序使用的 TTL 值比默认值短且未调整 MessageCleanupIntervalSecs 该值,则在下次清理间隔之前不会清理过期的消息。
解决方案
如果将应用程序的 TTL 值更改为小于默认值的值,则还要调整 MessageCleanupIntervalSecs 该值。 该值 MessageCleanupIntervalSecs 应明显小于客户端使用的最小 TTL 值。 例如,如果客户端应用程序在消息标头中定义 TTL 为 5 分钟,请将 MessageCleanupIntervalSecs 该值设置为 1 分钟。 这些设置可确保在 6 (5 + 1) 分钟内清理消息。
若要配置 MessageCleanupIntervalSecs 值,请在 IoT Edge 中心模块的部署清单中设置环境变量。 有关设置运行时环境变量的详细信息,请参阅 Edge 代理和 Edge 中心环境变量。
使用 AMQP 协议时,IoT Edge中心报告 System.FormatException 错误
症状
使用 AMQP 协议将消息从 IoT Edge 设备路由到 IoT Hub,并在传出设备消息上设置 iothub-creation-time-utc 属性时,IoT Edge中心将报告 System.FormatException 错误。 错误消息如下所示:
System.FormatException: String '2024-12-01T00:00:0.000Z' was not recognized as a valid DateTime.
原因
iot-hub-creation-time-utc 值不符合严格的格式条件。 Edge 中心所需的格式是 ISO 8601 的子集。
解决方案
此问题是 AMQP 协议IoT Edge中心中的已知问题。 目前,产品团队正在研究解决方案。 MQTT 协议不存在此问题。
网络
由于主机名无效,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 名称标签 ,请输入一个值,然后选择“ 保存”。
复制新的 DNS 名称,其格式应为:
<DNSnamelabel>.<vmlocation>.cloudapp.chinacloudapi.cn.在 IoT Edge 设备上,打开配置文件。
sudo nano /etc/aziot/config.toml将
hostname的值替换为你的 DNS 名称。保存并关闭该文件,然后将更改应用到 IoT Edge。
sudo iotedge config apply
IoT Edge 模块报告连接错误
症状
IoT Edge直接连接到云服务(包括运行时模块)的模块停止按预期工作,并返回与连接或网络故障相关的错误。
原因
容器依赖于 IP 数据包转发连接到 Internet,以便它们可以与云服务通信。 Docker 默认启用 IP 数据包转发,但如果禁用,连接到云服务的任何模块将无法按预期工作。 有关详细信息,请参阅 Docker 文档中的了解容器通信。
解决方案
使用以下步骤启用 IP 数据包转发。
打开 sysctl.conf 文件。
sudo nano /etc/sysctl.conf将以下行添加到该文件。
net.ipv4.ip_forward=1保存并关闭该文件。
重启网络服务和 docker 服务以应用更改。
IoT Edge网关后面的设备无法执行 HTTP 请求或启动 edgeAgent 模块
症状
使用有效的配置文件时,IoT Edge 运行时处于活动状态,但它无法启动 edgeAgent 模块。 命令 iotedge list 返回一个空列表。 日志中的 IoT Edge 运行时报告“Could not perform HTTP request”。
原因
网关后面的 IoT Edge 设备将从父 IoT Edge 设备(在配置文件的 parent_hostname 字段中指定)获取其模块映像。 此错误 Could not perform HTTP request 意味着下游设备无法通过 HTTP 访问其父设备。
解决方案
请确保父 IoT Edge 设备可以接收来自下游 IoT Edge 设备的传入请求。 在端口 443 和 6617 上打开网络流量,以获取来自下游设备的请求。
从一个 IoT 中心迁移到另一个 IoT 中心时,网关后面的 IoT Edge 无法进行连接
症状
将IoT Edge设备的层次结构从一个IoT Hub迁移到另一个IoT Hub时,顶级父IoT Edge设备可以连接到IoT Hub,但下游IoT Edge设备无法连接。 日志报告 Unable to authenticate client downstream-device/$edgeAgent with module credentials。
原因
迁移未正确更新下游设备的凭据。 由于此问题, edgeAgent 并且 edgeHub 模块具有身份验证类型 none (如果未显式设置,则为默认值)。 在连接过程中,下游设备上的模块使用旧凭据,导致身份验证失败。
解决方案
迁移到新的 IoT 中心(假设不使用 DPS),请按顺序执行以下步骤:
- 按照本指南将设备标识从旧的 IoT 中心导出,然后导入到新的 IoT 中心
- 在新的 IoT 中心重新配置所有 IoT Edge 部署和配置
- 在新的 IoT 中心重新配置所有父子设备关系
- 更新每台设备以指向新的 IoT 中心主机名(
iothub_hostname中[provisioning]下的config.toml) - 如果选择了在设备导出期间排除身份验证密钥,请使用新 IoT 中心(
device_id_pk中[provisioning.authentication]下的config.toml)提供的新密钥重新配置每个设备 - 首先重启顶级父 Edge 设备,确保它已启动并在运行
- 从上到下逐级重启层次结构中的每个设备
在地理位置上远离 IoT 中心时,IoT Edge 消息吞吐量较低
症状
Azure IoT Edge与Azure IoT Hub相距较远的设备的消息吞吐量较低。
原因
设备和IoT Hub之间的高延迟会导致消息吞吐量降低。 IoT Edge 使用的默认消息批大小为 10。 此批大小限制在单个批中发送的消息数,这会增加设备和IoT Hub之间的往返次数。
解决方案
尝试增加 IoT Edge 中心 MaxUpstreamBatchSize 环境变量。 此更改在单个批处理中发送更多消息,从而减少设备和IoT Hub之间的往返次数。
若要在 Azure 门户中设置 Azure Edge 中心环境变量,请执行以下操作:
- 导航到 IoT 中心,然后在“设备管理”菜单下选择“设备”。
- 选择要更新的 IoT Edge 设备。
- 选择“设置模块”。
- 选择“运行时设置”。
- 在“Edge 中心”模块设置选项卡中,将 MaxUpstreamBatchSize 环境变量添加为“数字”类型,值为 20。
- 选择应用。
后续步骤
你认为在 IoT Edge 平台中发现了漏洞吗? 提交问题以便产品团队可以继续改进平台。
如果你还有其他问题,请创建支持请求以获取帮助。