连接 Azure IoT Edge 设备以创建层次结构

适用于:IoT Edge 1.4 checkmark IoT Edge 1.4

本文提供的步骤说明了如何在 IoT Edge 网关和下游 IoT Edge 设备之间建立信任连接。 此配置也称为嵌套边缘

在网关方案中,IoT Edge 设备既可以是网关,也可以是下游设备。 可以将多个 IoT Edge 网关分层,以创建设备的层次结构。 下游设备(子设备)可以通过其网关设备(父设备)进行身份验证以及发送或接收消息。

网关层次结构中的 IoT Edge 设备有两种不同的配置,本文对这两种配置都进行了介绍。 第一种配置是顶层 IoT Edge 设备。 当多个 IoT Edge 设备互相连接时,任何没有父设备而是直接连接到 IoT 中心的设备都会被视为顶层设备。 此设备负责处理其下的所有设备的请求。 其他配置适用于层次结构的下层中的任何 IoT Edge 设备。 这些设备可能是其他下游 IoT 和 IoT Edge 设备的网关,但也需要通过其自己的父设备路由任何通信。

某些网络体系结构只允许层次结构中的顶层 IoT Edge 设备连接到云。 在此配置中,层次结构的下层中的所有 IoT Edge 设备只能与其网关设备(父设备)和任何下游设备(子设备)通信。

本文中的所有步骤都基于将 IoT Edge 设备配置为充当透明网关一文中的步骤,这篇文章介绍了如何将 IoT Edge 设备设置为下游 IoT 设备的网关。 同样的基本步骤适用于所有网关方案:

  • 身份验证:为网关层次结构中的所有设备创建 IoT 中心标识。
  • 授权:设置 IoT 中心内的父/子关系,以授权下游设备连接到其父设备,就像连接到 IoT 中心一样。
  • 网关发现:确保下游设备能够在本地网络上找到其父设备。
  • 安全连接:使用属于同一链的受信任证书建立安全连接。

先决条件

[提示] 本文提供详细的步骤和选项,以便帮助你创建适用于你的方案的网关层次结构。 如需引导式教程,请参阅使用网关创建 IoT Edge 设备的层次结构

创建网关层次结构

请通过为方案中的 IoT Edge 设备定义父/子关系来创建 IoT Edge 网关层次结构。 可以在创建新设备标识时设置父设备,也可以管理现有设备标识的父项和子项。

设置父/子关系的步骤可以授权下游设备连接到其父设备,就像连接到 IoT 中心一样。

只有 IoT Edge 设备可以是父设备,但是 IoT Edge 设备和 IoT 设备都可以是子设备。 父设备可以有多个子设备,但子设备只能有一个父设备。 通过将父/子集链接在一起来创建网关层次结构,使一个设备的子设备是另一个设备的父设备。

默认情况下,一个父设备最多只能有 100 个子设备。 可以通过在父设备的 edgeHub 模块中设置“MaxConnectedClients”环境变量来更改此限制。

在 Azure 门户中,可以在创建新设备标识时或通过编辑现有设备管理父/子关系。

创建新 IoT Edge 设备时,可以从该中心的现有 IoT Edge 设备的列表中选择父设备和子设备。

  1. Azure 门户中导航到 IoT 中心。
  2. 在“设备管理”菜单下选择“设备”。
  3. 选择“添加设备”,然后选中“IoT Edge 设备”复选框。
  4. 除了设置设备 ID 和身份验证设置,还可以选择“设置父设备”或“选择子设备”。
  5. 选择要用作父设备或子设备的设备。

还可以为现有设备创建或管理父/子关系。

  1. Azure 门户中导航到 IoT 中心。
  2. 在“设备管理”菜单中选择“设备”。
  3. 从列表中选择要管理的“IoT Edge 设备”。
  4. 选择“设置父设备”“齿轮”图标或“管理子设备”。
  5. 添加或删除任何父设备或子设备。

注意

如果要以编程方式建立父子关系,可以使用 C#、Java 或 Node.js IoT 中心服务 SDK

下面是使用 C# SDK 分配子设备的示例RegistryManager_AddAndRemoveDeviceWithScope() 任务演示如何以编程方式创建三层的层次结构。 IoT Edge 设备位于第一层,作为父项。 另一个 IoT Edge 设备位于第二层,同时充当父项和子项。 最后,IoT 设备处于第三层,作为最低层子设备。

生成证书

必须在同一网关层次结构中的所有设备上安装一致的证书链,才能在它们之间建立安全通信。 层次结构中的每个设备,无论是 IoT Edge 设备还是 IoT 下游设备,都需要同一根 CA 证书的副本。 然后,层次结构中的每个 IoT Edge 设备都会使用该根 CA 证书作为其设备 CA 证书的根。

使用此设置时,每个下游 IoT Edge 设备都可以通过验证其连接到的 edgeHub 是否具有由共享根 CA 证书签名的服务器证书,来验证其父设备的标识。

Illustration of certificate chain issued by root CA on gateway and downstream device

