チュートリアル:Azure Functions を IoT Edge モジュールとして展開する

適用対象:IoT Edge 1.4 checkmark IoT Edge 1.4

重要

IoT Edge 1.4 がサポートされているリリースです。 以前のリリースの場合は、「IoT Edge を更新する」を参照してください。

Azure Functions を使用して、ビジネス ロジックを実装するコードを Azure IoT Edge デバイスに直接展開できます。 このチュートリアルでは、シミュレートされた IoT Edge デバイス上のセンサー データをフィルター処理する Azure Functions の作成と展開について段階的に説明します。 ここでは、クイックスタートで作成した、シミュレートされた IoT Edge デバイスを使用します。 このチュートリアルでは、以下の内容を学習します。

  • Visual Studio Code を使用して、Azure Functions を作成する。
  • Visual Studio Code と Docker を使用して Docker イメージを作成し、コンテナー レジストリに発行します。
  • コンテナー レジストリから IoT Edge デバイスにモジュールを配置する。
  • フィルター処理されたデータを表示する。

Diagram of function architecture, showing how to stage and deploy a function module.

このチュートリアルでは、デバイスによって生成される温度データをフィルター処理する Azure Functions を作成します。 この関数では、指定されたしきい値を温度が上回っているときにのみ、上流の Azure IoT Hub にメッセージを送信します。

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

前提条件

このチュートリアルを開始する前に、チュートリアル「Visual Studio Code を使用して Azure IoT Edge モジュールを開発する」を行って Linux コンテナー開発用の開発環境を設定します。 そのチュートリアルを完了すると、以下の前提条件が満たされます。

Azure Functions を使用して IoT Edge モジュールを開発するには、開発用マシンに追加の前提条件をインストールします。

関数プロジェクトを作成する

前提条件としてインストールした Visual Studio Code 用 Azure IoT Edge は、いくつかのコード テンプレートと管理機能を提供します。 このセクションでは、Visual Studio Code を使用して、Azure Functions を含む IoT Edge ソリューションを作成します。

新しいプロジェクトを作成する

カスタマイズ可能な C# 関数ソリューション テンプレートを作成するには、次の手順に従います。

  1. 開発用マシンで Visual Studio Code を開きます。

  2. [表示]>[コマンド パレット] を選択して Visual Studio Code コマンド パレットを開きます。

  3. コマンド パレットで、Azure IoT Edge: New IoT Edge solution コマンドを追加して実行します。 コマンド パレットに表示されるこれらのメッセージに従って、ソリューションを作成します。

    • フォルダーの選択: Visual Studio Code によってソリューション ファイルが作成される、開発マシン上の場所を選択します。
    • Provide a solution name (ソリューション名の指定): FunctionSolution のように、ソリューションのわかりやすい名前を追加するか、既定値をそのまま使用します。
    • Select a module template (モジュール テンプレートの選択): [Azure Functions - C#] を選択します。
    • Provide a module name (モジュール名の指定): モジュールに CSharpFunction という名前を付けます。
    • Provide Docker image repository for the module (モジュールの Docker イメージ リポジトリの指定): イメージ リポジトリには、コンテナー レジストリの名前とコンテナー イメージの名前が含まれます。 コンテナー イメージは、前の手順で事前設定されます。 localhost:5000 を、Azure Container Registry のログイン サーバーの値に置き換えます。 ログイン サーバーは、Azure portal のコンテナー レジストリの [概要] ページから取得できます。 文字列は最終的に、<レジストリ名>.azurecr.io/csharpfunction のようになります。

    Screenshot showing where to add your Docker image repository name in Visual Studio Code.

レジストリ資格情報を追加する

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

Visual Studio Code の IoT Edge 拡張機能は、Azure からコンテナー レジストリの資格情報をプルし、それらを環境ファイルに取り込もうとします。 ファイルに既に資格情報が含まれているかどうかを確認します。 含まれていない場合は、次のようにして追加します。

  1. Visual Studio Code エクスプローラーで、.env ファイルを開きます。
  2. ご自身の Azure コンテナー レジストリからコピーしたユーザー名パスワードの値を使用して、フィールドを更新します。 Azure のコンテナー レジストリに再度移動し、[設定]>[アクセス キー] ページで確認できます。
  3. このファイルを保存します。

注意

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

ターゲット アーキテクチャを AMD64 に設定する

IoT Edge での Azure Functions モジュールの実行は、Linux AMD64 ベースのコンテナーでのみサポートされます。 Visual Studio Code の既定のターゲット アーキテクチャは Linux AMD64 ですが、ここで明示的に Linux AMD64 に設定します。

  1. コマンド パレットを開き、「Azure IoT Edge: Set Default Target Platform for Edge Solution (Azure IoT Edge: Edge ソリューションの既定のターゲット プラットフォームの設定)」を検索します。

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

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

CSharpFunction モジュールがメッセージを IoT Hub に転送する前に、エッジでそれらを処理できるように、コードを追加してみましょう。

  1. Visual Studio Code エクスプローラーで、[モジュール]>[CSharpFunction]>[CSharpFunction.cs] の順に開きます。

  2. CSharpFunction.cs ファイルの内容を次のコードに置き換えます。 このコードは、周囲温度とマシン温度に関するテレメトリを受け取り、定義されたしきい値をマシン温度が超えた場合にのみ、IoT Hub にメッセージを転送します。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Azure.Devices.Client;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.EdgeHub;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    
    namespace Functions.Samples
    {
        public static class CSharpFunction
        {
            [FunctionName("CSharpFunction")]
            public static async Task FilterMessageAndSendMessage(
                [EdgeHubTrigger("input1")] Message messageReceived,
                [EdgeHub(OutputName = "output1")] IAsyncCollector<Message> output,
                ILogger logger)
            {
                const int temperatureThreshold = 20;
                byte[] messageBytes = messageReceived.GetBytes();
                var messageString = System.Text.Encoding.UTF8.GetString(messageBytes);
    
                if (!string.IsNullOrEmpty(messageString))
                {
                    logger.LogInformation("Info: Received one non-empty message");
                    // Get the body of the message and deserialize it.
                    var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString);
    
                    if (messageBody != null && messageBody.machine.temperature > temperatureThreshold)
                    {
                        // Send the message to the output as the temperature value is greater than the threshold.
                        using (var filteredMessage = new Message(messageBytes))
                        {
                             // Copy the properties of the original message into the new Message object.
                             foreach (KeyValuePair<string, string> prop in messageReceived.Properties)
                             {filteredMessage.Properties.Add(prop.Key, prop.Value);}
                             // Add a new property to the message to indicate it is an alert.
                             filteredMessage.Properties.Add("MessageType", "Alert");
                             // Send the message.
                             await output.AddAsync(filteredMessage);
                             logger.LogInformation("Info: Received and transferred a message with temperature above the threshold");
                        }
                    }
                }
            }
        }
        //Define the expected schema for the body of incoming messages.
        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;}
        }
    }
    
  3. ファイルを保存します。

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

