次の方法で共有


チュートリアル: SQL Server データベースを使用してエッジにデータを格納する

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

Important

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

Linux コンテナーを使用して Azure IoT Edge を実行しているデバイスにデータを格納する SQL Server モジュールをデプロイします。

Azure IoT Edge と SQL Server を使用して、エッジにデータを格納してクエリを実行します。 Azure IoT Edge には、デバイスがオフラインになった場合にメッセージをキャッシュし、接続が再確立されたときにメッセージを転送する基本的なストレージ機能があります。 ただし、データをローカルで照会できるなど、より高度なストレージ機能が必要になる場合があります。 IoT Edge デバイスでは、ローカル データベースを使用して、IoT Hub への接続を維持することなく、より複雑なコンピューティングを実行できます。

この記事では、IOT Edge デバイスに SQL Server データベースをデプロイする手順について説明します。 IoT Edge デバイスで実行されている Azure Functions は、受信データを構造化し、データベースに送信します。 この記事の手順は、MySQL や PostgreSQL などのコンテナーで動作する他のデータベースにも適用できます。

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

  • Visual Studio Code を使用して Azure 関数を作成する
  • IoT Edge デバイスに SQL データベースをデプロイする
  • Visual Studio Code を使用してモジュールをビルドし、IoT Edge デバイスにデプロイする
  • 生成されたデータを表示する

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

[前提条件]

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

このチュートリアルでは、Azure Functions モジュールを使用して SQL Server にデータを送信します。 Azure Functions を使用して IoT Edge モジュールを開発するには、開発マシンに次の追加の前提条件をインストールします。

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

データベースにデータを送信するには、データを適切に構造化し、テーブルに格納できるモジュールが必要です。

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

次の手順では、Visual Studio Code と Azure IoT Edge 拡張機能を使用して IoT Edge 関数を作成する方法を示します。

  1. Visual Studio Code を開きます。

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

  3. コマンド パレットで、 Azure IoT Edge: New IoT Edge ソリューションのコマンドを入力して実行します。 コマンド パレットで、ソリューションを作成するための次の情報を指定します。

    フィールド 価値
    フォルダーの選択 Visual Studio Code 用の開発マシン上の場所を選択して、ソリューション ファイルを作成します。
    ソリューション名を指定する ソリューションのわかりやすい名前 ( SqlSolution など) を入力するか、既定値をそのまま使用します。
    モジュール テンプレートの選択 [Azure Functions - C#] を選択します。
    モジュール名を指定する モジュール に sqlFunction という名前を付けます。
    モジュールの Docker イメージ リポジトリを提供する イメージ リポジトリには、コンテナー レジストリの名前とコンテナー イメージの名前が含まれます。 コンテナー イメージは、最後の手順から事前に設定されています。 localhost:5000 を、Azure コンテナー レジストリのログイン サーバーの値に置き換えます。 ログイン サーバーは、Azure portal のコンテナー レジストリの [概要] ページから取得できます。

    最後の文字列は、 <registry name>.azurecr.io/sqlfunction のようになります。

    Visual Studio Code ウィンドウに IoT Edge ソリューション ワークスペースが読み込まれます。

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

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

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

  1. Visual Studio Code エクスプローラーで、.env ファイルを開きます。
  2. Azure コンテナー レジストリからコピーした ユーザー名パスワード の値でフィールドを更新します。
  3. このファイルを保存します。

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

ターゲット アーキテクチャを選択する

コンテナーはアーキテクチャの種類ごとに異なる方法でビルドおよび実行されるため、各ソリューションを対象とするアーキテクチャを選択する必要があります。 既定値は Linux AMD64 です。

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

  2. コマンド パレットで、オプションの一覧からターゲット アーキテクチャを選択します。 このチュートリアルでは、Ubuntu 仮想マシンを IoT Edge デバイスとして使用しているため、既定の amd64 をそのまま使用します。

カスタム コードを使用してモジュールを更新する

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

  2. パッケージ参照のグループを検索し、SqlClient を含める新しい参照を追加します。

    <PackageReference Include="System.Data.SqlClient" Version="4.5.1"/>
    
  3. sqlFunction.csproj ファイルを保存します。

  4. sqlFunction.cs ファイル 開きます。

  5. ファイルの内容全体を次のコードに置き換えます。

    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;
    using Sql = System.Data.SqlClient;
    
    namespace Functions.Samples
    {
        public static class sqlFunction
        {
            [FunctionName("sqlFunction")]
            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);
    
                    //Store the data in SQL db
                    const string str = "<sql connection string>";
                    using (Sql.SqlConnection conn = new Sql.SqlConnection(str))
                    {
                        conn.Open();
                        var insertMachineTemperature = "INSERT INTO MeasurementsDB.dbo.TemperatureMeasurements VALUES (CONVERT(DATETIME2,'" + messageBody.timeCreated + "', 127), 'machine', " + messageBody.machine.temperature + ");";
                        var insertAmbientTemperature = "INSERT INTO MeasurementsDB.dbo.TemperatureMeasurements VALUES (CONVERT(DATETIME2,'" + messageBody.timeCreated + "', 127), 'ambient', " + messageBody.ambient.temperature + ");";
                        using (Sql.SqlCommand cmd = new Sql.SqlCommand(insertMachineTemperature + "\n" + insertAmbientTemperature, conn))
                        {
                            //Execute the command and log the # rows affected.
                            var rows = await cmd.ExecuteNonQueryAsync();
                            logger.LogInformation($"{rows} rows were updated");
                        }
                    }
    
                    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;}
        }
    }
    
  6. 35 行目で、文字列 <sql 接続文字列> 次の文字列に置き換えます。 Data Source プロパティは、まだ存在しない SQL Server コンテナーを参照します。 次のセクションでは、 SQL という名前で作成します。 Password キーワードの強力なパスワードを選択します。

    Data Source=tcp:sql,1433;Initial Catalog=MeasurementsDB;User Id=SA;Password=<YOUR-STRONG-PASSWORD>;TrustServerCertificate=False;Connection Timeout=30;
    
  7. sqlFunction.cs ファイルを保存します。

