了解如何在 IoT Edge 中部署模块和建立路由Learn how to deploy modules and establish routes in IoT Edge

每个 IoT Edge 设备至少运行两个模块:$edgeAgent 和 $edgeHub,它们构成了 IoT Edge 运行时。Each IoT Edge device runs at least two modules: $edgeAgent and $edgeHub, which are part of the IoT Edge runtime. IoT Edge 设备可以为任意数量的进程运行多个附加模块。IoT Edge device can run multiple additional modules for any number of processes. 使用部署清单告知设备要安装哪些模块以及如何将它们配置为协同工作。Use a deployment manifest to tell your device which modules to install and how to configure them to work together.

部署清单是一个 JSON 文档,用于描述以下内容:The deployment manifest is a JSON document that describes:

  • IoT Edge 代理模块孪生,其中包括三个组件:The IoT Edge agent module twin, which includes three components:
    • 在设备上运行的每个模块的容器映像。The container image for each module that runs on the device.
    • 用于访问包含模块映像的专用容器注册表的凭据。The credentials to access private container registries that contain module images.
    • 有关如何创建和管理每个模块的说明。Instructions for how each module should be created and managed.
  • IoT Edge 中心模块孪生:描述消息如何在模块之间流动,并最终传送到 IoT 中心。The IoT Edge hub module twin, which includes how messages flow between modules and eventually to IoT Hub.
  • 任何附加模块孪生的所需属性(可选)。The desired properties of any additional module twins (optional).

必须使用部署清单配置所有 IoT Edge 设备。All IoT Edge devices must be configured with a deployment manifest. 在使用有效清单进行配置前,新安装的 IoT Edge 运行时会报告错误代码。A newly installed IoT Edge runtime reports an error code until configured with a valid manifest.

在 Azure IoT Edge 教程中,你将通过 Azure IoT Edge 门户中的向导生成部署清单。In the Azure IoT Edge tutorials, you build a deployment manifest by going through a wizard in the Azure IoT Edge portal. 此外,也可以使用 REST 或 IoT 中心服务 SDK 以编程方式应用部署清单。You can also apply a deployment manifest programmatically using REST or the IoT Hub Service SDK. 有关详细信息,请参阅了解 IoT Edge 部署For more information, see Understand IoT Edge deployments.

创建部署清单。Create a deployment manifest

从较高层面讲,部署清单是配置了所需属性的模块孪生的列表。At a high level, a deployment manifest is a list of module twins that are configured with their desired properties. 部署清单告知某个 IoT Edge 设备(或一组设备)要安装哪些模块,以及如何配置这些模块。A deployment manifest tells an IoT Edge device (or a group of devices) which modules to install and how to configure them. 部署清单包含每个模块孪生的所需属性。Deployment manifests include the desired properties for each module twin. IoT Edge 设备将报告每个模块的报告属性。IoT Edge devices report back the reported properties for each module.

每个部署清单中需要两个模块:$edgeAgent$edgeHubTwo modules are required in every deployment manifest: $edgeAgent, and $edgeHub. 这些模块属于管理 IoT Edge 设备及其上运行的模块的 IoT Edge 运行时。These modules are part of the IoT Edge runtime that manages the IoT Edge device and the modules running on it. 有关这些模块的详细信息,请参阅了解 IoT Edge 运行时及其体系结构For more information about these modules, see Understand the IoT Edge runtime and its architecture.

除了两个运行时模块以外,还可以添加最多 30 个你自己的要在 IoT Edge 设备上运行的模块。In addition to the two runtime modules, you can add up to 30 modules of your own to run on an IoT Edge device.

仅包含 IoT Edge 运行时(edgeAgent 和 edgeHub)的部署清单是有效的。A deployment manifest that contains only the IoT Edge runtime (edgeAgent and edgeHub) is valid.

部署清单遵循以下结构:Deployment manifests follow this structure:

{
    "modulesContent": {
        "$edgeAgent": { // required
            "properties.desired": {
                // desired properties of the Edge agent
                // includes the image URIs of all modules
                // includes container registry credentials
            }
        },
        "$edgeHub": { //required
            "properties.desired": {
                // desired properties of the Edge hub
                // includes the routing information between modules, and to IoT Hub
            }
        },
        "module1": {  // optional
            "properties.desired": {
                // desired properties of module1
            }
        },
        "module2": {  // optional
            "properties.desired": {
                // desired properties of module2
            }
        },
        ...
    }
}

配置模块Configure modules

定义 IoT Edge 运行时如何在部署中安装模块。Define how the IoT Edge runtime installs the modules in your deployment. IoT Edge 代理是管理 IoT Edge 设备的安装、更新和状态报告的运行时组件。The IoT Edge agent is the runtime component that manages installation, updates, and status reporting for an IoT Edge device. 因此,$edgeAgent 模块孪生包含所有模块的配置和管理信息。Therefore, the $edgeAgent module twin contains the configuration and management information for all modules. 此信息包括 IoT Edge 代理本身的配置参数。This information includes the configuration parameters for the IoT Edge agent itself.

