次の方法で共有


チュートリアル: Visual Studio Code を使用して IoT Edge モジュールを開発する

適用対象:IoT Edge 1.5 チェックマーク IoT Edge 1.5

重要

IoT Edge 1.5 LTS は 、サポートされているリリースです。 IoT Edge 1.4 LTS は、2024 年 11 月 12 日をもってサポートが終了しています。 以前のリリースの場合は、「 IoT Edge の更新」を参照してください。

このチュートリアルでは、コードを開発して IoT Edge デバイスにデプロイする方法について説明します。 Azure IoT Edge モジュールを使用すると、ビジネス ロジックを実行するコードを IoT Edge デバイスに直接デプロイできます。 「Linux デバイスへのコードのデプロイ」クイック スタートでは、IoT Edge デバイスを設定し、Azure Marketplace からモジュールをデプロイしました。

この記事では、2 つの IoT Edge 開発ツールの手順について説明します。

この記事の冒頭にあるツール セレクター ボタンを使用して、ツールを選択します。

このチュートリアルでは、以下の内容を学習します。

  • 開発用コンピューターを設定する
  • IoT Edge ツールを使用して新しいプロジェクトを作成する
  • Docker コンテナーとしてプロジェクトをビルドし、Azure コンテナー レジストリに格納する
  • IoT Edge デバイスにコードをデプロイする

このチュートリアルで作成する IoT Edge モジュールは、デバイスが生成する温度データをフィルター処理します。 温度が設定されたしきい値を超えている場合にのみ、アップストリームにメッセージを送信します。 エッジでこのような分析を行うと、クラウドに送信され、クラウドに格納されるデータの量を減らすことができます。

前提条件

開発マシン:

  • 自分のパソコンまたは仮想マシンを使用できます。
  • コンテナー エンジンを実行するための 入れ子になった仮想化が 開発マシンでサポートされていることを確認します。
  • コンテナー エンジンを実行するほとんどのオペレーティング システムを使用して、Linux デバイス用の IoT Edge モジュールを開発できます。 このチュートリアルでは Windows コンピューターを使用しますが、macOS または Linux での既知の違いについて説明します。
  • Visual Studio Code をインストールする
  • Azure CLI をインストールします。

Azure IoT Edge デバイス:

クラウド リソース:

  • 無料または Standard レベルの Azure IoT Hub を使用します。

Azure アカウントをお持ちでない場合は、開始する前に無料アカウントを作成してください。

ヒント

Visual Studio Code または Visual Studio 2022 での対話型デバッグに関するガイダンスについて。

このチュートリアルでは、Visual Studio Code の開発手順について説明します。

主要な概念

このチュートリアルでは、IoT Edge モジュールの開発について説明します。 "IoT Edge モジュール" は、実行可能コードのコンテナーです。 1 つ以上のモジュールを IoT Edge デバイスにデプロイします。 モジュールは、センサーからのデータの取り込み、データのクリーニングと分析、IoT Hub へのメッセージの送信などの特定のタスクを実行します。 詳細については、「 Azure IoT Edge モジュールについて」を参照してください。

IoT Edge モジュールを開発するときは、開発マシンと、モジュールがデプロイされるターゲット IoT Edge デバイスの違いを理解します。 モジュール コードを保持するためにビルドするコンテナーは、 ターゲット デバイスのオペレーティング システム (OS) と一致している必要があります。 たとえば、最も一般的なシナリオは、IoT Edge を実行している Linux デバイスを対象とするモジュールを Windows コンピューターで開発することです。 その場合、コンテナー オペレーティング システムは Linux です。 このチュートリアルを実行するときは、 開発用マシン OSコンテナー OS の違いに注意してください。

ヒント

Windows で Linux 用 IoT Edge を使用している場合、シナリオのターゲット デバイスは、Windows ホストではなく Linux 仮想マシンです。

このチュートリアルでは、Linux コンテナーを使用して IoT Edge を実行しているデバイスをターゲットとしています。 開発マシンが Linux コンテナーを実行している限り、任意のオペレーティング システムを使用します。 Linux コンテナーを使用した開発には Visual Studio Code をお勧めします。そのため、このチュートリアルではそれを使用します。 Visual Studio も使用できますが、この 2 つのツールの間にはサポートに違いがあります。

次の表に、Visual Studio Code と Visual Studio の Linux コンテナー でサポートされている開発シナリオを示します。

Visual Studio Code Visual Studio 2019/2022
Linux デバイス アーキテクチャ Linux AMD64
Linux ARM32v7
Linux ARM64
Linux AMD64
Linux ARM32
Linux ARM64
Azure サービス Azure Functions
Azure Stream Analytics
Azure Machine Learning
言語 C
C#
ジャワ
Node.js
Python(プログラミング言語)
C
C#
詳細情報 Azure IoT Edge for Visual Studio Code Visual Studio 2019 用の Azure IoT Edge ツール
Azure IoT Edge Tools for Visual Studio 2022

コンテナー エンジンをインストールする