有关 IoT Edge 证书要求的更多信息,请参阅了解 Azure IoT Edge 如何使用证书

  1. 创建或请求以下证书:

    • 根 CA 证书,是给定网关层次结构中所有设备的最顶层共享证书。 此证书安装在所有设备上。
    • 要包括在根证书链中的任何中间证书。
    • 设备 CA 证书及其私钥,由根证书和中间证书生成。 网关层次结构中的每个 IoT Edge 设备都需要独一无二的设备 CA 证书。

    可以使用自签名证书颁发机构颁发的证书,也可以从 Baltimore、Verisign、DigiCert 或 GlobalSign 等受信任的商业证书颁发机构购买一个证书。

  2. 如果没有用于测试的自有证书,请创建一组根证书和中间证书,然后为每个设备创建 IoT Edge 设备 CA 证书。 在本文中,我们将使用通过用于示例和教程的测试 CA 证书生成的测试证书。 例如,以下命令创建根 CA 证书、父设备证书和子设备证书。

    # !!! For test only - do not use in production !!!
    
    # Create the the root CA test certificate
    ./certGen.sh create_root_and_intermediate
    
    # Create the parent (gateway) device test certificate 
    # signed by the shared root CA certificate
    ./certGen.sh create_edge_device_ca_certificate "gateway"
    
    # Create the downstream device test certificate
    # signed by the shared root CA certificate
    ./certGen.sh create_edge_device_ca_certificate "downstream"
    

    警告

    请勿将测试脚本创建的证书用于生产。 它们包含硬编码密码,并会在 30 天后过期。 出于演示目的提供了测试 CA 证书,以帮助你了解 CA 证书。 在生产环境中使用你自己的最佳安全做法来创建认证和管理生存期。

    有关创建测试证书的详细信息,请参阅创建演示证书以测试 IoT Edge 设备功能

  3. 需要将证书和密钥传输到每个设备。 可使用 U 盘,这是一种类似于 Azure Key Vault 的服务,或使用安全文件复制等功能。 选择最适合方案的方法之一。 将文件复制到证书和密钥的首选目录。 对证书使用 /var/aziot/certs,对密钥使用 /var/aziot/secrets

有关在设备上安装证书的详细信息,请参阅管理 IoT Edge 设备上的证书

配置父设备

要配置父设备,请打开本地或远程命令行界面。

若要启用安全连接,需要为网关方案中的每个 IoT Edge 父设备配置独一无二的设备 CA 证书以及由网关层次结构中的所有设备共享的根 CA 证书的副本。

  1. 检查你的证书是否符合格式要求

  2. 将根 CA 证书、父设备 CA 证书和父私钥传输到父设备。

  3. 将证书和密钥复制到正确的目录。 对于设备证书,首选目录为 /var/aziot/certs;对于密钥,首选目录为 /var/aziot/secrets

    ### Copy device certificate ###
    
    # If the device certificate and keys directories don't exist, create, set ownership, and set permissions
    sudo mkdir -p /var/aziot/certs
    sudo chown aziotcs:aziotcs /var/aziot/certs
    sudo chmod 755 /var/aziot/certs
    
    sudo mkdir -p /var/aziot/secrets
    sudo chown aziotks:aziotks /var/aziot/secrets
    sudo chmod 700 /var/aziot/secrets
    
    # Copy full-chain device certificate and private key into the correct directory
    sudo cp iot-edge-device-ca-gateway-full-chain.cert.pem /var/aziot/certs
    sudo cp iot-edge-device-ca-gateway.key.pem /var/aziot/secrets
    
    ### Root certificate ###
    
    # Copy root certificate into the /certs directory
    sudo cp azure-iot-test-only.root.ca.cert.pem /var/aziot/certs
    
    # Copy root certificate into the CA certificate directory and add .crt extension.
    # The root certificate must be in the CA certificate directory to install it in the certificate store.
    # Use the appropriate copy command for your device OS or if using EFLOW.
    
    # For Ubuntu and Debian, use /usr/local/share/ca-certificates/
    sudo cp azure-iot-test-only.root.ca.cert.pem /usr/local/share/azure-iot-test-only.root.ca.cert.pem.crt
    # For EFLOW, use /etc/pki/ca-trust/source/anchors/
    sudo cp azure-iot-test-only.root.ca.cert.pem /etc/pki/ca-trust/source/anchors/azure-iot-test-only.root.ca.pem.crt
    
  4. 更改证书和密钥的所有权和权限。

    # Give aziotcs ownership to certificates
    # Read and write for aziotcs, read-only for others
    sudo chown -R aziotcs:aziotcs /var/aziot/certs
    sudo find /var/aziot/certs -type f -name "*.*" -exec chmod 644 {} \;
    
    # Give aziotks ownership to private keys
    # Read and write for aziotks, no permission for others
    sudo chown -R aziotks:aziotks /var/aziot/secrets
    sudo find /var/aziot/secrets -type f -name "*.*" -exec chmod 600 {} \;
    
    # Verify permissions of directories and files
    sudo ls -Rla /var/aziot
    

    包含正确所有权和权限的列表输出如下所示:

    azureUser@vm:/var/aziot$ sudo ls -Rla /var/aziot
    /var/aziot:
    total 16
    drwxr-xr-x  4 root    root    4096 Dec 14 00:16 .
    drwxr-xr-x 15 root    root    4096 Dec 14 00:15 ..
    drwxr-xr-x  2 aziotcs aziotcs 4096 Jan 14 00:31 certs
    drwx------ 2 aziotks aziotks 4096 Jan 23 17:23 secrets
    
    /var/aziot/certs:
    total 20
    drwxr-xr-x 2 aziotcs aziotcs 4096 Jan 14 00:31 .
    drwxr-xr-x 4 root    root    4096 Dec 14 00:16 ..
    -rw-r--r-- 1 aziotcs aziotcs 1984 Jan 14 00:24 azure-iot-test-only.root.ca.cert.pem
    -rw-r--r-- 1 aziotcs aziotcs 5887 Jan 14 00:27 iot-edge-device-ca-gateway-full-chain.cert.pem
    
    /var/aziot/secrets:
    total 16
    drwx------ 2 aziotks aziotks 4096 Jan 23 17:23 .
    drwxr-xr-x 4 root    root    4096 Dec 14 00:16 ..
    -rw------- 1 aziotks aziotks 3326 Jan 14 00:29 azure-iot-test-only.root.ca.key.pem
    -rw------- 1 aziotks aziotks 3243 Jan 14 00:28 iot-edge-device-ca-gateway.key.pem
    
  5. 通过使用特定于平台的命令更新设备上的证书存储,在父 IoT Edge 设备上安装根 CA 证书。

    # Update the certificate store
    
    # For Ubuntu or Debian - use update-ca-certificates
    sudo update-ca-certificates
    # For EFLOW or RHEL - use update-ca-trust
    sudo update-ca-trust
    

    有关在 EFLOW 中使用 update-ca-trust 的详细信息,请参阅 CBL-Mariner SSL CA 证书管理