有关可以或必须包含的属性的完整列表,请参阅 IoT Edge 代理和 IoT Edge 中心的属性For a complete list of properties that can or must be included, see Properties of the IoT Edge agent and IoT Edge hub.

$edgeAgent 属性遵循此结构:The $edgeAgent properties follow this structure:

"$edgeAgent": {
    "properties.desired": {
        "schemaVersion": "1.0",
        "runtime": {
            "settings":{
                "registryCredentials":{ // give the edge agent access to container images that aren't public
                    }
                }
            }
        },
        "systemModules": {
            "edgeAgent": {
                // configuration and management details
            },
            "edgeHub": {
                // configuration and management details
            }
        },
        "modules": {
            "module1": { // optional
                // configuration and management details
            },
            "module2": { // optional
                // configuration and management details
            }
        }
    }
},

声明路由Declare routes

IoT Edge 中心管理模块、IoT 中心与所有叶设备之间的通信。The IoT Edge hub manages communication between modules, IoT Hub, and any leaf devices. 因此,$edgeHub 模块孪生包含名为 routes 的所需属性,该属性声明如何在部署中传递消息。Therefore, the $edgeHub module twin contains a desired property called routes that declares how messages are passed within a deployment. 可以在同一个部署中创建多个路由。You can have multiple routes within the same deployment.

使用以下语法在 $edgeHub 所需属性中声明路由:Routes are declared in the $edgeHub desired properties with the following syntax:

"$edgeHub": {
    "properties.desired": {
        "routes": {
            "route1": "FROM <source> WHERE <condition> INTO <sink>",
            "route2": "FROM <source> WHERE <condition> INTO <sink>"
        },
    }
}

每个路由需要源和接收器,但条件是可用于筛选消息的可选片断。Every route needs a source and a sink, but the condition is an optional piece that you can use to filter messages.

Source

源指定消息来自何处。The source specifies where the messages come from. IoT Edge 可以路由来自模块或叶设备的消息。IoT Edge can route messages from modules or leaf devices.

通过 IoT SDK,模块可以使用 ModuleClient 类为其消息声明特定的输出队列。Using the IoT SDKs, modules can declare specific output queues for their messages using the ModuleClient class. 输出队列不是必需的,但对于管理多个路由很有帮助。Output queues aren't necessary, but are helpful for managing multiple routes. 叶设备可以使用 IoT SDK 的 DeviceClient 类将消息发送到 IoT Edge 网关设备,就像它们将消息发送到 IoT 中心一样。Leaf devices can use the DeviceClient class of the IoT SDKs to send messages to IoT Edge gateway devices in the same way that they would send messages to IoT Hub. 有关详细信息,请参阅了解和使用 Azure IoT 中心 SDKFor more information, see Understand and use Azure IoT Hub SDKs.

源属性可采用以下任何值:The source property can be any of the following values:

Source 说明Description
/* 所有设备到云的消息,或者来自任何模块或叶设备的孪生更改通知All device-to-cloud messages or twin change notifications from any module or leaf device
/twinChangeNotifications 来自任何模块或叶设备的任何孪生更改(报告属性)Any twin change (reported properties) coming from any module or leaf device
/messages/* 由模块或叶设备通过某种输出或不通过任何输出发送的任何设备到云的消息Any device-to-cloud message sent by a module through some or no output, or by a leaf device
/messages/modules/* 由带部分输出或不带输出的模块发送的任何设备到云的消息Any device-to-cloud message sent by a module through some or no output
/messages/modules/<moduleId>/* 由特定模块通过某种输出或不通过任何输出发送的任何设备到云的消息Any device-to-cloud message sent by a specific module through some or no output
/messages/modules/<moduleId>/outputs/* 由特定模块通过某种输出发送的任何设备到云的消息Any device-to-cloud message sent by a specific module through some output
/messages/modules/<moduleId>/outputs/<output> 由特定模块通过特定输出发送的任何设备到云的消息Any device-to-cloud message sent by a specific module through a specific output

条件Condition

条件在路由声明中是可选的。The condition is optional in a route declaration. 若要将所有消息从源传递到接收器,完全省略 WHERE 子句即可。If you want to pass all messages from the source to the sink, just leave out the WHERE clause entirely. 或者,可以使用 IoT 中心查询语言来筛选满足条件的特定消息或消息类型。Or you can use the IoT Hub query language to filter for certain messages or message types that satisfy the condition. IoT Edge 路由不支持基于孪生标记或属性筛选消息。IoT Edge routes don't support filtering messages based on twin tags or properties.

在 IoT Edge 中的模块之间传递的消息与在设备和 Azure IoT 中心之间传递的消息的格式是一样的。The messages that pass between modules in IoT Edge are formatted the same as the messages that pass between your devices and Azure IoT Hub. 所有消息都是 JSON 格式的,并具备 systemProperties、appProperties 和 body 参数 。All messages are formatted as JSON and have systemProperties, appProperties, and body parameters.

可使用以下语法围绕三个参数中的任何一个生成查询:You can build queries around any of the three parameters with the following syntax:

  • 系统属性:$<propertyName>{$<propertyName>}System properties: $<propertyName> or {$<propertyName>}
  • 应用程序属性:<propertyName>Application properties: <propertyName>
  • 正文属性:$body.<propertyName>Body properties: $body.<propertyName>

请参考设备到云消息路由查询表达式,查看针对消息属性创建查询的示例。For examples about how to create queries for message properties, see Device-to-cloud message routes query expressions.

有一个 IoT Edge 特定的示例,即筛选从叶设备到网关设备的消息的情况。An example that is specific to IoT Edge is when you want to filter for messages that arrived at a gateway device from a leaf device. 来自模块的消息包含名为 connectionModuleId 的系统属性。Messages that come from modules include a system property called connectionModuleId. 因此,若要将消息从叶设备直接路由到 IoT 中心,请使用以下路由来排除模块消息:So if you want to route messages from leaf devices directly to IoT Hub, use the following route to exclude module messages:

FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream

接收器Sink

接收器定义消息发送到的位置。The sink defines where the messages are sent. 只有模块和 IoT 中心可以接收消息。Only modules and IoT Hub can receive messages. 无法将消息路由到其他设备。Messages can't be routed to other devices. 接收器属性中没有通配符选项。There are no wildcard options in the sink property.

接收器属性可采用以下任何值:The sink property can be any of the following values:

接收器Sink 说明Description
$upstream 将消息发送到 IoT 中心Send the message to IoT Hub
BrokeredEndpoint("/modules/<moduleId>/inputs/<input>") 将消息发送到特定模块的特定输入Send the message to a specific input of a specific module

IoT Edge 提供至少一次保证。IoT Edge provides at-least-once guarantees. IoT Edge 中心在本地存储消息,以防路由无法将消息传送到其接收器。The IoT Edge hub stores messages locally in case a route can't deliver the message to its sink. 例如,如果 IoT Edge 中心无法连接到 IoT 中心,或者目标模块未连接。For example, if the IoT Edge hub can't connect to IoT Hub, or the target module isn't connected.

IoT Edge 中心会一直存储消息,直到达到在 IoT Edge 中心所需属性storeAndForwardConfiguration.timeToLiveSecs 属性中指定的时间。IoT Edge hub stores the messages up to the time specified in the storeAndForwardConfiguration.timeToLiveSecs property of the IoT Edge hub desired properties.

定义或更新所需属性Define or update desired properties

部署清单指定部署到 IoT Edge 设备的每个模块的所需属性。The deployment manifest specifies desired properties for each module deployed to the IoT Edge device. 部署清单中的所需属性会覆盖模块孪生中当前存在的任何所需属性。Desired properties in the deployment manifest overwrite any desired properties currently in the module twin.

如果未在部署清单中指定模块孪生的所需属性,则 IoT 中心不会以任何方式修改模块孪生。If you do not specify a module twin's desired properties in the deployment manifest, IoT Hub won't modify the module twin in any way. 可以编程方式设置所需属性。Instead, you can set the desired properties programmatically.

将使用用来修改设备孪生的相同机制来修改模块孪生。The same mechanisms that allow you to modify device twins are used to modify module twins. 有关详细信息,请参阅模块孪生开发人员指南For more information, see the module twin developer guide.

部署清单示例Deployment manifest example

以下示例演示了有效部署清单文档的外观。The following example shows what a valid deployment manifest document may look like.

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "schemaVersion": "1.0",
        "runtime": {
          "type": "docker",
          "settings": {
            "minDockerVersion": "v1.25",
            "loggingOptions": "",
            "registryCredentials": {
              "ContosoRegistry": {
                "username": "myacr",
                "password": "<password>",
                "address": "myacr.azurecr.cn"
              }
            }
          }
        },
        "systemModules": {
          "edgeAgent": {
            "type": "docker",
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-agent:1.0",
              "createOptions": ""
            }
          },
          "edgeHub": {
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-hub:1.0",
              "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}"
            }
          }
        },
        "modules": {
          "SimulatedTemperatureSensor": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
              "createOptions": "{}"
            }
          },
          "filtermodule": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "env": {
              "tempLimit": {"value": "100"}
            },
            "settings": {
              "image": "myacr.azurecr.cn/filtermodule:latest",
              "createOptions": "{}"
            }
          }
        }
      }
    },
    "$edgeHub": {
      "properties.desired": {
        "schemaVersion": "1.0",
        "routes": {
          "sensorToFilter": "FROM /messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/input1\")",
          "filterToIoTHub": "FROM /messages/modules/filtermodule/outputs/output1 INTO $upstream"
        },
        "storeAndForwardConfiguration": {
          "timeToLiveSecs": 10
        }
      }
    }
  }
}

后续步骤Next steps