IoT Edge モジュールはコンテナーとしてパッケージ化されているため、開発マシン上に Docker と互換性のあるコンテナー管理システム を構築して管理する必要があります。 Docker Desktop は強力な機能サポートを備えるため、開発に人気のある選択肢です。 Windows 上の Docker Desktop を使用すると、Linux コンテナーと Windows コンテナーを切り替えることができるため、さまざまな種類の IoT Edge デバイス用のモジュールを開発できます。

Docker のドキュメントを使用して、開発用コンピューターに Docker をインストールします。

ツールを設定する

Python ベースの Azure IoT Edge Dev Tool をインストールして、IoT Edge ソリューションを作成します。 次の 2 つのオプションがあります。

重要

Visual Studio Code 拡張機能用の Azure IoT Edge ツールメンテナンス モードです。 推奨される開発ツールは、コマンド ライン (CLI) の "Azure IoT Edge 開発ツール" です。

Visual Studio Code の IoT 拡張機能を使用して、IoT Edge モジュールを開発します。 これらの拡張機能は、プロジェクト テンプレートを提供し、配置マニフェストの作成を自動化し、IoT Edge デバイスを監視および管理できるようにします。 このセクションでは、Visual Studio Code と IoT 拡張機能をインストールし、次に Visual Studio Code 内から IoT Hub のリソースを管理する Azure アカウントを設定します。

  1. Azure IoT Edge 拡張機能をインストールします。

  2. Azure IoT Hub 拡張機能をインストールします。

  3. 拡張機能をインストールしたら、表示を選択して>を開きます。

  4. コマンド パレットで、 Azure IoT Hub: [IoT Hub の選択] を検索して選択します。 プロンプトに従って、Azure サブスクリプションと IoT Hub を選択します。

  5. アクティビティ バーでアイコンを選択するか、 ビュー>Explorer を選択して、Visual Studio Code のエクスプローラー セクションを開きます。

  6. エクスプローラー セクションの下部で、折りたたまれている Azure IoT Hub /[デバイス] メニューを 展開します。 コマンド パレットで選択した IoT Hub に関連付けられているデバイスと IoT Edge デバイスが表示されます。

言語固有のツールをインストールする

開発に使用する言語に固有のツールをインストールします:

コンテナー レジストリの作成

このチュートリアルでは、 Azure IoT EdgeAzure IoT Hub 拡張機能を使用してモジュールをビルドし、ファイルから コンテナー イメージ を作成します。 その後、イメージを格納および管理する レジストリ にこのイメージをプッシュします。 最後に、レジストリからイメージを展開し、IoT Edge デバイスで実行します。

重要

Azure IoT Edge Visual Studio Code 拡張機能は メンテナンス モードです。

コンテナー イメージは、Docker と互換性のある任意のレジストリを使用して格納できます。 一般的な 2 つの Docker レジストリ サービスは 、Azure Container RegistryDocker Hub です。 このチュートリアルでは、Azure Container Registry を使用します。

コンテナー レジストリがまだない場合は、次の手順に従って、Azure に新しいコンテナー レジストリを作成します。

  1. Azure portal で、リソースの作成>Containers>Container Registry を選択します。

  2. コンテナー レジストリを作成するために、以下の必須値を指定します。

    フィールド
    サブスクリプション ドロップダウン リストで、サブスクリプションを選択します。
    リソースグループ IoT Edge のクイックスタートおよびチュートリアルで作成したすべてのテスト リソースに対して同じリソース グループを使用します。 たとえば、 IoTEdgeResources です
    レジストリ名 一意の名前を指定します。
    ロケーション 近くの場所を選択します。
    SKU(在庫管理単位) [ 基本] を選択します。
  3. [ 確認と作成]、[ 作成] の順に選択します。

  4. Azure portal のホーム ページの [リソース ] セクションから新しいコンテナー レジストリを選択して開きます。

  5. コンテナー レジストリの左側のウィンドウで、[設定] の下にあるメニューから [アクセス キー] を選択します。

    [アクセス キー] メニューの場所のスクリーンショット。

  6. トグル ボタンを使用して 管理者ユーザー を有効にし、コンテナー レジストリの ユーザー名パスワード を表示します。

  7. ログイン サーバーユーザー名パスワードの値をコピーし、便利な場所に保存します。 このチュートリアルではこれらの値を使用して、コンテナー レジストリへのアクセスを提供します。

新しいモジュール プロジェクトを作成する

この Azure IoT Edge 拡張機能には、Visual Studio Code でサポートされているすべての IoT Edge モジュール言語のプロジェクト テンプレートが用意されています。 これらのテンプレートには、IoT Edge をテストするために作業モジュールをデプロイするために必要なすべてのファイルとコードが含まれています。また、独自のビジネス ロジックを使用してテンプレートをカスタマイズするための出発点を提供します。

プロジェクト テンプレートを作成する