该命令报告了已将一个证书添加到 /etc/ssl/certs

Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.

更新父配置文件

你应该已在设备上安装了 IoT Edge。 如果没有,按照步骤手动预配单个 Linux IoT Edge 设备

  1. 验证父设备上是否存在 /etc/aziot/config.toml 配置文件。

    如果设备上不存在配置文件,请使用以下命令基于模板文件创建该文件:

    sudo cp /etc/aziot/config.toml.edge.template /etc/aziot/config.toml
    

    还可以使用模板文件作为参考,添加本部分中的配置参数。

  2. 使用编辑器打开 IoT Edge 配置文件。 例如,使用 nano 编辑器打开 /etc/aziot/config.toml 文件。

    sudo nano /etc/aziot/config.toml
    
  3. 查找 hostname 参数,或将其添加到配置文件的开头。 将值更新为 IoT Edge 父设备的完全限定的域名 (FQDN) 或 IP 地址。 例如:

    hostname = "10.0.0.4"
    

    若要启用网关发现,需要为每个 IoT Edge 网关(父)设备指定 hostname 参数,供其子设备用来在本地网络上查找它。 每个下游 IoT Edge 设备都需要指定 parent_hostname 参数来标识其父级。 在具有层次结构的方案中,单个 IoT Edge 设备既是父设备又是子设备,则需要这两个参数。

    hostnametrust_bundle_cert 参数必须位于配置文件的开头,位于任何部分之前。 在定义的部分之前添加参数,确保正确应用参数。

    使用少于 64 个字符的 hostname,这是服务器证书公用名称的字符限制。

    与网关层次结构中的 hostname 模式保持一致。 请使用 FQDN 或 IP 地址,但不能同时使用这二者。 连接下游设备需要 FQDN 或 IP 地址。

    在创建 edgeHub 容器之前设置主机名。 如果 edgeHub 正在运行,则在重新创建容器之前,更改配置文件中的主机名不会生效。 有关如何验证主机名是否已应用的详细信息,请参阅验证父配置部分。

  4. 查找“信任捆绑包证书”参数,或将其添加到配置文件的开头。

    trust_bundle_cert 参数更新为设备上根 CA 证书的文件 URI。 例如:

    trust_bundle_cert = "file:///var/aziot/certs/azure-iot-test-only.root.ca.cert.pem"
    
  5. 在配置文件中找到或添加“Edge CA certificate”部分。 使用 IoT Edge 父设备上全链证书和密钥文件的文件 URI 路径来更新证书 cert 和私钥 pk 参数。 IoT Edge 要求证书和私钥采用基于文本的隐私增强邮件 (PEM) 格式。 例如:

    [edge_ca]
    cert = "file:///var/aziot/certs/iot-edge-device-ca-gateway-full-chain.cert.pem"
    pk = "file:///var/aziot/secrets/iot-edge-device-ca-gateway.key.pem"
    
  6. 验证 IoT Edge 设备在启动时是否使用正确版本的 IoT Edge 代理。 找到“Default Edge Agent”节,并将 IoT Edge 的映像值设置为版本 1.4。 例如:

    [agent.config]
    image = "mcr.microsoft.com/azureiotedge-agent:1.4"
    
  7. 父配置文件的开头应类似于以下示例。

    hostname = "10.0.0.4"
    trust_bundle_cert = "file:///var/aziot/certs/azure-iot-test-only.root.ca.cert.pem"
    
    [edge_ca]
    cert = "file:///var/aziot/certs/iot-edge-device-ca-gateway-full-chain.cert.pem"
    pk = "file:///var/aziot/secrets/iot-edge-device-ca-gateway.key.pem"
    
  8. 保存并关闭 config.toml 配置文件。 例如,如果使用 nano 编辑器,请选择 Ctrl+O - “写出”、Enter 和 Ctrl+X - “退出”。

  9. 如果以前使用过 IoT Edge 的任何其他证书,请删除以下两个目录中的文件,以确保新证书得到应用:

    • /var/lib/aziot/certd/certs
    • /var/lib/aziot/keyd/keys
  10. 单击“应用”以应用更改。

    sudo iotedge config apply
    
  11. 检查配置中是否有任何错误。

    sudo iotedge check --verbose
    

    注意

    在新预配的设备上,可能会看到与 IoT Edge 中心相关的错误:

    × 生产就绪性:Edge 中心的存储目录持久保存在主机文件系统上- 错误

    无法检查 edgeHub 容器的当前状态

    由于 IoT Edge 中心模块未运行,在新预配的设备上预期会出现此错误。 若要解决此错误,请在 IoT 中心为设备设置模块并创建部署。 为设备创建部署会启动设备上的模块,包括 IoT Edge 中心模块。