SQL Server コンテナーを追加する

配置マニフェストは、IoT Edge ランタイムが IoT Edge デバイスにインストールするモジュールを宣言します。 前のセクションでカスタマイズされた関数モジュールを作成するコードを提供しましたが、SQL Server モジュールは既にビルドされており、Microsoft Artifact Registry で使用できます。 IoT Edge ランタイムに組み込むように指示し、デバイスで構成するだけです。

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

  2. コマンド パレットで、 Azure IoT Edge: Add IoT Edge モジュールを入力して実行します。 コマンド パレットで、次の情報を入力して新しいモジュールを追加します。

    フィールド 価値
    デプロイ テンプレート ファイルを選択する コマンド パレットで、現在のソリューション フォルダー内の deployment.template.json ファイルが強調表示されます。 そのファイルを選択します。
    モジュール テンプレートの選択 [既存のモジュール] を選択します ([完全なイメージの URL を入力])。
    モジュール名を指定する 「sql」と入力します。 この名前は、sqlFunction.cs ファイルの接続文字列で宣言されているコンテナー名と一致します。
    モジュールに Docker イメージを提供する 次の URI を入力して、Microsoft Artifact Registry から SQL Server コンテナー イメージをプルします。 Ubuntu ベースのイメージの場合は、 mcr.microsoft.com/mssql/server:latestを使用します。 Red Hat Enterprise Linux (RHEL) ベースのイメージの場合は、 mcr.microsoft.com/mssql/rhel/server:latestを使用します。

    Azure SQL Edge コンテナー イメージは、IoT Edge デバイスで実行できる、コンテナー化された軽量バージョンの SQL Server です。 エッジ シナリオ向けに最適化されており、ARM および AMD64 デバイスで実行できます。

  3. ソリューション フォルダーで、 deployment.template.json ファイルを開きます。

  4. モジュール セクション 見つけます。 3 つのモジュールが表示されます。 SimulatedTemperatureSensor モジュールは、新しいソリューションに既定で含まれており、他のモジュールで使用するテスト データを提供します。 モジュール sqlFunction は、最初に作成し、新しいコードで更新したモジュールです。 最後に、モジュール sql が Microsoft Artifact Registry からインポートされました。

    ヒント

    SQL Server モジュールには、配置マニフェストの環境変数に既定のパスワードが設定されています。 運用環境で SQL Server コンテナーを作成するたびに、 既定のシステム管理者パスワードを変更する必要があります。

  5. deployment.template.json ファイルを閉じます。

IoT Edge ソリューションを構築する