IoT Edge Dev Tool は、環境変数によって駆動されるコマンドを使用して Azure IoT Edge 開発を簡略化します。 これは、既定のモジュールと必要なすべての構成ファイルを含む IoT Edge 開発コンテナーと IoT Edge ソリューションスキャフォールディングを使用して IoT Edge 開発を開始するのに役立ちます。

  1. 目的のパスにソリューションのディレクトリを作成します。 iotedgesolution ディレクトリに移動します。

    mkdir c:\dev\iotedgesolution
    cd c:\dev\iotedgesolution
    
  2. iotedgedev solution init コマンドを使用してソリューションを作成し、任意の開発言語で Azure IoT Hub を設定します。

    iotedgedev solution init --template csharp
    

iotedgedev ソリューション init スクリプトでは、次のようないくつかの手順を完了するように求められます。

  • Azure に対して認証します
  • Azure サブスクリプションを選択する
  • リソース グループを選択または作成する
  • Azure IoT Hub を選択または作成する
  • Azure IoT Edge デバイスを選択または作成する

Visual Studio Code と Azure IoT Edge 拡張機能を使用します。 まず、ソリューションを作成し、そのソリューションで最初のモジュールを生成します。 各ソリューションには、複数のモジュールを含めることができます。

  1. [ 表示>コマンド パレット] を選択します。
  2. コマンド パレットで、「 Azure IoT Edge: New IoT Edge Solution」コマンドを入力して実行します。
  3. 新しいソリューションを作成するフォルダーを参照し、[フォルダーの選択] を 選択します
  4. ソリューションの名前を入力します。
  5. ソリューション内の最初のモジュールになるように、好きな開発言語用のモジュール テンプレートを選択します。
  6. モジュールの名前を入力します。 コンテナー レジストリ内に一意の名前を選択します。
  7. モジュールのイメージ リポジトリの名前を入力します。 Visual Studio Code では、モジュール名に localhost:5000/< モジュール名>が自動的に入力されます。 独自のレジストリ情報に置き換えます。 テストにローカル Docker レジストリを使用する場合は、 localhost を使用します。 Azure Container Registry を使用する場合は、レジストリの設定から ログイン サーバー を使用します。 サインイン サーバーは、<registry name>.azurecr.io のようになります。 localhost:5000部分のみを置き換えて、最終結果が<registry name>.azurecr.io/<あなたのモジュール名>のように見えるようにします。

Visual Studio Code は、指定された情報を取得し、IoT Edge ソリューションを作成して、それを新しいウィンドウに読み込みます。

ソリューションを作成すると、次のメイン ファイルがソリューションに含まれます。

  • .vscode フォルダーには、構成ファイルlaunch.jsonが含まれています

  • modules フォルダーには、各モジュールのサブフォルダーがあります。 各サブフォルダーでは、module.json ファイルによってモジュールのビルドとデプロイ方法が制御されます。

  • .env ファイルには、環境変数が一覧表示されます。 コンテナー レジストリの環境変数は、既定では localhost:5000 です。

  • deployment.template.jsondeployment.debug.template.jsonの 2 つのモジュール展開ファイルに、デバイスにデプロイするモジュールが一覧表示されます。 既定では、一覧には IoT Edge システム モジュール (edgeAgent と edgeHub) と次のようなサンプル モジュールが含まれます。

    注意

    インストールされる正確なモジュールは、選択した言語によって異なります。

IoT Edge ランタイム バージョンを設定する

