複数のAzure IoT Edgeデバイスへコンテナーを自動デプロイする

複数のIoT Edgeデバイスに対し、コンテナーをゼロタッチで配布する方法について調べてみました。
定義された一連の条件を満たす登録済みデバイスにモジュールを自動的にデプロイします。

<img width="500" alt="a78ddabd-26c3-0f67-952b-772b6bf815b8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/a78ddabd-26c3-0f67-952b-772b6bf815b8.png">

# 1) 事前準備
事前に以下の準備が必要です。

### IoT Edgeモジュールの開発およびContainer Registryへの登録
自動デプロイを試す前に、デプロイするものが必要になります。
今回は、事前に以下リンクの手順に従って、**classifier** と **cameraCapture** という二つのIoT Edgeモジュールを開発し、Azure Container Registryにプッシュしておきます。
（レジストリにイメージを配置するところまでを実施し、最後のIoT Edgeデバイスへデプロイする手順は実施せず止めておきます）

[チュートリアル:Custom Vision Service を使用してエッジで画像の分類を実行する](https://docs.microsoft.com/ja-jp/azure/iot-edge/tutorial-deploy-custom-vision)
 
### IoT Edgeデバイスのプロビジョニング
IoT Edge自動デプロイを行うためには、IoT Hub と IoT Edgeデバイスとが通信できるようにしておく必要があります。
IoT Edgeデバイスの IoT Hub へのプロビジョニング方法は以下手順が参考になります。手っ取り早いのは、IoT Hubへの接続文字列をデバイスの config.yaml に埋め込む手動プロビジョニングです。

[セキュリティ デーモンを構成する](https://docs.microsoft.com/ja-jp/azure/iot-edge/how-to-install-iot-edge-linux#configure-the-security-daemon)

また、大量のデバイスを扱う場合は、以下記事も参考にしてください。

[Azure IoT EdgeデバイスをX.509証明書を使って自動プロビジョニングする](https://qiita.com/yasuhanda/items/1763a79f14fc9d9215c5)

詳細手順は割愛しますが、今回は事前に`iotedgedev001`と`iotedgedev002`という名前の二つの IoT Edgeデバイスを、IoT Hubと通信できる状態に設定しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/7bfb072b-eb83-c4cc-d866-1ba0252bb146.png)

また、デバイス ツイン内のタグを使用してデプロイ対象のデバイスを識別させることができますので、デプロイ対象とする上記二つのデバイスに対して、以下のタグを設定しておきます。

```
  "tags": {
    "environment": "test"
  },
```

<img width="300" alt="7a2e18e1-3709-fc86-26ba-a9561334fb0e.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/7a2e18e1-3709-fc86-26ba-a9561334fb0e.png">

# 2) デプロイの作成
ここからが本題です。
[Azure portal](https://ms.portal.azure.com/) へサインインし、IoT Hubのインスタンスに移動し、[デバイスの自動管理] > [IoT Edge] を開き、[展開の作成] をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/1d35643a-dbb9-809e-9e71-e3922f2d90b9.png)

### Name and Label

作成するデプロイ定義に対して、任意の名前やラベルを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/4a537619-c9bc-5d36-8102-539c53572aab.png)

### Modules

[Container Registry Credentials] には、事前準備でコンテナーイメージをプッシュした Azure Container Registry の接続情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/8ebbb21a-d5a0-34c3-5ea1-aefadb46cef7.png)

[IoT Edge Modules] で [+ Add] > [+ IoT Edge Module] をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/f1841458-93d0-e10b-71e9-171860521607.png)

以下の通り **classifier** モジュールの情報を指定し、[Add]をクリックします。

- IoT Edge Module Name: `classifier`
- Module Settings > Image URI: `<registryname>.azurecr.io/classifier:0.0.1-amd64`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/bd9e6ed8-cc7e-42e8-ee81-251f268396bc.png)

同様の手順で、**cameraCapture** モジュールも追加します。

- IoT Edge Module Name: `cameraCapture`
- Module Settings > Image URI: `<registryname>.azurecr.io/cameracapture:0.0.1-amd64`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/d42a9de9-38ae-bead-0c15-616173ac6c5e.png)

- Container Create Options: `{"Env":["IMAGE_PATH=test_image.jpg","IMAGE_PROCESSING_ENDPOINT=http://classifier/image"]}`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/440b2174-c2f0-d0f7-2919-3584e8aa4c59.png)

### Routes

以下の通りデプロイ内のモジュール間の通信方法を指定します。

- NAME: `CameraCaptureToIoTHub`
- VALUE: `FROM /messages/modules/cameraCapture/outputs/* INTO $upstream`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/6562c95f-3271-b72b-2f36-4cb4aa1fbb69.png)

### Target Devices

デプロイの優先度とデプロイ対象を指定します。[Target Condition] ではデバイス ツインのタグ情報を利用して対象のデバイスを抽出します。
（[Target Condition] 入力後に [View Devices] をクリックし、目的のデバイスが取得できることを確認ください）

- Priority: (任意の整数)
- Target Condition: `tags.environment='test'`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/c06eb120-310d-b5b1-9cdf-24aca525556e.png)

### Review + create

[Create]をクリックします。デプロイが開始されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/7da5f55d-0258-4fac-c2aa-3704d1f637d2.png)


# 3) デプロイ結果の確認

### IoT Edge側での確認方法

それぞれのIoT Edgeデバイスにログインし、`journalctl -u iotedge`コマンドにてデプロイ状況のログが確認できます。

また、`iotedge list`よりデプロイ済みモジュールが確認できます。


```:iotedgedev001
testuser001@IoTEdgeVM001:~$ iotedge list
NAME             STATUS           DESCRIPTION      CONFIG
cameraCapture    running          Up a minute      yahanda1.azurecr.io/cameracapture:0.0.1-amd64
classifier       running          Up 8 seconds     yahanda1.azurecr.io/classifier:0.0.1-amd64
edgeAgent        running          Up 2 hours       mcr.microsoft.com/azureiotedge-agent:1.0
edgeHub          running          Up 2 minutes     mcr.microsoft.com/azureiotedge-hub:1.0
testuser001@IoTEdgeVM001:~$
```

```:iotedgedev002
testuser001@IoTEdgeVM002:~$ iotedge list
NAME             STATUS           DESCRIPTION      CONFIG
cameraCapture    running          Up 38 seconds    yahanda1.azurecr.io/cameracapture:0.0.1-amd64
classifier       running          Up 43 seconds    yahanda1.azurecr.io/classifier:0.0.1-amd64
edgeAgent        running          Up 17 minutes    mcr.microsoft.com/azureiotedge-agent:1.0
edgeHub          running          Up 2 minutes     mcr.microsoft.com/azureiotedge-hub:1.0
testuser001@IoTEdgeVM002:~$
```


### IoT Hub側での確認方法

Azure portal の IoT Hub のメニューからもデプロイ結果の確認が可能です。

- [デバイスの自動管理] > [IoT Edge] > 対象のデバイスIDをクリック
    - →各モジュールのデプロイ状況および稼働状況の確認が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/7f7929d9-f0da-47fe-2873-84fee389dc6f.png)

- [デバイスの自動管理] > [IoT Edge] > [IoT Edgeデプロイ] タブをクリック
    - →デプロイの詳細情報の確認が可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575879/6431a9f1-e5a5-880e-36f7-232988f50c72.png)