前のセクションでは、1 つのモジュールを含むソリューションを作成し、配置マニフェスト テンプレートに別のモジュールを追加しました。 SQL Server モジュールは Microsoft によってパブリックにホストされていますが、Functions モジュールでコードをコンテナー化する必要があります。 このセクションでは、ソリューションをビルドし、sqlFunction モジュールのコンテナー イメージを作成し、そのイメージをコンテナー レジストリにプッシュします。

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

  2. イメージをレジストリにプッシュできるように、Visual Studio Code でコンテナー レジストリにサインインします。 .env ファイルに追加したのと同じ Azure Container Registry (ACR) 資格情報を使用します。 統合ターミナルで次のコマンドを入力します。

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

    --password-stdin パラメーターの使用を推奨するセキュリティ警告が表示される場合があります。 その使用はこの記事の範囲外ですが、このベスト プラクティスに従うことをお勧めします。 詳細については、 docker login コマンド リファレンスを参照してください。

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

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

    このプロセスは初めて数分かかる場合がありますが、次回コマンドを実行する場合は高速です。

    sqlFunction モジュールがコンテナー レジストリに正常にプッシュされたことを確認できます。 Azure portal で、コンテナー レジストリに移動します。 リポジトリを選択し、sqlFunction を検索します。 他の 2 つのモジュール SimulatedTemperatureSensor と sql は、リポジトリが既に Microsoft レジストリにあるため、コンテナー レジストリにプッシュされません。

ソリューションをデバイスにデプロイする

IoT Hub を介してデバイスにモジュールを設定できますが、Visual Studio Code を使用して IoT Hub とデバイスにアクセスすることもできます。 このセクションでは、IoT Hub へのアクセスを設定し、Visual Studio Code を使用して IoT Edge デバイスにソリューションをデプロイします。

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

  2. デプロイの対象にするデバイスを右クリックし、[ Create Deployment for Single Device]\(単一デバイスのデプロイの作成\) を選択します。

  3. config フォルダー内のdeployment.amd64.json ファイルを選択し、[Edge 配置マニフェストの選択] をクリックします。 deployment.template.json ファイルは使用しないでください。

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

    また、すべてのモジュールがデバイスで稼働していることを確認することもできます。 IoT Edge デバイスで、次のコマンドを実行して、モジュールの状態を確認します。

    iotedge list
    

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

SQL データベースを作成する

配置マニフェストをデバイスに適用すると、3 つのモジュールが実行されます。 SimulatedTemperatureSensor モジュールは、シミュレートされた環境データを生成します。 sqlFunction モジュールは、データを受け取り、データベース用に書式設定します。 このセクションでは、温度データを格納するように SQL データベースを設定する手順について説明します。

IoT Edge デバイスで次のコマンドを実行します。 これらのコマンドは、デバイスで実行されている sql モジュールに接続し、送信される温度データを保持するデータベースとテーブルを作成します。 <YOUR-STRONG-PASSWORD>接続文字列で選択した強力なパスワードに置き換えます。

  1. IoT Edge デバイスのコマンド ライン ツールで、データベースに接続します。

    sudo docker exec -it sql bash
    
  2. SQL コマンド ツールを開きます。

    /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P '<YOUR-STRONG-PASSWORD>'
    
  3. データベースを作成します。

    CREATE DATABASE MeasurementsDB
    ON
    (NAME = MeasurementsDB, FILENAME = '/var/opt/mssql/measurementsdb.mdf')
    GO
    
  4. テーブルを定義します。

    CREATE TABLE MeasurementsDB.dbo.TemperatureMeasurements (measurementTime DATETIME2, location NVARCHAR(50), temperature FLOAT)
    GO
    

SQL Server Docker ファイルをカスタマイズして、複数の IoT Edge デバイスにデプロイされるように SQL Server を自動的に設定できます。 詳細については、 Microsoft SQL Server コンテナーのデモ プロジェクトを参照してください。

ローカル データを表示する

テーブルが作成されると、sqlFunction モジュールは IoT Edge デバイス上のローカル SQL Server 2017 データベースにデータの格納を開始します。

SQL コマンド ツール内から、次のコマンドを実行して、書式設定されたテーブル データを表示します。

SELECT * FROM MeasurementsDB.dbo.TemperatureMeasurements
GO

ローカル データベースの内容を表示する

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

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

それ以外の場合は、課金を回避するために、この記事で作成したローカル構成と Azure リソースを削除できます。

Azure リソースを削除する

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

リソースを削除するには:

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

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

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

このチュートリアルでは、IoT Edge デバイスによって生成された生データをフィルター処理するコードを含む Azure Functions モジュールを作成しました。 独自のモジュールをビルドする準備ができたら、 Visual Studio Code を使用して Azure IoT Edge モジュールを開発する方法の詳細を確認できます。

次のステップ

エッジで別のストレージ方法を試す場合は、IoT Edge で Azure Blob Storage を使用する方法について説明します。