最新の安定した IoT Edge システム モジュールのバージョンは 1.5 です。 システム モジュールをバージョン 1.5 に設定します。

  1. Visual Studio Code で、配置マニフェスト ファイル deployment.template.json 開きます。 配置マニフェストは、ターゲット IoT Edge デバイスで構成するモジュールについて説明する JSON ドキュメントです。

  2. システム ランタイム モジュール イメージ edgeAgentedgeHub のランタイム バージョンを変更します。 たとえば、IoT Edge ランタイム バージョン 1.5 を使用する場合は、配置マニフェスト ファイルで次の行を変更します。

    "systemModules": {
        "edgeAgent": {
    
            "image": "mcr.microsoft.com/azureiotedge-agent:1.5",
    
        "edgeHub": {
    
            "image": "mcr.microsoft.com/azureiotedge-hub:1.5",
    

レジストリの資格情報を IoT Edge エージェントに提供する

コンテナー レジストリの資格情報は、環境ファイルに格納され、IoT Edge ランタイムと共有されます。 コンテナー イメージを IoT Edge デバイスにプルするには、ランタイムにこれらの資格情報が必要です。

IoT Edge 拡張機能は、Azure からコンテナー レジストリの資格情報をプルし、それらを環境ファイルに取り込もうとします。

注意

環境ファイルは、モジュールのイメージ リポジトリを指定した場合にのみ作成されます。 localhost の既定値を受け入れてローカルでテストおよびデバッグする場合は、環境変数を宣言する必要はありません。

資格情報が存在するかどうかを確認します。 含まれていない場合は、次のようにして追加します。

  1. レジストリが Azure Container Registry の場合、Azure Container Registry のユーザー名とパスワードを設定します。 これらの値は、Azure portal のコンテナー レジストリの >] メニューから取得します。

  2. モジュール ソリューションで .env ファイルを開きます。

  3. Azure コンテナー レジストリからコピーした ユーザー名パスワード の値を追加します。 次に例を示します。

    CONTAINER_REGISTRY_SERVER="myacr.azurecr.io"
    CONTAINER_REGISTRY_USERNAME="myacr"
    CONTAINER_REGISTRY_PASSWORD="<registry_password>"
    
  4. 変更を .env ファイルに保存します。

注意

このチュートリアルでは、開発とテストのシナリオに便利な Azure Container Registry の管理者資格情報を使用します。 運用環境のシナリオに向けて準備ができたら、サービス プリンシパルやリポジトリスコープ トークンのような最小特権の認証オプションを使用することをお勧めします。 詳細については、「 コンテナー レジストリへのアクセスの管理」を参照してください

ターゲット アーキテクチャ

コンテナーのビルドと実行方法に影響するため、各ソリューションを対象とするアーキテクチャを選択します。 既定値は Linux AMD64 です。 このチュートリアルでは、IoT Edge デバイスとして Ubuntu 仮想マシンを使用し、既定の amd64 をそのまま使用します。

ソリューションのターゲット アーキテクチャを変更する必要がある場合は、次の手順に従います。

  1. コマンド パレットを開き、「 Azure IoT Edge: Edge ソリューションの既定のターゲット プラットフォームを設定する」を検索するか、ウィンドウの下部にあるサイド バーにあるショートカット アイコンを選択します。

  2. コマンド パレットで、オプションの一覧からターゲット アーキテクチャを選択します。

ターゲット アーキテクチャは、後の手順でコンテナー イメージを作成するときに設定されます。

カスタム コードでモジュールを更新する

各テンプレートには、 SimulatedTemperatureSensor モジュールからシミュレートされたセンサー データを取得し、それを IoT Hub にルーティングするサンプル コードが含まれています。 サンプル モジュールは、メッセージを受信して渡します。 パイプライン機能は、IoT Edge における重要な概念である、モジュールが相互に通信する方法を示しています。

各モジュールは、コード内で複数の 入力 キューと 出力 キューを宣言できます。 デバイスで実行されている IoT Edge ハブは、1 つのモジュールの出力から 1 つ以上のモジュールの入力にメッセージをルーティングします。 入力と出力を宣言するための特定のコードは言語によって異なりますが、概念はすべてのモジュールで同じです。 モジュール間のルーティングの詳細については、「ルートの 宣言」を参照してください。

プロジェクト テンプレートに付属するサンプル C# コードでは、IoT Hub SDK for .NET の ModuleClient クラス を使用します。

  1. Visual Studio Code エクスプローラーで、 モジュール>filtermodule>ModuleBackgroundService.csを開きます。

  2. filtermodule 名前空間の前に、後で使用する型に対して 3 つの using ステートメントを追加します。

    using System.Collections.Generic;     // For KeyValuePair<>
    using Microsoft.Azure.Devices.Shared; // For TwinCollection
    using Newtonsoft.Json;                // For JsonConvert
    
  3. temperatureThreshold 変数を ModuleBackgroundService クラスに追加します。 この変数は、IoT Hub にデータを送信するために測定温度が超える必要がある値を設定します。

    static int temperatureThreshold { get; set; } = 25;
    
  4. MessageBodyMachineAmbient クラスを追加します。 これらのクラスは、受信メッセージの本文に対して予期されるスキーマを定義します。

    class MessageBody
    {
        public Machine machine {get;set;}
        public Ambient ambient {get; set;}
        public string timeCreated {get; set;}
    }
    class Machine
    {
        public double temperature {get; set;}
        public double pressure {get; set;}
    }
    class Ambient
    {
        public double temperature {get; set;}
        public int humidity {get; set;}
    }
    
  5. ExecuteAsync 関数を見つけます。 この関数は、モジュールがローカルの Azure IoT Edge ランタイムに接続してメッセージを送受信できるようにする ModuleClient オブジェクトを作成して構成します。 ModuleClient を作成した後、コードはモジュール ツインの必要なプロパティから temperatureThreshold 値を読み取ります。 このコードは、 input1 というエンドポイントを介して IoT Edge ハブからメッセージを受信するコールバックを登録します。

    ProcessMessageAsync メソッドの呼び出しを、エンドポイントの名前と入力が到着したときに呼び出されるメソッドを更新する新しいメソッドに置き換えます。 また、必要なプロパティを更新するための SetDesiredPropertyUpdateCallbackAsync メソッドを追加します。 この変更を行うには、ExecuteAsync メソッドの最後の行を次のコードに置き換えます

    // Register a callback for messages that are received by the module.
    // await _moduleClient.SetInputMessageHandlerAsync("input1", PipeMessage, cancellationToken);
    
    // Read the TemperatureThreshold value from the module twin's desired properties
    var moduleTwin = await _moduleClient.GetTwinAsync();
    await OnDesiredPropertiesUpdate(moduleTwin.Properties.Desired, _moduleClient);
    
    // Attach a callback for updates to the module twin's desired properties.
    await _moduleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdate, null);
    
    // Register a callback for messages that are received by the module. Messages received on the inputFromSensor endpoint are sent to the FilterMessages method.
    await _moduleClient.SetInputMessageHandlerAsync("inputFromSensor", FilterMessages, _moduleClient);
    
  6. OnDesiredPropertiesUpdate メソッドを ModuleBackgroundService クラスに追加します。 このメソッドは、モジュール ツインから必要なプロパティの更新を受け取り、 temperatureThreshold 変数を一致するように更新します。 すべてのモジュールに独自のモジュール ツインがあり、これにより、モジュール内で実行されているコードをクラウドから直接構成できます。

    static Task OnDesiredPropertiesUpdate(TwinCollection desiredProperties, object userContext)
    {
        try
        {
            Console.WriteLine("Desired property change:");
            Console.WriteLine(JsonConvert.SerializeObject(desiredProperties));
    
            if (desiredProperties["TemperatureThreshold"]!=null)
                temperatureThreshold = desiredProperties["TemperatureThreshold"];
    
        }
        catch (AggregateException ex)
        {
            foreach (Exception exception in ex.InnerExceptions)
            {
                Console.WriteLine();
                Console.WriteLine("Error when receiving desired property: {0}", exception);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine("Error when receiving desired property: {0}", ex.Message);
        }
        return Task.CompletedTask;
    }
    
  7. FilterMessages メソッドを追加します。 このメソッドは、モジュールが IoT Edge ハブからメッセージを受け取るたびに呼び出されます。 これにより、モジュール ツインで設定されているしきい値を下回る温度を報告するメッセージは除外されます。 また、値が Alert に設定された MessageType プロパティをメッセージに追加 します

    async Task<MessageResponse> FilterMessages(Message message, object userContext)
    {
        var counterValue = Interlocked.Increment(ref _counter);
        try
        {
            ModuleClient moduleClient = (ModuleClient)userContext;
            var messageBytes = message.GetBytes();
            var messageString = Encoding.UTF8.GetString(messageBytes);
            Console.WriteLine($"Received message {counterValue}: [{messageString}]");
    
            // Get the message body.
            var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString);
    
            if (messageBody != null && messageBody.machine.temperature > temperatureThreshold)
            {
                Console.WriteLine($"Machine temperature {messageBody.machine.temperature} " +
                    $"exceeds threshold {temperatureThreshold}");
                using (var filteredMessage = new Message(messageBytes))
                {
                    foreach (KeyValuePair<string, string> prop in message.Properties)
                    {
                        filteredMessage.Properties.Add(prop.Key, prop.Value);
                    }
    
                    filteredMessage.Properties.Add("MessageType", "Alert");
                    await moduleClient.SendEventAsync("output1", filteredMessage);
                }
            }
    
            // Indicate that the message treatment is completed.
            return MessageResponse.Completed;
        }
        catch (AggregateException ex)
        {
            foreach (Exception exception in ex.InnerExceptions)
            {
                Console.WriteLine();
                Console.WriteLine("Error in sample: {0}", exception);
            }
            // Indicate that the message treatment is not completed.
            var moduleClient = (ModuleClient)userContext;
            return MessageResponse.Abandoned;
        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine("Error in sample: {0}", ex.Message);
            // Indicate that the message treatment is not completed.
            ModuleClient moduleClient = (ModuleClient)userContext;
            return MessageResponse.Abandoned;
        }
    }
    
  8. ModuleBackgroundService.cs ファイルを保存します。

  9. Visual Studio Code エクスプローラーで、IoT Edge ソリューション ワークスペースの deployment.template.json ファイルを開きます。

  10. モジュールがリッスンするエンドポイントの名前を変更したので、配置マニフェスト内のルートも、"edgeHub" が新しいエンドポイントにメッセージを送信するように更新する必要があります。

    $edgeHub モジュール ツインでルート セクションを見つけます。 sensorTofiltermodule ルートを更新して、input1inputFromSensorに置き換えます。

    "sensorTofiltermodule": "FROM /messages/modules/tempSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/inputFromSensor\")"
    
  11. 配置マニフェストに filtermodule モジュール ツインを追加します。 modulesContent セクションの下部に、$edgeHub モジュール ツインの後に次の JSON コンテンツを挿入します。

       "filtermodule": {
           "properties.desired":{
               "TemperatureThreshold":25
           }
       }
    
  12. deployment.template.json ファイルを保存します。

ソリューションをビルドしてプッシュする

いくつかの主要なデプロイ概念を理解できるように、モジュール コードと展開テンプレートを更新しました。 次に、モジュール コンテナー イメージをビルドして、コンテナー レジストリにプッシュします。

Visual Studio Code で、 deployment.template.json 配置マニフェスト ファイルを開きます。 配置マニフェストでは、対象の IoT Edge デバイスで構成するモジュールについて説明します。 デプロイの前に、Azure Container Registry 資格情報とモジュール イメージを適切な createOptions の値で更新する必要があります。 createOption 値の詳細については、「 IoT Edge モジュールのコンテナー作成オプションを構成する方法」を参照してください。

Azure Container Registry を使用してモジュール イメージを格納する場合は、deployment.template.jsonの modulesContent>edgeAgent>settings>registryCredentials セクションに資格情報 を追加します。 myacr を独自のレジストリ名に置き換え、パスワードとログイン サーバー アドレスを指定します。 次に例を示します。

"registryCredentials": {
    "myacr": {
        "username": "myacr",
        "password": "<your_acr_password>",
        "address": "myacr.azurecr.io"
    }
}

一覧表示されているシステム (edgeHub と edgeAgent) とカスタム モジュール (filtermodule と tempSensor) ごとに、次の文字列化されたコンテンツを "createOptions" の値に追加するか置き換えます。 必要に応じて、値を変更します。

"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"

たとえば、 filtermodule の構成は次のようになります。

"filtermodule": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
   "image": "myacr.azurecr.io/filtermodule:0.0.1-amd64",
   "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
}

