共用方式為


了解如何在 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 中樞服務 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 版同時發行,並啟用模組啟動順序。 如果在任何 IoT Edge 部署中執行 1.0.10 以上版本,建議使用結構描述 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 代理程式如何管理模組:

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

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

  • StartupOrder於 IoT Edge 1.0.10 版中引進。第一次部署時,IoT Edge 代理程式應啟動模組所依循的順序。 順序以整數表示,其中啟動值為 0 的模組會先啟動,再依序啟動數值較高的模組。 edgeAgent 模組一律會先啟動,因此沒有啟動值。 選擇性。

    IoT Edge 代理程式會依啟動值的順序啟動模組,但不會等待各個模組啟動完成才接續啟動下一個模組。

    如果有些模組必須依存於其他模組,啟動順序會有所幫助。 例如,您可能想要先啟動 edgeHub 模組,以便在其他模組啟動期間,就能路由傳送訊息。 或者,您可能想先啟動儲存體模組,再啟動傳送資料至該模組的模組。 不過,模組的設計應要能處理其他模組發生錯誤的情形。 就本質而言,容器可以隨時停止及重新啟動,且啟動次數不限。

    注意

    變更模組屬性會導致模組重新啟動, 例如要是您變更下列項目的屬性,模組就會重新啟動:

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

    如果您沒有變更任何模組屬性,模組就不會重新啟動。

宣告路由

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

路由會以下列語法在 $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 版同時發行,並啟用路由優先順序和存留時間。 如果在任何 IoT Edge 部署中執行 1.0.10 以上版本,建議使用結構描述 1.1 版。

每個路由都需要一個傳送訊息的來源,以及接收訊息的接收器條件是您可用來篩選訊息的選用項目。

您可以將優先順序指派給您想確保先處理其訊息的路由。 當上游的連線微弱或效能有限,而且您有重要資料需要比標準的遙測訊息優先處理時,這項功能就相當實用。

來源

來源會指定訊息來自於何處。 IoT Edge 可路由來自模組或下游裝置的訊息。

使用 IoT SDK,模組可使用 ModuleClient 類別來宣告其訊息的特定輸出佇列。 輸出佇列非必要,但對管理多個路由很有幫助。 下游裝置可使用 IoT SDK 的 DeviceClient 類別,以將訊息傳送至 IoT 中樞的相同方式將訊息傳送到 IoT Edge 閘道裝置。 如需詳細資訊,請參閱了解和使用 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 格式,且含 systemPropertiesappPropertiesbody 參數。

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

  • 系統屬性:$<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 中樞所需屬性storeAndForwardConfiguration.timeToLiveSecs 屬性會指定訊息能在 IoT Edge 中樞內儲存多久。

優先順序和存留時間

您可透過只使用字串定義路由的方式宣告路由,也可以將路由宣告為物件,具備路由字串、優先順序整數和存留時間整數。

選項 1:

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

IoT Edge 1.0.10 版導入選項 2,其具備 IoT Edge 中樞結構描述 1.1 版:

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

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

除非明確設定,否則 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
        }
      }
    }
  }
}

下一步