验证父配置

主机名必须是 IoT Edge 设备的限定域名 (FQDN) 或 IP 地址,因为当下游设备连接时,IoT Edge 会在服务器证书中使用此值。 这些值必须匹配,否则会收到“IP 地址不匹配”错误。

若要验证主机名,需要检查 edgeHub 容器的环境变量。

  1. 列出正在运行的 IoT Edge 容器。

    iotedge list
    

    验证 edgeAgent 和 edgeHub 容器是否正在运行。 命令的输出应如以下示例所示。

    NAME                        STATUS           DESCRIPTION      CONFIG
    SimulatedTemperatureSensor  running          Up 5 seconds     mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0
    edgeAgent                   running          Up 17 seconds    mcr.microsoft.com/azureiotedge-agent:1.4
    edgeHub                     running          Up 6 seconds     mcr.microsoft.com/azureiotedge-hub:1.4
    
  2. 检查 edgeHub 容器。

    sudo docker inspect edgeHub
    
  3. 在输出中的 Env 部分找到 EdgeDeviceHostName 参数。

    "EdgeDeviceHostName=10.0.0.4"
    
  4. 验证 EdgeDeviceHostName 参数值是否与config.toml主机名设置匹配。 如果不匹配,则修改并应用配置时,edgeHub 容器正在运行。 若要更新 EdgeDeviceHostName,先删除 edgeAgent 容器。

    sudo docker rm -f edgeAgent
    

    EdgeAgent 和 edgeHub 容器将在几分钟内重新创建和启动。 EdgeHub 容器开始运行后,检查容器并验证 EdgeDeviceHostName 参数与配置文件是否匹配。

配置下游设备

若要配置下游设备,请打开本地或远程命令外壳。

若要启用安全连接,需要为网关方案中的每个 IoT Edge 下游设备配置独一无二的设备 CA 证书以及由网关层次结构中的所有设备共享的根 CA 证书的副本。

  1. 检查你的证书是否符合格式要求

  2. 将根 CA 证书、子设备 CA 证书和子设备私钥传输到下游设备。

  3. 将证书和密钥复制到正确的目录。 对于设备证书,首选目录为 /var/aziot/certs;对于密钥,首选目录为 /var/aziot/secrets

    ### Copy device certificate ###
    
    # If the device certificate and keys directories don't exist, create, set ownership, and set permissions
    sudo mkdir -p /var/aziot/certs
    sudo chown aziotcs:aziotcs /var/aziot/certs
    sudo chmod 755 /var/aziot/certs
    
    sudo mkdir -p /var/aziot/secrets
    sudo chown aziotks:aziotks /var/aziot/secrets
    sudo chmod 700 /var/aziot/secrets
    
    # Copy device full-chain certificate and private key into the correct directory
    sudo cp iot-device-downstream-full-chain.cert.pem /var/aziot/certs
    sudo cp iot-device-downstream.key.pem /var/aziot/secrets
    
    ### Root certificate ###
    
    # Copy root certificate into the /certs directory
    sudo cp azure-iot-test-only.root.ca.cert.pem /var/aziot/certs
    
    # Copy root certificate into the CA certificate directory and add .crt extension.
    # The root certificate must be in the CA certificate directory to install it in the certificate store.
    # Use the appropriate copy command for your device OS or if using EFLOW.
    
    # For Ubuntu and Debian, use /usr/local/share/ca-certificates/
    sudo cp azure-iot-test-only.root.ca.cert.pem /usr/local/share/azure-iot-test-only.root.ca.cert.pem.crt
    # For EFLOW, use /etc/pki/ca-trust/source/anchors/
    sudo cp azure-iot-test-only.root.ca.cert.pem /etc/pki/ca-trust/source/anchors/azure-iot-test-only.root.ca.pem.crt
    
  4. 更改证书和密钥的所有权和权限。

    # Give aziotcs ownership to certificates
    # Read and write for aziotcs, read-only for others
    sudo chown -R aziotcs:aziotcs /var/aziot/certs
    sudo find /var/aziot/certs -type f -name "*.*" -exec chmod 644 {} \;
    
    # Give aziotks ownership to private keys
    # Read and write for aziotks, no permission for others
    sudo chown -R aziotks:aziotks /var/aziot/secrets
    sudo find /var/aziot/secrets -type f -name "*.*" -exec chmod 600 {} \;
    
  5. 通过使用特定于平台的命令更新设备上的证书存储,在下游 IoT Edge 设备上安装根 CA 证书。

    # Update the certificate store
    
    # For Ubuntu or Debian - use update-ca-certificates
    sudo update-ca-certificates
    # For EFLOW or RHEL - use update-ca-trust
    sudo update-ca-trust
    

    有关在 EFLOW 中使用 update-ca-trust 的详细信息,请参阅 CBL-Mariner SSL CA 证书管理