モジュールの Docker イメージをビルドする

ターミナル>新しいターミナルを選択して、Visual Studio Code 統合ターミナルを開きます。

dotnet publish コマンドを使って、Linux および amd64 アーキテクチャ用のコンテナー イメージをビルドします。 プロジェクトの filtermodule ディレクトリにディレクトリを変更し、 dotnet publish コマンドを実行します。

dotnet publish --os linux --arch x64 /t:PublishContainer

現在、 iotedgedev ツール テンプレートは .NET 7.0 を対象としています。 別のバージョンの .NET をターゲットにする場合は、 filtermodule.csproj ファイルを編集し、 TargetFrameworkPackageReference の値を変更できます。 たとえば、.NET 8.0 をターゲットにするには、 filtermodule.csproj ファイルは次のようになります。

<Project Sdk="Microsoft.NET.Sdk.Worker">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.Azure.Devices.Client" Version="1.42.0" />
        <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
    </ItemGroup>
</Project>

コンテナー レジストリ情報、バージョン、アーキテクチャで Docker イメージにタグを付けます。 myacr を独自のレジストリ名に置き換えます。

docker tag filtermodule myacr.azurecr.io/filtermodule:0.0.1-amd64

モジュールの Docker イメージをプッシュする

コンテナー イメージをレジストリ内のストレージにプッシュできるように、Docker にコンテナー レジステリの資格情報を提供します。

  1. Azure Container Registry (ACR) 資格情報を使って Docker にサインインします。

    docker login -u <ACR username> -p <ACR password> <ACR login server>
    

    --password-stdin の使用を推奨するセキュリティ警告が表示される場合があります。 これは運用環境のシナリオでの推奨されているベスト プラクティスですが、このチュートリアルの範囲外になります。 詳細については、 Docker ログイン リファレンスを参照してください。

  2. Azure Container Registry にサインインします。 コマンドを使用するには、azする必要があります。 このコマンドは 、設定>Access キーのコンテナー レジストリで見つかったユーザー名とパスワードを要求します。

    az acr login -n <ACR registry name>
    

    ヒント

    このチュートリアルの任意の時点でログアウトした場合、Docker および Azure Container Registry のサインイン ステップを繰り返して続行します。

  3. モジュール イメージをローカル レジストリまたはコンテナー レジストリにプッシュします。

    docker push <ImageName>
    

    次に例を示します。

    # Push the Docker image to the local registry
    
    docker push localhost:5000/filtermodule:0.0.1-amd64
    
    # Or push the Docker image to an Azure Container Registry. Replace myacr with your Azure Container Registry name.
    
    az acr login --name myacr
    docker push myacr.azurecr.io/filtermodule:0.0.1-amd64
    

