Azure VM に EFLOW（Azure IoT Edge for Linux on Windows） 環境を構築する

## はじめに

EFLOW（Azure IoT **E**dge **f**or **L**inux **o**n **W**indows） が 2021 年 6 月に一般公開（GA）されました。
[Azure IoT Edge for Linux now generally available](https://azure.microsoft.com/ja-jp/updates/azure-iot-edge-for-linux-now-generally-available/)

EFLOW では、Windows マシン上で Linux 仮想マシンを実行します。
これにより、Linux コンテナの Azure IoT Edge モジュールを Windows の IoT デバイスで動作させられるため、IoT デバイスの選択肢が広がります。
今回は Windows マシンとして Azure VM を選択し、EFLOW 環境を構築してみました。

## 想定読者

- Azure IoT Edge を利用し、Windows IoT デバイス上で分析やビジネスロジックを実行したい方
- Hyper-V による仮想化に興味がある方

## Azure VM の準備

今回は Azure 仮想マシンの作成については割愛します。
Azure Portal から Windows 仮想マシンを作成する手順については、下記のリンクを参照ください。
[クイック スタート:Azure Portal で Windows 仮想マシンを作成する](https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/quick-create-portal#create-virtual-machine)

### システム要件

EFLOW に必要な Windows デバイスの最小要件は[こちら](https://docs.microsoft.com/ja-jp/azure/iot-edge/how-to-install-iot-edge-on-windows?view=iotedge-2018-06&tabs=windowsadmincenter#prerequisites)で参照できます。

- 共通の要件
  - Windows 10 バージョン 1809 以降、ビルド 17763 以降
  - Professional、Enterprise、または Server エディション
  - 最小空きメモリ容量：1 GB
  - 最小空きディスク領域：10 GB

上記のほかに、Windows10/Windows Server/VM の中からどれを採用するかによって、個別のシステム要件を満たす必要があります。

- 個別の要件
  - Windows 10：有効化された Hyper-V
  - Windows Server：Hyper-V ロールのインストールとネットワークスイッチ
  - VM：入れ子になった仮想化の構成

今回は VM を採用するため、**入れ子になった仮想化**と呼ばれる構成が必要となります。

### 入れ子になった仮想化

入れ子になった仮想化とは、**Hyper-V 上で動作している VM で、さらに Hyper-V を利用して VM を起動する構成のこと**です。

Hyper-V は CPU の拡張機能に依存して仮想マシンを実行しています。
Intel VT-x や AMD-V などが代表的です。
一般的に、この仮想化のための拡張機能は、Hyper-V で使用している間は他のプロセスで使用できません。
そこで、その制限を解消して VM 上でも Hyper-V を利用できるようになった構成が「入れ子になった仮想化」というわけです。
![nasted_virtualization.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/e31fd962-9155-344f-937c-9a256586a4a6.png)
出典：[Azure IoT Edge for Linux on Windows (EFLOW)](https://docs.microsoft.com/ja-jp/windows/iot/iot-enterprise/eflow)

Azure VM は Hyper-V で仮想化されたインスタンスであるため、今回のケースのように Azure VM の中で Hyper-V を利用するには、入れ子になった仮想化をサポートするインスタンスを選択する必要があります。

入れ子になった仮想化がサポートされる Azure VM のサイズは、[Azure コンピューティング ユニット (ACU)](https://docs.microsoft.com/ja-jp/azure/virtual-machines/acu?view=iotedge-2018-06)で確認できます。
今回は Standard_D4s_v4 のインスタンスを選択しました。

詳細は以下のリンクをご参照ください。

- [入れ子になった仮想化の有効化](https://docs.microsoft.com/ja-jp/virtualization/hyper-v-on-windows/user-guide/nested-virtualization)
- [Azure IoT Edge for Linux on Windows の入れ子になった仮想化](https://docs.microsoft.com/ja-jp/azure/iot-edge/nested-virtualization?view=iotedge-2018-06)

## EFLOW 環境の構築

[MS Docs のチュートリアル](https://docs.microsoft.com/ja-jp/azure/iot-edge/how-to-install-iot-edge-on-windows?view=iotedge-2018-06&tabs=windowsadmincenter)に従って、Azure VM に EFLOW 環境を構築します。

システム要件を満たすインスタンスを選択していれば、特に問題なくデプロイできるかと思いますが、前述した入れ子になった仮想化がサポートされていないインスタンスを選択した場合、EFLOW のデプロイを作成する際に以下のエラーが検出されます。

`Hyper-V core services not running (vmms, vmcompute, hvhost). Please ensure Hyper-V is configured properly and capable of starting virtual machines. As you are deploying inside a virtual machine, please ensure nested virtualization is enabled. (L4573)`

![eflow_deploy_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/6bd9d911-8e75-437e-8f92-661a8b65739f.png)

詳細な作業手順は[こちら](https://qiita.com/motoJinC25/items/edc8c01a9d21b53cd642)の記事が非常にわかりやすいです。

## Azure IoT Edge モジュールのデプロイ

無事に EFLOW 環境を構築できたら、実際に IoT Edge モジュールをデプロイして動作を確認してみます。

今回は、Azure Marketplace からデプロイできる [Simulated Temperature Sensor](https://github.com/Azure/iotedge/tree/master/edge-modules/SimulatedTemperatureSensor) と MS Docs で公開されている [Python カスタムコードモジュール](https://docs.microsoft.com/ja-jp/azure/iot-edge/tutorial-python-module?view=iotedge-2020-11)の 2 つを IoT Edge デバイスにデプロイしました。

### Simulated Temperature Sensor

架空の機械温度/湿度/気圧の測定値を生成するモジュールです。
時間経過で気温が上昇するようになっており、異常検出のチュートリアルでよく利用されています。

Azure Portal からデプロイする場合、IoT Hub から IoT Edge デバイスを選択し、IoT Edge モジュールの設定から追加します。

![marketplace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/e4ca4faf-98b6-f59a-fd97-6312d9d3d421.png)

検索バーに Simulated...と入力していくとサジェストされるので、選択して追加します。

![temp_sensor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/7d097e02-8477-8e57-ecb8-50b79ea7c1b4.png)

### Python カスタムコードモジュール

IoT Edge では、任意の処理を実行するモジュールを作成し、デバイスにデプロイすることが可能です。
今回は、上述の Simulated Temperature Sensor で生成される温度が 25℃ を超えた場合に、そのデータを IoT Hub に送信するモジュールをデプロイしました。

[こちら](https://docs.microsoft.com/ja-jp/azure/iot-edge/tutorial-python-module?view=iotedge-2020-11)のチュートリアル通りに進めることで、モジュールの作成、コンテナの build & push、IoT Edge デバイスへのデプロイを VS Code 上で完結できます。

モジュール名はなんでもいいのですが、今回は PythonModule としました。

### 動作確認

EFLOW 環境に入り、`iotedge list`で 2 つの IoT Edge モジュールがデプロイされているか確認します。

![iotedge_list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/7c54b148-520a-ea83-e2a4-6b14450b506e.png)

`iotedge logs モジュール名`を実行し、各モジュールからのログを確認します。

- Simulated Temoerature Sensor のログ
  ![iotedge_logs_temp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/d1ebce22-0a80-8309-e2c0-fab48de1f126.png)

- Python カスタムコードモジュールのログ
  ![iotedge_logs_python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/1d9eeda8-7586-f679-13c8-d2e337f81306.png)


最後に、IoT Hub に到達するメッセージを確認します。
Simulated Temperature Sensor で生成されたデータが PythonModule でフィルタリングされ、25℃ 以上のデータが送信されています。
![iothub_message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1871738/e3b854ac-1bcb-d672-908e-4a6aa64c66a7.png)

## まとめ

今回は一般公開された EFLOW 環境を Azure VM 上に構築し、一般のシステム要件に加えて入れ子になった仮想化のサポートが必要であることを確認しました。

今後は EFLOW 環境の強みである、Windows アプリケーションとの連携や Linux ディストリビューションでの開発を中心に調査を進めていきます。