该命令报告了已将一个证书添加到 /etc/ssl/certs

Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.

更新下游配置文件

你应该已在设备上安装了 IoT Edge。 如果没有,按照步骤手动预配单个 Linux IoT Edge 设备

  1. 验证下游设备上是否存在 /etc/aziot/config.toml 配置文件。

    如果设备上不存在配置文件,请使用以下命令基于模板文件创建该文件:

    sudo cp /etc/aziot/config.toml.edge.template /etc/aziot/config.toml
    

    还可以使用模板文件作为参考,添加本部分中的配置参数。

  2. 使用编辑器打开 IoT Edge 配置文件。 例如,使用 nano 编辑器打开 /etc/aziot/config.toml 文件。

    sudo nano /etc/aziot/config.toml
    
  3. 找到 parent_hostname 参数,或将其添加到配置文件的开头。每个下游 IoT Edge 设备都需要指定一个 parent_hostname 参数来标识其父级。 将 parent_hostname 参数更新为父设备的 FQDN 或 IP 地址,使之与父设备的配置文件中作为主机名提供的内容匹配。 例如:

    parent_hostname = "10.0.0.4"
    
  4. 查找“信任捆绑包证书”参数,或将其添加到配置文件的开头。

    trust_bundle_cert 参数更新为设备上根 CA 证书的文件 URI。 例如:

    trust_bundle_cert = "file:///var/aziot/certs/azure-iot-test-only.root.ca.cert.pem"
    
  5. 在配置文件中找到或添加“Edge CA certificate”部分。 使用 IoT Edge 下游设备上全链证书和密钥文件的文件 URI 路径来更新证书 cert 和私钥 pk 参数。 IoT Edge 要求证书和私钥采用基于文本的隐私增强邮件 (PEM) 格式。 例如:

    [edge_ca]
    cert = "file:///var/aziot/certs/iot-device-downstream-full-chain.cert.pem"
    pk = "file:///var/aziot/secrets/iot-device-downstream.key.pem"
    
  6. 验证 IoT Edge 设备在启动时是否使用正确版本的 IoT Edge 代理。 找到“Default Edge Agent”节,并将 IoT Edge 的映像值设置为版本 1.4。 例如:

    [agent.config]
    image: "mcr.microsoft.com/azureiotedge-agent:1.4"
    
  7. 下游配置文件的开头应类似于以下示例所示。

    parent_hostname = "10.0.0.4"
    trust_bundle_cert = "file:///var/aziot/certs/azure-iot-test-only.root.ca.cert.pem"
    
    [edge_ca]
    cert = "file:///var/aziot/certs/iot-device-downstream-full-chain.cert.pem"
    pk = "file:///var/aziot/secrets/iot-device-downstream.key.pem"
    
  8. 保存并关闭 config.toml 配置文件。 例如,如果使用 nano 编辑器,请选择 Ctrl+O - “写出”、Enter 和 Ctrl+X - “退出”。

  9. 如果以前使用过 IoT Edge 的任何其他证书,请删除以下两个目录中的文件,以确保新证书得到应用:

    • /var/lib/aziot/certd/certs
    • /var/lib/aziot/keyd/keys
  10. 单击“应用”以应用更改。

    sudo iotedge config apply
    
  11. 检查配置中是否有任何错误。

    sudo iotedge check --verbose
    

    提示

    IoT Edge 检查工具使用容器来执行某些诊断检查。 若要在下游 IoT Edge 设备上使用此工具,请确保它们可以访问 mcr.microsoft.com/azureiotedge-diagnostics:latest,或将容器映像置于专用容器注册表中。

    注意

    在新预配的设备上,可能会看到与 IoT Edge 中心相关的错误:

    × 生产就绪性:Edge 中心的存储目录持久保存在主机文件系统上- 错误

    无法检查 edgeHub 容器的当前状态

    由于 IoT Edge 中心模块未运行,在新预配的设备上预期会出现此错误。 若要解决此错误,请在 IoT 中心为设备设置模块并创建部署。 为设备创建部署会启动设备上的模块,包括 IoT Edge 中心模块。

网络隔离的下游设备

本文中到目前为止的步骤可将 IoT Edge 设备设置为网关或下游设备,并在其间创建一个信任连接。 网关设备处理下游设备与 IoT 中心之间的交互,包括身份验证和消息路由。 部署到下游 IoT Edge 设备的模块仍可创建其自己的到云服务的连接。