デプロイ テンプレートを更新する

デプロイ テンプレート "deployment.template.json" をコンテナー レジストリ イメージの場所で更新します。 たとえば、Azure Container Registry "myacr.azurecr.io" を使用していて、イメージが "filtermodule:0.0.1-amd64" の場合は、"filtermodule" 構成を次のように更新します。

"filtermodule": {
    "version": "1.0",
    "type": "docker",
    "status": "running",
    "restartPolicy": "always",
    "settings": {
        "image": "myacr.azurecr.io/filtermodule:0.0.1-amd64",
        "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
    }
}

Visual Studio Code エクスプローラーで、 deployment.template.json ファイルを右クリックし、[ IoT Edge ソリューションのビルドとプッシュ] を選択します。

ビルドおよびプッシュ コマンドでは、3 つの操作を開始します。 最初に、ソリューションに config という名前の新しいフォルダーを作成します。このフォルダーには、配置テンプレートやその他のソリューション ファイルの情報から構築された完全な配置マニフェストが保持されます。 次に、docker build を実行して、お使いのターゲット アーキテクチャ用の適切な Dockerfile に基づいてコンテナー イメージをビルドします。 そして、docker push を実行して、イメージ リポジトリをコンテナー レジストリにプッシュします。

このプロセスは、初回は数分間かかる可能性がありますが、次回これらのコマンドを実行するときは、それより速くなります。