前のセクションでは、IoT Edge ソリューションを作成し、CSharpFunction を変更しました。これにより、レポートされたマシンの温度が許容可能なしきい値を下回るメッセージがフィルターで除外されます。 次は、ソリューションをコンテナー イメージとしてビルドして、それをコンテナー レジストリにプッシュする必要があります。

  1. [表示]>[ターミナル] の順に選択して、Visual Studio Code 統合ターミナルを開きます。

  2. ターミナルで次のコマンドを入力して、Docker にサインインします。 自分の Azure コンテナー レジストリのユーザー名、パスワード、ログイン サーバーを使用してサインインします。 これらの値は、Azure portal でご自身のレジストリの [アクセス キー] セクションから取得できます。

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

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

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

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

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

コンテナー イメージの表示

コンテナー イメージがコンテナー レジストリにプッシュされると、Visual Studio Code によって成功メッセージが出力されます。 操作の成功を自分で確認したい場合は、レジストリのイメージを表示できます。

  1. Azure portal で、Azure Container Registry に移動します。
  2. [サービス]>[リポジトリ] を選択します。
  3. csharpfunction リポジトリが一覧に表示されます。 このリポジトリを選択すると、さらに詳しい情報が表示されます。
  4. [タグ] セクションには、0.0.1-amd64 タグが表示されます。 このタグには、作成したイメージのバージョンとプラットフォームが示されます。 これらの値は、CSharpFunction フォルダーの module.json ファイルで設定されます。

ソリューションの配置と実行

クイックスタートで行ったように、Azure portal を使用して関数モジュールを IoT Edge デバイスに展開できます。 また、Visual Studio Code 内からモジュールを配置して、監視することもできます。 以降のセクションでは、前提条件で示された Visual Studio Code 用の Azure IoT Edge と IoT Hub の拡張機能が使われます。 この拡張機能をまだインストールしていない場合は、ここでインストールしてください。

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

  2. IoT Edge デバイスの名前を右クリックし、 [Create Deployment for Single Device](単一デバイスのデプロイの作成) を選択します。

  3. CSharpFunction が含まれているソリューション フォルダーの場所を参照します。 config フォルダーを開き、deployment.amd64.json ファイルを選択して、 [Select Edge Deployment Manifest](Edge 展開マニフェストの選択) を選択します。

  4. お使いのデバイスの [モジュール] を展開し、デプロイされて実行中のモジュールの一覧を表示します。 更新ボタンをクリックします。 新しい CSharpFunction が、SimulatedTemperatureSensor モジュール、 $edgeAgent および $edgeHub と一緒に実行されていることがわかります。

    新しいモジュールが表示されるまでに、数分かかる場合があります。 IoT Edge デバイスは、その新しいデプロイ情報を IoT Hub から取得し、新しいコンテナーを起動した後、その状態を IoT Hub にレポートする必要があります。

    Screenshot showing how to view deployed modules in Visual Studio Code.

生成されたデータを表示する

コマンド パレットで Azure IoT Hub: Start Monitoring Built-in Event Endpoint を実行することで、お使いのすべてのでデバイスから IoT ハブに届くすべてのメッセージを確認できます。 メッセージの監視を停止するには、コマンド パレットで Azure IoT Hub: Stop Monitoring Built-in Event Endpoint コマンドを実行します。

また、特定のデバイスから IoT Hub に届くすべてのメッセージが表示されるよう、ビューをフィルター処理することもできます。 Visual Studio Code エクスプローラーの [Azure IoT Hub]>[デバイス] セクションでデバイスを右クリックし、[組み込みイベント エンドポイントの監視を開始します] を選択します。

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

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

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

Azure リソースを削除する

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

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

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

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

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

次のステップ

このチュートリアルでは、IoT Edge デバイスによって生成された生データをフィルター処理するコードが含まれる Azure Functions モジュールを作成しました。

引き続き次のチュートリアルを実行すると、Azure IoT Edge を利用して、エッジでデータをビジネス上の分析情報に変える他の方法について学習できます。