IoT Edge は現在プレビューですが、「透過的なゲートウェイとして動作する IoT Edge デバイスを作成する - プレビュー」のドキュメントの具体的な手順に関するご質問をいただいておりますので、私の手元で確認した手順を一つの構成例としてご案内します。
弊社が公開している構成例として、すでに以下のようなページがありますが、今回ご案内する手順では、両方を参考にして、後者の、IoT Edge のゲートウェイをLinux (ローカルPC 上の仮想マシン)、IoT デバイスをRaspberry Pi 3 としています。
・IoT Edge のゲートウェイがWindows、IoT デバイスがRaspberry Pi 3 の例
IOT EDGE PYTHON RASPBERRYPI CONNET TRANSPARENT GATEWAY
< https://github.com/Azure-Samples/iot-edge-python-raspberrypi-connect-transparent-gateway >
・IoT Edge のゲートウェイとIoT デバイスをともにLinux のAzure VM 1 つの中に持つ例
Azure IoT Edge Hands On Labs
< https://github.com/AzureIoTGBB/azure-iot-edge-hol-linux >
Lab 1,2 をご参照ください。
-
- 今回前提とする構成
今回は、最小構成として、以下の図のような、IoT Hub に、IoT Edge のゲートウェイ1 つがつながっていて、そのゲートウェイを通じて IoT Hub と透過的(transparent) に通信するデバイス(リーフ デバイス, leaf device) 1 つがつながっていることを前提とします。
![clip_image002 clip_image002]()
IoT Edge のゲートウェイには、今回、(作業用 PC の) Windows 10 Enterprise x64 1709 上のHyper-V の仮想マシン(最大メモリ4GB、外部ネットワークに接続) として、Ubuntu 16.04 LTS をインストールしています。
リーフデバイスには、Raspberry Pi 3 を用意し、以下の手順でインストールしています。(「Raspberry Pi の Azure IoT Hub への接続 (Python)」の「Pi の Raspbian オペレーティング システムのインストール」の手順と同様です。)
Windows 10 Enterprise x64 1709 上で以下を実施します。
(a) < https://www.raspberrypi.org/downloads/raspbian/ > のサイトから、Raspbian Stretch with desktop の zip ファイルをダウンロードし、解凍します。
(b) Etcher SD カード書き込みユーティリティをダウンロードしてインストールします。
(c) micro SD カード(私の手元では64GB のものを使用しています) をWindows PC に接続します。
(d) Etcher を実行し、[Select image] をクリックして、(a) で解凍したRaspbian イメージ(今回は2018-03-13-raspbian-stretch.img) を選択します。
(e) micro SD カード ドライブを選択します。 適切なドライブが既に選択されている場合があります。
(f) [Flash (フラッシュ)] をクリックして、micro SD カードにRaspbian をインストールします。
(g) インストールが完了したら、コンピューターからmicro SD カードを取り出します。Etcher では完了時にmicro SD カードを自動的に取り出すか、マウント解除するため、micro SD カードを直接取り出しても問題ありません。
(h) micro SD カードをRaspberry Pi 3 に挿入します。
-
- SSH の設定と接続確認
(a) リーフデバイス(Raspberry Pi 3) 側で、SSH を有効にします。
-
- Raspberry Pi 3 にモニター、キーボード、マウスを接続し、Raspberry Pi 3 を起動してから、pi をユーザー名として、raspberry をパスワードとして使用してRaspbian にログインします。(起動するだけで、自動的にログインされている場合があります。)
-
- Raspberry アイコン> [Preferences](設定) > [Raspberry Pi Configuration](Raspberry Pi 構成) の順にクリックします。
-
- [Interfaces] (インターフェイス) タブで、[SSH] を[Enable] (有効) に設定し、[OK] をクリックします。
(b) Raspberry Pi 3 にイーサネット ケーブルを使用して有線ネットワークに接続します。
(c) Terminal を起動し、ifconfig を実行して、eth0 の inet に表示されるIP アドレスをメモします。
(d) Hostname を変更しておきます。
-
- nano で /etc/hostname を開きます
$ sudo nano /etc/hostname
-
- raspberrypi から任意の名前に変更します
-
- Ctrl-o とEnter で保存します
-
- Ctrl-x でnano を終了します
-
- 再起動します。
$ sudo reboot
(e) passwd でパスワードも変更しておきます。
(f) Raspbian を更新しておきます。
$ sudo apt update && sudo apt full-upgrade -y
(g) IoT Edge ゲートウェイ(Ubuntu) 側で、SSH を有効にします。
-
- Terminal を起動します。
-
- パッケージの管理を行うためのaptitudeをインストールします。
$ sudo apt-get install aptitude
-
- aptitudeを使ってsshを導入します。
$ sudo aptitude install ssh
-
- ifconfig を実行して、eth0 のinet に表示されるIP アドレスをメモします。
(h) Windows 10 (作業用PC) にWindows 版の PuTTY をダウンロードしてインストールします。
(i) PuTTY を起動して、(c) のIP アドレスでSSH 接続し、ログインできるか確認します。
(j) PuTTY をもう1 つ起動して、(g) のIP アドレスでSSH 接続し、ログインできるか確認します。
-
- IoT Hub の作成
(a) 「Linux または MacOS のシミュレートされたデバイスへの Azure IoT Edge のデプロイ - プレビュー」の「IoT Hub の作成」の手順に従って、[F1 - Free] レベルのIoT Hub を作成します。
(b) Azure ポータル上で作成されたIoT Hub をクリックし、左側のペインの[共有アクセスポリシー] をクリックし、右側に表示される[iothubowner] をクリックして、表示される「接続文字列 –
プライマリキー」の値をメモします。
![clip_image004 clip_image004]()
-
- IoT Edge デバイスの登録
(a) 「Linux または MacOS のシミュレートされたデバイスへの Azure IoT Edge のデプロイ - プレビュー」の「IoT Edge デバイスを登録する」の手順に従って、IoT Edge ゲートウェイの名前を登録します。今回、以下の[デバイスID] をIoT Edge ゲートウェイの hostname と同じにしました。
![clip_image006 clip_image006]()
(b) 登録されたデバイスID をクリックし、表示される「接続文字列 – プライマリキー」の値をメモします。
![clip_image008 clip_image008]()
![clip_image010 clip_image010]()
-
- IoT Edge ゲートウェイ(Ubuntu) 側の準備
以下は、IoT Edge ゲートウェイ(Ubuntu) へのSSH 通信を行っている PuTTY 上で実行します。
(a) パッケージを更新します。
$ sudo apt-get update
(b) pip をインストールします。
$ sudo apt-get install python-pip
(c) curl がない場合はインストールします。
$ sudo apt install curl
(d) Docker for Linux をインストールします。(参考:Get Docker CE for Ubuntu)
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
(e) Ubuntu に現在ログインしているユーザーアカウントがルート権限を持たない場合、Docker admin group にそのユーザーアカウントを追加することでルート権限でコンテナを実行できます。以下を実行後、いったんログアウトし、再度ログインすることで有効になります。
$ sudo usermod -aG docker <Ubuntu に現在ログインしているユーザーアカウント>
(f) Azure IoT Edge コントロールスクリプトをインストールします。
$ sudo pip install -U azure-iot-edge-runtime-ctl
(g) iothub-explorer tool をインストールします。
$ sudo apt-get install nodejs
$ sudo apt-get install npm
$ sudo npm install -g iothub-explorer
インストールしたバージョンを確認し、動作していることを確認します。
$ iothub-explorer –version
「/usr/bin/env: ‘node’: No such file or directory」のエラーが出る場合は、先に以下を実行します。
$ sudo ln -s /usr/bin/nodejs /usr/bin/node
iothub-explorer –version を実行すると、今回は 1.2.1 と表示されました。
(h) .NET Core をインストールします。(参考:Prerequisites for .NET Core on Linux)
$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
$ sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
$ sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
$ sudo apt-get update
$ sudo apt-get install dotnet-sdk-2.1.4
インストールしたバージョンを確認し、動作していることを確認します。
$ dotnet --version
インストールしたバージョン通り、2.1.4 と表示されます。
(i) Azure IoT C SDK の “modules-preview” ブランチをクローンします。
git がインストールされていない場合はインストールします。
$ sudo apt install git
$ git clone -b modules-preview https://github.com/Azure/azure-iot-sdk-c
(j) リーフデバイスがIoT Edge ゲートウェイ経由で IoT Hub までの通信には TLS 接続を行います。そのための自己署名証明書作成の作業用ディレクトリとして edge ディレクトリを作成し、そこに移動します。
$ mkdir edge
$ cd edge
(k) 証明書作成のスクリプトを上記ディレクトリにコピーします。
$ cp ~/azure-iot-sdk-c/tools/CACertificates/*.cnf .
$ cp ~/azure-iot-sdk-c/tools/CACertificates/*.sh .
(l) certGen.sh を実行可能にします。
$ chmod 700 certGen.sh
(m) 証明書チェーンを作るためのルート証明書と中間証明書を作成します。
$ ./certGen.sh create_root_and_intermediate
certs ディレクトリに、以下のファイルができることを確認します。
$ ls certs
azure-iot-test-only.chain.ca.cert.pem azure-iot-test-only.root.ca.cert.pem
azure-iot-test-only.intermediate.cert.pem
(n) IoT Edge ゲートウェイ自体のデバイス固有の証明書を作成します。
$ ./certGen.sh create_edge_device_certificate myGateway
※ この時、myGateway の部分は変更せず、そのままにしてください。
certs ディレクトリに、new-edge-device.cert.pem とnew-edge-device.cert.pfx が追加されます。
(o) これによって公開鍵と秘密鍵が作成されます。certs ディレクトリに移動して、そこで公開鍵の完全なチェーンを作ります。
$ cd certs
$ cat ./new-edge-device.cert.pem ./azure-iot-test-only.intermediate.cert.pem ./azure-iot-test-only.root.ca.cert.pem > ./new-edge-device-full-chain.cert.pem
-
- リーフデバイス(Raspbian) 側の準備
以下は、リーフデバイス(Raspbian) へのSSH 通信を行っているPuTTY 上で実行します。
(a) IoT Edge ゲートウェイのIP アドレス(2-(g) でメモしたもの) を、リーフデバイス側から見えるようにします。
$ sudo nano /etc/hosts
ファイルの最も下の行に以下のように記載します。
<2-(g) でメモしたIoT Edge ゲートウェイのIP アドレス> mygateway.local
※この時、mygateway.local は変更せずそのままにしてください。
Ping してリーフデバイス側から IoT Edge ゲートウェイに通信できることを確認します。
$ ping mygateway.local
(b) 5-(m) で作成したルート証明書を、リーフデバイスにインストールします。
-
- こちらにもedge ディレクトリとその下のcerts ディレクトリを作成します。
$ mkdir edge
$ cd edge
$ mkdir certs
$ cd certs
-
- azure-iot-test-only.root.ca.cert.pem をこのディレクトリにコピーします。
今回は、IoT Edge ゲートウェイ側で sudo nano azure-iot-test-only.root.ca.cert.pem を実行し、内容全部(-----BEGIN CERTIFICATE-----から-----END CERTIFIATE----- まで含めて全部)を、リーフデバイス側でもsudo nano azure-iot-test-only.root.ca.cert.pem を実行してコピー、Ctrl-o とEnterで保存しました。
-
- これを以下の手順でインストールします。
$ openssl x509 -in azure-iot-test-only.root.ca.cert.pem -inform PEM -out azure-iot-test-only.root.ca.cert.crt
$ sudo mkdir /usr/share/ca-certificates/extra
$ sudo cp azure-iot-test-only.root.ca.cert.crt /usr/share/ca-certificates/extra/azure-iot-test-only.root.ca.cert.crt
$ sudo dpkg-reconfigure ca-certificates
-
- 最後のコマンドを実行すると、証明書をルートストアにインストールすることについて警告が出ますが、yes をハイライトさせてEnter で<Ok>
します。
![clip_image012 clip_image012]()
-
- 次の画面では以下の赤いスペース部分のようにextra/azure-iot-test-only.root.ca.cert.crt の[ ] がブランクになっています。
![clip_image014 clip_image014]()
ここでスペースを押し、extra/azure-iot-test-only.root.ca.cert.crt が [*] になるようにしてから、Enter で <Ok> します。
![clip_image016 clip_image016]()
-
- 確認のために、以下を実行し、末尾に「extra/azure-iot-test-only.root.ca.cert.crt」があることを確認します。
$ sudo cat /etc/ca-certificates.conf
-
- IoT Edge ゲートウェイの開始
以下は、IoT Edge ゲートウェイ(Ubuntu) へのSSH 通信を行っている PuTTY 上で実行します。
-
- 以下を実行して、IoT Edge ゲートウェイとしてのセットアップを行います。
$ cd ~
$ sudo iotedgectl setup --connection-string "<4-(b) のIot Edge ゲートウェイの接続文字列>" --edge-hostname mygateway.local --device-ca-cert-file /home/<Iot Edge ゲートウェイのUbuntu
のログインユーザー名>/edge/certs/new-edge-device.cert.pem --device-ca-chain-cert-file /home/<Iot Edge ゲートウェイのUbuntu のログインユーザー名>/edge/certs/new-edge-device-full-chain.cert.pem --device-ca-private-key-file /home/<Iot Edge ゲートウェイのUbuntu のログインユーザー名>/edge/private/new-edge-device.key.pem --owner-ca-cert-file /home/<Iot Edge ゲートウェイのUbuntu のログインユーザー名>/edge/certs/azure-iot-test-only.root.ca.cert.pem
-
-
- ここでも、--edge-hostname の mygateway.local は変更せず、そのままにしてください。
-
- 「Please enter the Edge Agent private key passphrase. Length should be >=4 and <= 1023:」と表示されたら12345 と入力し Enter を押します。
-
- 再度入力を求められるので同じようにします。
-
- IoT Edge ランタイムを起動します。
$ sudo iotedgectl start
-
- IoT Edge ランタイムを構成しているコンテナ/モジュール のedgeAgent が動作していることを確認します。
$ sudo docker ps
以下のように表示されます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d8178dc82f6 microsoft/azureiotedge-agent:1.0-preview "/usr/bin/dotnet Mic…" 2 minutes ago Up 2 minutes edgeAgent
-
- 以下を実行すれば edgeAgent のログも確認できます。
$ sudo docker logs -f edgeAgent
-
- リーフデバイス側からの通信
(a) 今回は例として「Azure IoT Edge Hands On Labs - Module 2」のサンプルを動作させてみます。
-
- この Lab のサンプルをクローンします。
$ cd ~
$ git clone http://github.com/azureiotgbb/azure-iot-edge-hol-linux
-
- Python SDK のプレビューバージョンのライブラリをセットアップ、ビルドします。
$ git clone --recursive -b modules-preview http://github.com/azure/azure-iot-sdk-python
$ cd ~/azure-iot-sdk-python/build_all/linux
$ sudo ./setup.sh
$ sudo ./build.sh
-
- ビルドが終わったら、Lab のサンプルのソリューション ディレクトリにコピーします。
$ cp ../../device/samples/iothub_client.so ~/azure-iot-edge-hol-linux/module2
(b) IoT Hub にリーフデバイスを登録します。
-
- Azure ポータルのIoT Hub の左側のペインで、[デバイス エクスプローラー] をクリックします。
-
- [追加] をクリックし、[デバイスの追加] で [デバイスID] にリーフデバイスの名前を入力し、[保存] します。今回は、2-(d) で設定した hostname と同じにしました。
![clip_image018 clip_image018]()
(c) 追加されたデバイスID をクリックし、[デバイスの詳細] 画面で「接続文字列 – プライマリ キー」をメモします。
![clip_image020 clip_image020]()
(d) この接続文字列の末尾に「;GatewayHostName=mygateway.local」(今回は mygateway.local を変更せずそのまま使ってください)を入れ、Python スクリプトに記入します。
$ cd ~/azure-iot-edge-hol-linux/module2
$ nano iotdevice.py
以下の行を見つけ、接続文字列を置き換えます。
connection_string = "<IoT Device connection string here>"
Ctrl-o、Enterで保存し、Ctrl-xで終了します。
これを行うことで、指定した IoT Edge ゲートウェイを通じてIoT Hub にリーフデバイス(上のPython スクリプト) が接続しに行きます。
(e) Azure ポータルのIoT Hub の左側のペインの [IoT Edge (preview)] をクリックし、IoT Edge ゲートウェイのデバイスID をクリックします。
![clip_image022 clip_image022]()
(f) 画面上部の[Set Modules] をクリックします。
![clip_image024 clip_image024]()
(g) [1 Add Modules (optional)] では何もせず画面下部の[Next] をクリックします。
(h) [2 Specify Routes (optional)] では、以下のようになっていることを確認し、画面下部の[Next] をクリックします。
![clip_image026 clip_image026]()
これは、$upstream はクラウド上のIoT Hub に送信する、ということを意味します。この route は全てのメッセージ(/*) を受け取り、クラウドに送ります。
(i) [3 Review Template (optional)] では、そのまま [Submit] をクリックします。
(j) これにより、IoT Edge ゲートウェイ上には edgeHub が起動します。IoT Edge ゲートウェイと通信しているPuTTY 上で以下を実行して確認できます。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
670d08c9c3c7 microsoft/azureiotedge-hub:1.0-preview "scripts/linux/start…" 3 minutes ago Up 3 minutes 0.0.0.0:443->443/tcp, 0.0.0.0:8883->8883/tcp edgeHub
8d8178dc82f6 microsoft/azureiotedge-agent:1.0-preview "/usr/bin/dotnet Mic…" 2 hours ago Up 2 hours edgeAgent
(k) 以下のようにedgeHub のログを確認できます。
$ sudo docker logs -f edgeHub
以下のような、ポート8883 (MQTT over SSL, TLS 認証を使ったMQTT) が初期化されたこともわかります。
[INF] - Initializing TLS endpoint on port 8883 for MQTT head.
これで IoT Edge ゲートウェイにリーフデバイスから接続できます。
(l) ここで、リーフデバイスと通信している PuTTY 上で以下を実行して、証明書チェーンに問題がないことを確認します。
$ openssl s_client -connect mygateway.local:8883 -showcerts
以下が表示例です。「verify return:1」と全て1 が返ってきていれば問題ありません。
=====表示例:ここから=====
CONNECTED(00000003)
depth=4 CN = Azure IoT Hub CA Cert Test Only
verify return:1
depth=3 CN = Azure IoT Hub Intermediate Cert Test Only
verify return:1
depth=2 CN = myGateway
verify return:1
depth=1 CN = Edge Agent CA
verify return:1
depth=0 CN = mygateway.local
verify return:1
---
Certificate chain
0 s:/CN=mygateway.local
i:/CN=Edge Agent CA
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
1 s:/CN=Azure IoT Hub Intermediate Cert Test Only
i:/CN=Azure IoT Hub CA Cert Test Only
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
2 s:/CN=myGateway
i:/CN=Azure IoT Hub Intermediate Cert Test Only
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
3 s:/CN=Edge Agent CA
i:/CN=myGateway
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=mygateway.local
issuer=/CN=Edge Agent CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5506 bytes and written 302 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: BD0F16D2519A492477F6F3F142398EA9535102843A9136E98FBE3D832D4F4697
Session-ID-ctx:
Master-Key: DB3BA5E6A2B391CB27D34C8F58E8ABEBD5375AF78372874E81C32219ADBCE6D40F71E15035D5CF341BA1AD1803B95C52
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - 98 95 db cb 68 1b f0 34-ee fb 76 4b e8 fc b5 e5 ....h..4..vK....
0010 - 23 09 ad 14 06 eb 4c ef-50 3c 5d d2 09 c5 84 62 #.....L.P<]....b
0020 - 32 d0 c0 28 db a6 68 b5-df d0 93 83 1b ea f8 a6 2..(..h.........
0030 - b6 ee b9 97 f2 eb 91 08-c4 43 ec ce 37 0f b8 68 .........C..7..h
0040 - f6 61 67 8e 58 41 b0 bd-10 0c 91 1e 9b ff 6c 18 .ag.XA........l.
0050 - e3 20 75 f4 23 4e 56 59-52 72 08 24 d6 f0 f4 03 . u.#NVYRr.$....
0060 - 45 1a 8d 0f b5 ef 05 55-5d 7d 2e 6a 43 3b 2b 7c E......U]}.jC;+|
0070 - f0 5b fa 38 31 e6 21 ec-0a b2 fb 17 e5 cb 8b 9d .[.81.!.........
0080 - 8d c0 2a 6e 86 08 48 29-35 6d 87 79 3f 68 b3 f1 ..*n..H)5m.y?h..
0090 - 2d 85 e7 22 83 75 19 0e-d5 3c 42 8a c6 00 6c 59 -..".u...<B...lY
Start Time: 1523165748
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
---
read:errno=0
=====表示例:ここまで=====
「Certificate chain」の部分について少し補足します。
「s:/CN=mygateway.local」のように「s:」で始まるものはsubject (証明対象の名称) を表し、「i:/CN=Edge Agent CA」のように「i:」で始まるものはissuer (証明書の発行者、通常CA) を表します。
この証明書チェーンの検証は、以下の図のように、mygateway.local から、ルート証明書(Azure IoT Hub CA Cert Test Only) まで、「i:」に該当する「s:」があるかをチェックしていきます。
![clip_image028 clip_image028]()
なお、Raspberry Pi 3 上の信頼できるルート証明書(Azure IoT Hub CA Cert Test Only) にたどり着けばよいため、公開ドキュメントにあるようなAzure ポータルのIoT Hub のCertificates
に登録する必要はありません。
(m) IoT Hub 側の様子を見るために、PuTTY をさらにもう一つ起動し、IoT Edge ゲートウェイのIP アドレスに対してSSH 接続して、以下を実行します。
$ iothub-explorer monitor-events <8-(b)-2)でIoT Hub に登録したリーフデバイス名> -r --login "<3-(b)のIoT Hub のiothubowner の接続文字列>"
実行しても、リーフデバイスからの通信が始まらない限りは何も表示されないため、次に進みます。
(n) リーフデバイスからの通信を開始します。
リーフデバイスに接続している PuTTY から、以下を実行します。
$ cd ~/azure-iot-edge-hol-linux/module2
$ python -u iotdevice.py
以下のように表示されます。
![clip_image030 clip_image030]()
(o) (m) のウィンドウには以下のように表示されます。
![clip_image032 clip_image032]()
上記の内容がお役に立てば幸いです。
Azure IoT 開発サポートチーム 津田