了解如何在 IoT Edge 中部署模組及建立路由

適用于: IoT Edge 1.4 checkmark IoT Edge 1.4

重要

支援的版本是 IoT Edge 1.4。 如果您是舊版,請參閱更新 IoT Edge

每個 IoT Edge 裝置至少會執行兩個模組:$edgeAgent和$edgeHub,這是 IoT Edge 執行時間的一部分。 IoT Edge 裝置可以針對任意數目的進程執行多個模組。 使用部署資訊清單來告知您的裝置要安裝哪些模組,以及如何設定它們以一起運作。

部署資訊清單 是 JSON 檔,描述:

  • IoT Edge 代理程式 模組對應項,其中包含三個元件:
    • 裝置上執行之每個模組的容器映射。
    • 用來存取包含模組映射之私人容器登錄的認證。
    • 如何建立和管理每個模組的指示。
  • IoT Edge 中 模組對應項,其中包含訊息在模組之間流動的方式,以及最終流向IoT 中樞的方式。
  • 任何額外模組對應項的所需屬性(選擇性)。

所有 IoT Edge 裝置都必須使用部署資訊清單進行設定。 新安裝的 IoT Edge 執行時間會報告錯誤碼,直到使用有效的資訊清單進行設定為止。

在 Azure IoT Edge 教學課程中,您會透過 Azure IoT Edge 入口網站中的精靈來建置部署資訊清單。 您也可以使用 REST 或 IoT 中樞 Service SDK,以程式設計方式套用部署資訊清單。 如需詳細資訊,請參閱 瞭解 IoT Edge 部署

建立部署資訊清單

概括而言,部署資訊清單是模組對應項的清單,這些對應項會以其所需的屬性進行設定。 部署資訊清單會告訴 IoT Edge 裝置(或一組裝置)要安裝哪些模組,以及如何設定它們。 部署資訊清單包含 每個模組對應項所需的屬性 。 IoT Edge 裝置會回報每個模組的報告 屬性

每個部署資訊清單都需要兩個模組: $edgeAgent 、 和 $edgeHub 。 這些模組是 IoT Edge 執行時間的一部分,可管理 IoT Edge 裝置及其上執行的模組。 如需這些模組的詳細資訊,請參閱 瞭解 IoT Edge 執行時間及其架構

除了兩個執行階段模組之外,您可新增最多 50 個專屬的模組,以在 IoT Edge 裝置上執行。

只包含 IoT Edge 執行時間 (edgeAgent 和 edgeHub) 的部署資訊清單有效。

部署資訊清單遵循下列結構:

{
  "modulesContent": {
    "$edgeAgent": { // required
      "properties.desired": {
        // desired properties of the IoT Edge agent
        // includes the image URIs of all deployed modules
        // includes container registry credentials
      }
    },
    "$edgeHub": { //required
      "properties.desired": {
        // desired properties of the IoT 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
      }
    }
  }
}

設定模組

定義 IoT Edge 執行時間如何在部署中安裝模組。 IoT Edge 代理程式是管理 IoT Edge 裝置安裝、更新和狀態報表的執行時間元件。 因此,$edgeAgent模組對應項包含所有模組的組態和管理資訊。 此資訊包含 IoT Edge 代理程式本身的組態參數。

$edgeAgent屬性會遵循下列結構:

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

IoT Edge 代理程式架構 1.1 版與 IoT Edge 1.0.10 版一起發行,並啟用模組啟動順序。 針對執行 1.0.1 版或更新版本的任何 IoT Edge 部署,建議使用架構 1.1 版。

模組組態和管理

IoT Edge 代理程式所需的屬性清單是您定義要將哪些模組部署至 IoT Edge 裝置的位置,以及其設定和管理方式。

如需可或必須包含之所需屬性的完整清單,請參閱 IoT Edge 代理程式和 IoT Edge 中樞 的屬性。

例如:

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "runtime": { ... },
        "systemModules": {
          "edgeAgent": { ... },
          "edgeHub": { ... }
        },
        "modules": {
          "module1": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 2,
            "settings": {
              "image": "myacr.azurecr.io/module1:latest",
              "createOptions": "{}"
            }
          },
          "module2": { ... }
        }
      }
    },
    "$edgeHub": { ... },
    "module1": { ... },
    "module2": { ... }
  }
}

每個模組都有一個 設定 屬性,其中包含模組 映射 、容器登錄中容器映射的位址,以及任何 createOptions 在啟動時設定映射。 如需詳細資訊,請參閱 如何設定 IoT Edge 模組 的容器建立選項。