某些网络体系结构(例如那些遵循 ISA-95 标准的网络体系结构)会尝试最大程度地减少 Internet 连接数。 在这些方案中,你可以配置没有直接 Internet 连接的下游 IoT Edge 设备。 除了通过网关设备路由 IoT 中心通信之外,下游 IoT Edge 设备还可以依赖网关设备进行所有的云连接。

此网络配置要求仅网关层次结构顶层的 IoT Edge 设备能够直接连接到云。 下层中的 IoT Edge 设备只能与其父设备或子设备通信。 网关设备上的特殊模块可启用此方案,这些模块包括:

  • API 代理模块:在任何 IoT Edge 网关(在其下有另一个 IoT Edge 设备)上都是必需的。 这意味着,它必须位于网关层次结构的每个层(底层除外)。 此模块使用 nginx 反向代理在单个端口上通过网络层路由 HTTP 数据。 它的可配置性高(可以通过模块孪生和环境变量进行配置),因此可以根据网关方案要求对其进行调整。

  • 可以在网关层次结构顶层的 IoT Edge 网关上部署 Docker 注册表模块。 此模块负责检索和缓存那些代表下层中的所有 IoT Edge 设备的容器映像。 在顶层部署此模块的替代方法是使用本地注册表,或者手动将容器映像加载到设备上,并将模块拉取策略设置为 never。

  • 可以在网关层次结构顶层的 IoT Edge 网关上部署 IoT Edge 上的 Azure Blob 存储。 此模块负责上传那些代表下层中的所有 IoT Edge 设备的 blob。 上传 blob 的功能还为下层中的 IoT Edge 设备启用了有用的故障排除功能,例如模块日志上传和支持包上传。

网络配置

对于顶层中的每个网关设备,网络操作员需要执行以下操作:

  • 提供静态 IP 地址或完全限定的域名 (FQDN)。

  • 授权通过端口 443 (HTTPS) 和5671 (AMQP) 进行的从此 IP 地址到 Azure IoT 中心主机名的出站通信。

  • 授权通过端口 443 (HTTPS) 进行的从此 IP 地址到 Azure 容器注册表主机名的出站通信。

    API 代理模块一次只能处理到一个容器注册表的连接。 建议拥有所有容器映像,包括 Azure 容器注册表 (mcr.microsoft.com) 提供的公共映像,这些映像存储在专用容器注册表中。

对于下层中的每个网关设备,网络操作员需要执行以下操作:

  • 提供静态 IP 地址。
  • 授权通过端口 443 (HTTPS) 和5671 (AMQP) 进行的从此 IP 地址到父网关的 IP 地址的出站通信。

将模块部署到顶层设备

除了可以在设备上运行的任何工作负荷模块外,网关层次结构顶层的 IoT Edge 设备还有一组必须部署到其中的必需模块。

