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

適用於:IoT Edge 1.5 複選標記 IoT Edge 1.5 IoT Edge 1.4 複選標記 IoT Edge 1.4

重要

支援 IoT Edge 1.5 LTS 和 IoT Edge 1.4 LTS 版本。 IoT Edge 1.4 LTS 於 2024 年 11 月 12 日結束生命週期。 如果您是舊版,請參閱更新 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 裝置與在其上執行的模組。 如需這些模組的詳細資訊,請參閱 瞭解 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

來源屬性可以是下列其中任何一個值:

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

Condition

條件在路由宣告中是選擇性項目。 如果您想要將所有訊息從來源傳遞至接收,請完全排除 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 中樞能接收訊息。 訊息無法路由到其他裝置。 接收屬性中沒有任何萬用字元選項。

接收屬性可以是下列其中任何一個值:

接收 描述
$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.5",
              "createOptions": "{}"
            }
          },
          "edgeHub": {
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 0,
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-hub:1.5",
              "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}"
            }
          }
        },
        "modules": {
          "SimulatedTemperatureSensor": {
            "version": "1.5",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 2,
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.5",
              "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
        }
      }
    }
  }
}

下一步