edgeHub 模組和自訂模組也有三個屬性,可告訴 IoT Edge 代理程式如何管理它們:

  • 狀態 :模組應該在第一次部署時執行或停止。 必要。

  • RestartPolicy :如果 IoT Edge 代理程式停止,應該重新開機模組的時機和時機。 如果模組停止且沒有任何錯誤,則不會自動啟動。 如需詳細資訊,請參閱 Docker Docs - 自動 啟動容器。 必要。

  • StartupOrder 在 IoT Edge 1.0.10 版中引進。 第一次部署時,IoT Edge 代理程式應該啟動模組的順序。 順序會以整數來宣告,其中指定啟動值為 0 的模組會先啟動,然後接著較高的數位。 edgeAgent 模組沒有啟動值,因為它一律會先啟動。 選擇性。

    IoT Edge 代理程式會依啟動值的順序起始模組,但不會等待每個模組完成開始,再移至下一個模組。

    如果某些模組相依于其他模組,啟動順序會很有説明。 例如,您可能想要先啟動 edgeHub 模組,以便在其他模組啟動時準備好路由訊息。 或者,您可能想要先啟動儲存體模組,再啟動將資料傳送至該模組的模組。 不過,您應該一律設計模組來處理其他模組的失敗。 容器的本質是容器隨時可能會停止和重新開機,以及任何次數。

    注意

    模組屬性的變更會導致該模組重新開機。 例如,如果您變更 下列屬性,就會重新開機:

    • 模組映射
    • Docker 建立選項
    • 環境變數
    • 重新開機原則
    • 映射提取原則
    • version
    • 啟動順序

    如果沒有變更模組屬性,模組將不會 重新開機。

宣告路由

IoT Edge 中樞會管理模組、IoT 中樞和任何下游裝置之間的通訊。 因此,$edgeHub模組對應項包含稱為路由 的所需屬性 ,可宣告訊息在部署內傳遞的方式。 您可以在相同的部署內有多個路由。

路由會在具有下列語法的$edgeHub 所需屬性中 宣告:

{
  "modulesContent": {
    "$edgeAgent": { ... },
    "$edgeHub": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "routes": {
          "route1": "FROM <source> WHERE <condition> INTO <sink>",
          "route2": {
            "route": "FROM <source> WHERE <condition> INTO <sink>",
            "priority": 0,
            "timeToLiveSecs": 86400
          }
        },
        "storeAndForwardConfiguration": {
          "timeToLiveSecs": 10
        }
      }
    },
    "module1": { ... },
    "module2": { ... }
  }
}

IoT Edge 中樞架構第 1 版與 IoT Edge 1.0.10 版一起發行,並啟用路由優先順序和存留時間。 針對執行 1.0.1 版或更新版本的任何 IoT Edge 部署,建議使用架構 1.1 版。

每個路由都需要 訊息的來源,以及 訊息所在的接收 。 條件 是可用來篩選訊息的選擇性部分。

您可以將優先順序 指派 給您想要確保先處理其訊息的路由。 這項功能對於上游連線弱式或有限,且您有應該優先處理于標準遙測訊息的重要資料時很有説明。

來源

來源會指定訊息的來源。 IoT Edge 可以從模組或下游裝置路由傳送訊息。

透過 IoT SDK,模組可以使用 ModuleClient 類別為其訊息宣告特定的輸出佇列。 輸出佇列並非必要,但有助於管理多個路由。 下游裝置可以使用 IoT SDK 的 DeviceClient 類別,以將訊息傳送至 IoT Edge 閘道裝置的方式,與將訊息傳送至IoT 中樞相同。 如需詳細資訊,請參閱 瞭解和使用Azure IoT 中樞 SDK

source 屬性可以是下列任何值:

來源 描述
/* 來自任何模組或下游裝置的所有裝置到雲端訊息或對應項變更通知
/twinChangeNotifications 來自任何模組或下游裝置的任何對應項變更 (報告屬性)
/messages/* 模組透過部分或無輸出或下游裝置傳送的任何裝置到雲端訊息
/messages/modules/* 模組透過部分或無輸出傳送的任何裝置到雲端訊息
/messages/modules/<moduleId>/* 特定模組透過部分或無輸出傳送的任何裝置到雲端訊息
/messages/modules/<moduleId>/outputs/* 特定模組透過某些輸出傳送的任何裝置到雲端訊息
/messages/modules/<moduleId>/outputs/<output> 特定模組透過特定輸出傳送的任何裝置到雲端訊息

條件

條件在路由宣告中是選擇性的。 如果您想要將所有訊息從來源傳遞至接收,請完全排除 WHERE 子句。 或者,您可以使用 IoT 中樞查詢語言 來篩選符合條件的特定訊息或訊息類型。 IoT Edge 路由不支援根據對應項標籤或屬性來篩選訊息。

IoT Edge 中模組之間傳遞的訊息會格式化為與裝置與Azure IoT 中樞之間傳遞的訊息相同。 所有訊息都會格式化為 JSON,並具有 systemProperties、 appProperties 主體 參數。

您可以使用下列語法,針對這三個參數中的任何一個建置查詢:

  • 系統屬性: $<propertyName>{$<propertyName>}
  • 應用程式屬性: <propertyName>
  • 主體屬性: $body.<propertyName>

如需如何建立訊息屬性查詢的範例,請參閱 裝置到雲端訊息路由查詢運算式

IoT Edge 特有的範例是,當您想要篩選從下游裝置抵達閘道裝置的訊息時。 從模組傳送的訊息包含名為 connectionModuleId 的系統屬性。 因此,如果您想要將訊息從下游裝置直接路由傳送至IoT 中樞,請使用下列路由來排除模組訊息:

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

接收

接收會定義訊息的傳送位置。 只有模組和IoT 中樞可以接收訊息。 訊息無法路由傳送至其他裝置。 sink 屬性中沒有萬用字元選項。

接收屬性可以是下列任何值:

接收 描述
$upstream 將訊息傳送至IoT 中樞
BrokeredEndpoint("/modules/<moduleId>/inputs/<input>") 將訊息傳送至特定模組的特定輸入

IoT Edge 提供至少一次保證。 如果路由無法將訊息傳遞至其接收,IoT Edge 中樞會將訊息儲存在本機。 例如,如果 IoT Edge 中樞無法連線到IoT 中樞,或目的模組未連線。

IoT Edge 中樞會將訊息儲存在 IoT Edge 中樞所需屬性 的 屬性 中指定的 storeAndForwardConfiguration.timeToLiveSecs 時間。

優先順序和存留時間

路由可以只使用定義路由的字串來宣告,或做為接受路由字串、優先順序整數和存留時間整數的物件。

選項 1:

"route1": "FROM <source> WHERE <condition> INTO <sink>",

選項 2,在 IoT Edge 1.0.10 版中引進,IoT Edge 中樞架構 1.1 版:

"route2": {
  "route": "FROM <source> WHERE <condition> INTO <sink>",
  "priority": 0,
  "timeToLiveSecs": 86400
}

優先順序 值可以是 0-9,包含,其中 0 是最高優先順序。 訊息會根據其端點排入佇列。 所有以特定端點為目標的優先順序 0 訊息都會在處理以相同端點為目標的任何優先順序 1 訊息之前處理,然後向下一行。 如果相同端點的多個路由具有相同的優先順序,其訊息將會以先到先得為基礎進行處理。 如果未指定優先順序,則會將路由指派給最低優先順序。

timeToLiveSecs 屬性會從 IoT Edge 中樞的 storeAndForwardConfiguration 繼承其值,除非明確設定。 此值可為任何正整數。

如需如何管理優先順序佇列的詳細資訊,請參閱路由優先順序和生存 時間的 參考頁面。

定義或更新所需的屬性

部署資訊清單會針對部署到 IoT Edge 裝置的每個模組指定所需的屬性。 部署資訊清單中的所需屬性會覆寫模組對應項中目前的任何所需屬性。

如果您未在部署資訊清單中指定模組對應項所需的屬性,IoT 中樞不會以任何方式修改模組對應項。 相反地,您可以透過程式設計方式設定所需的屬性。

可讓您修改裝置對應項的相同機制可用來修改模組對應項。 如需詳細資訊,請參閱模組對應 項開發人員指南

部署資訊清單範例

下列範例顯示有效的部署資訊清單檔外觀。

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "runtime": {
          "type": "docker",
          "settings": {
            "minDockerVersion": "v1.25",
            "loggingOptions": "",
            "registryCredentials": {
              "ContosoRegistry": {
                "username": "myacr",
                "password": "<password>",
                "address": "myacr.azurecr.io"
              }
            }
          }
        },
        "systemModules": {
          "edgeAgent": {
            "type": "docker",
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-agent:1.4",
              "createOptions": "{}"
            }
          },
          "edgeHub": {
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 0,
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-hub:1.4",
              "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",
            "startupOrder": 2,
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
              "createOptions": "{}"
            }
          },
          "filtermodule": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 1,
            "env": {
              "tempLimit": {"value": "100"}
            },
            "settings": {
              "image": "myacr.azurecr.io/filtermodule:latest",
              "createOptions": "{}"
            }
          }
        }
      }
    },
    "$edgeHub": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "routes": {
          "sensorToFilter": {
            "route": "FROM /messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/input1\")",
            "priority": 0,
            "timeToLiveSecs": 1800
          },
          "filterToIoTHub": {
            "route": "FROM /messages/modules/filtermodule/outputs/output1 INTO $upstream",
            "priority": 1,
            "timeToLiveSecs": 1800
          }
        },
        "storeAndForwardConfiguration": {
          "timeToLiveSecs": 100
        }
      }
    }
  }
}

下一步