API 代理模块已经过设计,可以通过自定义来处理最常见的网关方案。 本文提供了一个以基本配置设置模块的示例。 有关详细信息和示例,请参阅配置适用于网关层次结构方案的 API 代理模块

  1. Azure 门户中导航到 IoT 中心。

  2. 在“设备管理”菜单下选择“设备”。

  3. 从列表中选择要配置的顶层 IoT Edge 设备。

  4. 选择“设置模块”。

  5. 在“IoT Edge 模块”部分选择“添加”,然后选择“市场模块” 。

  6. 搜索并选择“IoT Edge API 代理”模块。

  7. 从已部署模块的列表中选择 API 代理模块的名称,并更新以下模块设置:

    1. 在“环境变量”选项卡中,将 NGINX_DEFAULT_PORT 的值更新为 443

    2. 在“容器创建选项”选项卡中,将端口绑定更新为引用端口 443。

      {
        "HostConfig": {
          "PortBindings": {
            "443/tcp": [
              {
                "HostPort": "443"
              }
            ]
          }
        }
      }
      

    这些更改将 API 代理模块配置为在端口 443 上进行侦听。 若要防止端口绑定冲突,需要将 edgeHub 模块配置为不在端口 443 上进行侦听。 改为让 API 代理模块在端口 443 上路由任何 edgeHub 流量。

  8. 选择“运行时设置”并查找 edgeHub 模块创建选项。 删除端口 443 的端口绑定,保留端口 5671 和 8883 的绑定。

    {
      "HostConfig": {
        "PortBindings": {
          "5671/tcp": [
            {
              "HostPort": "5671"
            }
          ],
          "8883/tcp": [
            {
              "HostPort": "8883"
            }
          ]
        }
      }
    }
    
  9. 选择“保存”,将更改保存到运行时设置。

  10. 再次选择“添加”,然后选择“IoT Edge 模块” 。

  11. 提供以下值,以便将 Docker 注册表模块添加到你的部署:

    1. IoT Edge 模块名称:registry

    2. “模块设置”选项卡中的“映像 URI”:registry:latest

    3. 在“环境变量”选项卡上,添加以下环境变量:

      • Name: REGISTRY_PROXY_REMOTEURLValue:希望此注册表模块映射到的容器注册表的 URL。 例如,https://myregistry.azurecr

        注册表模块只能映射到一个容器注册表,因此,建议将所有容器映像置于单个专用容器注册表中。

      • Name: REGISTRY_PROXY_USERNAMEValue:用于向容器注册表进行身份验证的用户名。

      • Name: REGISTRY_PROXY_PASSWORDValue:用于向容器注册表进行身份验证的密码。

    4. 在“容器创建选项”选项卡上,粘贴以下内容:

      {
          "HostConfig": {
              "PortBindings": {
                  "5000/tcp": [
                      {
                          "HostPort": "5000"
                      }
                  ]
              }
          }
      }
      
  12. 选择“添加”,将模块添加到部署中。

  13. 选择“下一步:路由”以转到下一步。

  14. 若要允许来自下游设备的设备到云的消息到达 IoT 中心,请包括将所有消息传递到 IoT 中心的路由。 例如:

    1. 名称Route
    2. FROM /messages/* INTO $upstream
  15. 选择“查看 + 创建”,转到最后一步。

  16. 选择“创建”以部署到设备。

将模块部署到下层设备

除了可以在设备上运行的任何工作负荷模块外,网关层次结构下层的 IoT Edge 设备还有一个必须部署到其中的必需模块。

路由容器映像拉取

在讨论网关层次结构中的 IoT Edge 设备所需的代理模块之前,务必了解下层中的 IoT Edge 设备如何获取其模块映像。

如果下层设备无法连接到云,但你希望它们照常拉取模块映像,则必须将网关层次结构的顶层设备配置为处理这些请求。 顶层设备需要运行一个映射到容器注册表的 Docker 注册表模块。 然后,配置 API 代理模块,以便将容器请求路由到该模块。 本文前面的部分已讨论这些详细信息。 在此配置中,下层设备不应指向云容器注册表,而应指向在顶层运行的注册表。

例如,下层设备应调用 $upstream:443/azureiotedge-api-proxy:1.1,而不应调用 mcr.microsoft.com/azureiotedge-api-proxy:1.1

$upstream 参数指向下层设备的父设备,因此,请求会以路由的形式通过所有层,直到到达顶层,而顶层的代理环境会将容器请求路由到注册表模块。 此示例中的 :443 端口应替换为父设备上的 API 代理模块正在侦听的端口。

API 代理模块只能路由到一个注册表模块,每个注册表模块只能映射到一个容器注册表。 因此,下层设备需要拉取的任何映像都必须存储在单个容器注册表中。

如果不希望下层设备通过网关层次结构发出模块拉取请求,则可通过另一个选项管理本地注册表解决方案。 也可在创建部署之前将模块映像推送到设备上,然后将 imagePullPolicy 设置为 never。

启动 IoT Edge 代理

IoT Edge 代理是在任意 IoT Edge 设备上启动的第一个运行时组件。 需确保任何下游 IoT Edge 设备可以在启动时访问 edgeAgent 模块映像,然后可以访问部署并启动其余的模块映像。

在进入 IoT Edge 设备上的配置文件以提供设备的身份验证信息、证书和父主机名时,也请更新 edgeAgent 容器映像。

如果顶级网关设备配置为处理容器映像请求,请将 mcr.microsoft.com 替换为父主机名和 API 代理侦听端口。 在部署清单中,可以将 $upstream 用作快捷方式,但这需要 edgeHub 模块来处理路由,而该模块此时尚未启动。 例如:

[agent]
name = "edgeAgent"
type = "docker"

[agent.config]
image: "{Parent FQDN or IP}:443/azureiotedge-agent:1.4"

如果使用本地容器注册表,或在设备上手动提供容器映像,请相应地更新配置文件。

配置运行时和部署代理模块

需要 API 代理模块来路由云和任何下游 IoT Edge 设备之间的所有通信。 层次结构底层中的 IoT Edge 设备(没有下游 IoT Edge 设备)不需要此模块。

API 代理模块已经过设计,可以通过自定义来处理最常见的网关方案。 本文简要介绍了以基本配置设置模块的步骤。 有关详细信息和示例,请参阅配置适用于网关层次结构方案的 API 代理模块

  1. Azure 门户中导航到 IoT 中心。

  2. 在“设备管理”菜单下选择“设备”。

  3. 从列表中选择要配置的下层 IoT Edge 设备。

  4. 选择“设置模块”。

  5. 在“IoT Edge 模块”部分选择“添加”,然后选择“市场模块” 。

  6. 搜索并选择“IoT Edge API 代理”模块。

  7. 从已部署模块的列表中选择 API 代理模块的名称,并更新以下模块设置:

    1. 在“模块设置”选项卡中,更新“映像 URI”的值。 将 mcr.microsoft.com 替换为 $upstream:443

    2. 在“环境变量”选项卡中,将 NGINX_DEFAULT_PORT 的值更新为 443

    3. 在“容器创建选项”选项卡中,将端口绑定更新为引用端口 443。

      {
        "HostConfig": {
          "PortBindings": {
            "443/tcp": [
              {
                "HostPort": "443"
              }
            ]
          }
        }
      }
      

    这些更改将 API 代理模块配置为在端口 443 上进行侦听。 若要防止端口绑定冲突,需要将 edgeHub 模块配置为不在端口 443 上进行侦听。 改为让 API 代理模块在端口 443 上路由任何 edgeHub 流量。

  8. 选择“运行时设置”。

  9. 更新 edgeHub 模块设置:

    1. 在“映像”字段中,将 mcr.microsoft.com 替换为 $upstream:443
    2. 在“创建选项”字段中,删除端口 443 的端口绑定,保留端口 5671 和 8883 的绑定。
    {
      "HostConfig": {
        "PortBindings": {
          "5671/tcp": [
            {
              "HostPort": "5671"
            }
          ],
          "8883/tcp": [
            {
              "HostPort": "8883"
            }
          ]
        }
      }
    }
    
  10. 更新 edgeAgent 模块设置:

    1. 在“映像”字段中,将 mcr.microsoft.com 替换为 $upstream:443
  11. 选择“保存”,将更改保存到运行时设置。

  12. 在完成时选择“下一步:路由”以转到下一步。

  13. 若要允许来自下游设备的设备到云的消息到达 IoT 中心,请包括将所有消息传递到 $upstream 的路由。 如果使用的是下层设备,则 upstream 参数指向父设备。 例如:

    1. 名称Route
    2. FROM /messages/* INTO $upstream
  14. 选择“查看 + 创建”,转到最后一步。

  15. 选择“创建”以部署到设备。

验证从子级到父级的连接

  1. 通过在下游设备上运行以下 openssl 命令,验证从子级到父级的 TLS/SSL 连接。 将 <parent hostname> 替换为父级的 FQDN 或 IP 地址。

    openssl s_client -connect <parent hostname>:8883 </dev/null 2>&1 >/dev/null
    

    该命令应断言父证书链验证成功,类似于以下示例:

    azureUser@child-vm:~$ openssl s_client -connect <parent hostname>:8883 </dev/null 2>&1 >/dev/null
    Can't use SSL_get_servername
    depth=3 CN = Azure_IoT_Hub_CA_Cert_Test_Only
    verify return:1
    depth=2 CN = Azure_IoT_Hub_Intermediate_Cert_Test_Only
    verify return:1
    depth=1 CN = gateway.ca
    verify return:1
    depth=0 CN = <parent hostname>
    verify return:1
    DONE
    

    可以忽略“无法使用 SSL_get_servername”消息。

    depth=0 CN = 值应与父级 config.toml 配置文件中指定的 hostname 参数匹配。

    如果命令超时,则可能是子设备和父设备之间的端口被阻塞。 请查看设备的网络配置和设置。

    警告

    不在网关的 [edge_ca] 部分中使用全链证书会导致下游设备出现证书验证错误。 例如,上面的 openssl s_client ... 命令会生成:

    Can't use SSL_get_servername
    depth=1 CN = gateway.ca
    verify error:num=20:unable to get local issuer certificate
    verify return:1
    depth=0 CN = <parent hostname>
    verify return:1
    DONE
    

    如果未在下游设备上使用和配置全链设备证书,则连接到下游 IoT Edge 设备的已启用 TLS 的设备也会出现相同的问题。

将 Microsoft Defender for IoT 与 IoT Edge 网关集成

下游设备可用于使用下游设备代理将 Microsoft Defender for IoT 的微代理与 IoT Edge 网关集成。

若要使用下游设备代理将 Microsoft Defender for IoT 与 IoT Edge 集成,请执行以下操作:

  1. 登录到 Azure 门户。

  2. 导航到“IoT 中心”>Your Hub>“设备管理”>“设备”

  3. 选择你的设备。

    Screenshot showing where your device is located for selection.

  4. 选择创建的 DefenderIotMicroAgent 模块孪生。

    Screenshot showing the location of the DefenderIotMicroAgent.

  5. 选择 按钮以复制连接字符串(主密钥)。

  6. 将连接字符串粘贴到文本编辑应用程序中,然后将 GatewayHostName 添加到字符串。 例如,HostName=nested11.azure-devices.cn;DeviceId=downstream1;ModuleId=module1;SharedAccessKey=xxx;GatewayHostName=10.16.7.4

  7. 在下游设备上打开终端。

  8. 使用以下命令将 Defender for Cloud Agent 目录中以 utf-8 编码的连接字符串放入以下路径中的文件 connection_string.txt/etc/defender_iot_micro_agent/connection_string.txt

    sudo bash -c 'echo "<connection string>" > /etc/defender_iot_micro_agent/connection_string.txt'
    

    connection_string.txt 现应在路径位置 /etc/defender_iot_micro_agent/connection_string.txt 中。

  9. 使用以下命令重启服务:

    sudo systemctl restart defender-iot-micro-agent.service 
    
  10. 导航回到设备。

    Screenshot showing how to navigate back to your device.

  11. 启用与 IoT 中心的连接,然后选择齿轮图标。

    Screenshot showing what to select to set a parent device.

  12. 从显示的列表中选择父设备。

  13. 确保下游设备和 IoT Edge 设备之间的端口 8883 (MQTT) 已打开。

后续步骤

如何将 IoT Edge 设备用作网关

配置适用于网关层次结构方案的 API 代理模块