省略可能: モジュールとイメージを更新する

モジュール コードを変更する場合は、モジュール イメージをリビルドしてコンテナー レジストリにプッシュする必要があります。 このセクションの手順を使って、ビルドとコンテナー イメージを更新します。 モジュール コードを変更しなかった場合は、このセクションをスキップできます。

新しく作成した config フォルダーで deployment.amd64.json ファイルを開きます。 このファイル名はターゲット アーキテクチャを反映しているため、別のアーキテクチャを選択した場合は別の名前になります。

プレースホルダーがある 2 つのパラメーターに、適切な値が入れられていることに注意してください。 registryCredentials セクションには、レジストリユーザー名とパスワードが .env ファイルからプルされています。 filtermodule には、module.json ファイルの名前、バージョン、およびアーキテクチャ タグを含む完全なイメージ リポジトリがあります。

  1. filtermodule フォルダー内の module.json ファイルを開きます。

  2. モジュール イメージのバージョン番号を変更します。 たとえば、モジュール コードで軽微な修正を行ったかのように、パッチのバージョン番号を "version": "0.0.2" に増分します。

    ヒント

    モジュール バージョンではバージョン管理が有効であり、実稼働環境に更新プログラムをデプロイする前に、少数のデバイスで変更をテストすることができます。 ビルドとプッシュの前にモジュール バージョンを増分しないと、コンテナー レジストリ内のリポジトリが上書きされます。

  3. 変更をmodule.json ファイルに保存します。

0.0.2 バージョン タグを使用して、更新されたイメージをビルドしてプッシュします。 たとえば、ローカル レジストリまたは Azure コンテナー レジストリのイメージをビルドしてプッシュするには、次のコマンドを使用します:


# Build the container image for Linux and amd64 architecture.

dotnet publish --os linux --arch x64

# For local registry:
# Tag the image with version 0.0.2, x64 architecture, and the local registry.

docker tag filtermodule localhost:5000/filtermodule:0.0.2-amd64

# For Azure Container Registry:
# Tag the image with version 0.0.2, x64 architecture, and your container registry information. Replace **myacr** with your own registry name.

docker tag filtermodule myacr.azurecr.io/filtermodule:0.0.2-amd64

deployment.template.json ファイルをもう一度右クリックし、もう一度 [IoT Edge ソリューションのビルドとプッシュ] を選択します。

deployment.amd64.json ファイルをもう一度開きます。 ビルド コマンドとプッシュ コマンドをもう一度実行しても、ビルド システムで新しいファイルが作成されないことに注意してください。 代わりに、同じファイルが変更を反映するように更新されます。 "filtermodule" イメージは現在、コンテナーの 0.0.2 バージョンを指しています。

ビルドおよびプッシュ コマンドの実行内容をさらに確認するには、 Azure portal に移動し、コンテナー レジストリに移動します。

コンテナー レジストリで、[ リポジトリ ] を選択し、 フィルターモジュールを選択します。 イメージの両方のバージョンがレジストリにプッシュされることを確認します。

コンテナー レジストリの両方のイメージ バージョンを表示する場所のスクリーンショット。

トラブルシューティング

モジュール イメージをビルドおよびプッシュしているときにエラーが発生する場合は、開発マシン上の Docker 構成に関連していることがよくあります。 次のチェックを使用して構成を確認してください。

  • コンテナー レジストリからコピーした資格情報を使用して docker login コマンドを実行したか。 これらの資格情報は、Azure にサインインする際に使用するものとは異なります。
  • コンテナー リポジトリは正しいか。 正しいコンテナー レジストリ名と正しいモジュール名が含まれているか。 確認するには、filtermodule フォルダー内の module.json ファイルを開きます。 リポジトリの値は、<registry name>.azurecr.io/filtermodule のようになります。
  • モジュールに filtermodule とは異なる名前を使用した場合、その名前はソリューション全体で一貫していますか?
  • 対象のマシンは、ビルドしているのと同じ種類のコンテナーを実行しているか。 このチュートリアルは Linux IoT Edge デバイスを対象としているため、Visual Studio Code ではサイド バーに amd64 または arm32v7 が表示され、Docker Desktop は Linux コンテナーを実行している必要があります。

モジュールをデバイスにデプロイする

ビルドしたコンテナー イメージがコンテナー レジストリに保存されているのを確認したので、次にそれらをデバイスにデプロイします。 お使いの IoT Edge デバイスが稼働していることを確認します。

IoT Edge Azure CLI set-modules コマンドを使用して、モジュールを Azure IoT Hub にデプロイします。 たとえば、"deployment.template.json" ファイルで定義されているモジュールを、IoT Edge デバイス "my-device" の IoT Hub "my-iot-hub" にデプロイするには、次のコマンドを使用します。 ハブ名デバイス IDログイン IoT Hub 接続文字列の値を独自の値に置き換えます。

az iot edge set-modules --hub-name my-iot-hub --device-id my-device --content ./deployment.template.json --login "HostName=my-iot-hub.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=<SharedAccessKey>"

ヒント

Azure portal で、共有アクセス キーを含む IoT Hub 接続文字列を見つけます。 IoT Hub >セキュリティ設定>共有アクセス ポリシー>iothubowner に移動します。

  1. Visual Studio Code エクスプローラーの Azure IoT Hub セクションで、[ デバイス ] を展開して、IoT デバイスの一覧を表示します。

  2. デプロイする IoT Edge デバイスを右クリックし、[ 単一デバイスのデプロイの作成] を選択します。

  3. エクスプローラーで config フォルダーに移動し、 deployment.amd64.json ファイルを選択します。

    deployment.template.json ファイルは使用しないでください。これには、コンテナー レジストリ資格情報もモジュール イメージの値も含まれていません。 Linux ARM32 デバイスをターゲットとする場合、配置マニフェストの名前は deployment.arm32v7.json

  4. デバイスの下で、[ モジュール ] を展開して、デプロイおよび実行中のモジュールの一覧を表示します。 [更新] ボタンを選択します。 新しい "tempSensor" と "filtermodule" モジュールがデバイスで実行されていることがわかります。

    モジュールが起動するまでに数分かかる場合があります。 IoT Edge ランタイムは、新しい配置マニフェストを受け取り、コンテナー ランタイムからモジュール イメージをプルダウンしてから、新しい各モジュールを開始します。

デバイスからのメッセージを表示する

サンプル モジュール コードは、入力キューを介してメッセージを取得し、出力キューを介して送信します。 配置マニフェストは、tempSensor から filtermodule にメッセージを送信し、フィルターモジュールから IoT Hub にメッセージを転送するルートを設定します。 Azure IoT Edge と Azure IoT Hub 拡張機能を使用すると、デバイスから IoT Hub に到着したメッセージを確認できます。

  1. Visual Studio Code エクスプローラーで、監視する IoT Edge デバイスを選択し、[ 組み込みイベント エンドポイントの監視の開始] を選択します。

  2. Visual Studio Code の出力ウィンドウを見て、メッセージが IoT Hub に到着することを確認します。

    デバイスからクラウドへの受信メッセージを示す Visual Studio Code の出力ウィンドウのスクリーンショット。

デバイスでの変更を表示する

デバイスで何が起こっているかを確認するには、このセクションのコマンドを使用して、デバイスで実行されている IoT Edge ランタイムとモジュールを調べます。

これらのコマンドは、開発用コンピューターではなく、IoT Edge デバイス用です。 IoT Edge デバイスに仮想マシンを使用している場合は、すぐに接続してください。 Azure で、仮想マシンの概要ページに移動し、[ 接続 ] を選択してセキュリティで保護されたシェル接続にアクセスします。

  • お使いのデバイスにデプロイされているすべてのモジュールを表示し、それらの状態をチェックします。

    iotedge list
    

    4 つのモジュール (2 つの IoT Edge ランタイム モジュール、 tempSensorfiltermodule) が表示されます。 4つすべてが「実行中」としてリストされます。

  • 次のように、特定のモジュールのログを検査します。

    iotedge logs <module name>
    

    モジュール名の大文字と小文字は区別されます。

    tempSensor ログと filtermodule ログには、処理しているメッセージが表示されます。 edgeAgent モジュールは他のモジュールを起動するため、そのログには配置マニフェストに関する情報が含まれます。 モジュールが一覧に表示されていないか、実行されていない場合は、edgeAgent ログでエラーがないか確認します。 edgeHub モジュールは、モジュールと IoT Hub 間の通信を管理します。 モジュールが実行されていても、メッセージが IoT Hub に到着しない場合は、edgeHub ログでエラーがないか確認します。

リソースをクリーンアップする

次の推奨記事に進む場合は、作成したリソースと構成を保持し、再利用します。 また、同じ IoT Edge デバイスをテスト デバイスとして使用し続けることもできます。

それ以外の場合は、課金されないように、この記事で使用したローカル構成と Azure リソースを削除します。

Azure リソースを削除する

Azure のリソースとリソース グループは、削除すると元に戻すことができません。 間違ったリソース グループやリソースをうっかり削除しないようにしてください。 保持するリソースを含む既存のリソース グループ内に IoT Hub を作成した場合は、リソース グループではなく、IoT Hub リソース自体のみを削除します。

リソースを削除するには、次の手順に従います。

  1. Azure portal にサインインし、[リソース グループ] を選択します。

  2. IoT Edge のテスト リソースを含んだリソース グループの名前を選択します。

  3. リソース グループに含まれているリソースの一覧を確認します。 それらすべてを削除する場合は、[ リソース グループの削除] を選択できます。 一部だけを削除する場合は、削除する各リソースを選択して個別に削除してください。

次のステップ

このチュートリアルでは、開発用コンピューターに Visual Studio Code を設定し、IoT Edge デバイスによって生成された生データをフィルター処理するコードを使用して、最初の IoT Edge モジュールをデプロイします。

次のチュートリアルに進み、Azure IoT Edge を使用して Azure クラウド サービスをデプロイし、エッジでデータを処理および分析する方法について説明します。