ホーム » 技術 » Edge Computing » AWS Greengrassを動かしてみた

SAKURA Internet Inc.

アーカイブ

AWS Greengrassを動かしてみた

こんにちは、さくらインターネット研究所の菊地です。研究所ブログに登場するのは初めてになります。以後よろしくお願いいたします。

さくらインターネット研究所では、現在より一歩先の技術・サービスの調査・評価を継続的に実施しております。今回、コンシューマが利用可能なエッジコンピューティングの具体的なサービスとしてAmazon AWSより先日公開されたGreengrassを、サンプルを動かす程度ですが使ってみましたので、その様子をご紹介します。

なお、さくらインターネット研究所はAmazonやAWSとは特に関係はなく、以下の内容は菊地が一般ユーザとして試した内容になります。内容に誤りがある場合にはご教授いただければ幸いです。

Greengrassってなに?

AWSの公式の説明は、このへん(GreengrassのFAQページ)にありますが、菊地の現時点での認識としては「AWS IoTのノード(デバイス)収容とLambda関数実行をユーザ近傍エッジ(現場)に持ってきたもの」です。なおGreengrassの実体としては、センター側サービスと、Dockerっぽい(Dockerではない)エッジノードで稼働させるパッケージ、およびデバイス上で動かすユーザ作成プログラムの組み合わせ、です。AWS IoTを拡張する形で実装されています。

使い方、動かし方

以下、サンプルの実行方法です。基本的には以下のデベロッパーガイドに従うように作業します。ここでは差異・注意ポイントを中心に書きます。

なお、現時点では、Greengrassのサンプルは、C++のものしか提供されていないようです。AWSのgit(Amazon Web Services レポジトリ)を見てみましたが、greengrass関係のコードはaws-iot-device-sdk-cppにしか見当たらないようです。

実行環境(デバイス等)の用意

今回はRaspberry Pi 3 Model Bを3台利用しました。1台をGreengrass_Coreとして利用し、2台をThing(現場デバイス)として使います。いずれも最新のRasbian OSをインストールして、取りあえず使えるように(sshdを起動するなど)設定しておきます。

今回は以下のような構成を構築しました。作業用に有線ネットワーク接続(図では下側)を利用していますが必須ではありません。今回は、WiFi側は動的にアドレスが変わって面倒なので固定アドレスの有線ネットワークを利用しました。なおアドレスの順番がちょっとおかしいのは作業の経緯の関係です。わかりにくくてすみません。

ソフトウェアのインストール、設定、AWS IoTコンソールでの作業

大まかに、1. AWS IoTコンソール上での設定、2. Greengrass_Coreの設定、3. Thingの設定、の3つのパートにわかれます。

1. AWS IoTコンソール上での設定

デベロッパーガイドではCLIで操作するように書いてありますが、試したところ、デバイス登録についてはAWS IoTコンソールでの操作が必要で、CLI/GUI(AWS IoTコンソール)を混ぜて操作するとエラーになってしまう現象が発生したため(バージョンの不整合を起こしてしまうためと想定)、全てAWS IoTコンソール上で作業しました。

リージョンの切り替え

greengrassは現時点では東京リージョンではサービス展開されていないため、サービス展開されているオレゴン(US-WEST-2)のリージョンに切り替えます。

GreenGrassグループとコアノードの作成

左側のメニューから”Greengrass”の”グループ”を選び、”グループの作成”をクリックします。すると、

という画面になるので、”簡単な作成の使用”を選びます。次の画面でグループの名前を入力し(今回は”GreengrassTest4″)、”次へ”と進むと、

コアノードの名前を聞かれますのでデフォルトのまま”次へ”、すると、グループとコアの作成を自動実行してくれて、さらに”次へ”と進むと、Coreノード用の証明書とコアソフトウェアのダウンロードができる画面になりますので、忘れずにダウンロードしておきます(あとで使います)。なお、ラズパイ3用のコアソフトウェアは、”ARMv7l”を選んで下さい。なお余談ですがGreegrassTest4なのは、試行錯誤の結果です。古いのを消したいと思っているのですが、うまくいきません…。

グループへのデバイスの追加

左側メニューの”Greengrass”の”グループ”を選び、画面に表示される、先ほど作成したgreengrassグループ(“GreengrassTest4”)を選択します。”デバイス”を選択し、デバイスを2つ作成します。下記の画面はすでに作成し終わった状態でキャプチャしたものですが、初期状態では何もデバイスが存在しておらず、ウィザード画面的なものが表示されていると思います。

“デバイス追加”をクリックすると、

という画面になるので、まだデバイスを作っていない場合には”新しいデバイスの作成”、を、あるいは色々試行錯誤した結果として既にデバイスを作成しているのであれば”IoT Thingを選択する”を選びます。どちらでも大丈夫です。このあたりの作業手順は一本道ではなくて、最終的にデバイスが追加されている状態になればOKです。(私は構成を理解するまでにしばらく試行錯誤が必要でした。)

新しいデバイスの作成を選んだ場合は次の画面でデバイスの名前を入力することになるので、”RobotArm_Thing”(もしくはSwitch_Thing)と入力します。(これを別の名前にしてしまうと、他のいろいろなところをを変更しなければならなくなるので、とりあえずサンプルを手っ取り早く動かしたい方は変更はお勧めしません。)

その次の画面では”セキュリティを設定する”となるので、”デフォルトを使用”(1-Clickデプロイ)を選びます。

すると、証明書と公開鍵/秘密鍵が生成されるので、必ずダウンロードしておきます(あとで使います)。

端末登録はRobotArm_ThingとSwitch_Thingの2台分実施します。

Lambda関数の登録

ここで一旦Greengrass設定からは離れて、Lambda関数を登録します。画面左上の”サービス”メニューを開き、コンピューティング項目にあるLambdaを選びます。

(この画面は既にLambda関数の登録がなされたものです)。 青い”Lambda関数の作成”をクリックして2つのLambda関数を登録します。

登録すべきコードは、AWS GreengrassコアSDKのzipファイル内にあります(greengrassコアソフトウェアと名前が似てるが別のもの)。AWS IoTコンソール左下の”ソフトウェア”の項目からダウンロード画面にいけます。これをダウンロードして展開しておいてから、Lambda関数の作成を実施します。作り方はデベロッパーガイドのCreate a Lambda Function Definitionにあります。そのページに書いてありますが、Lambda関数を作った後で、バージョンを切ってエイリアスを作っておくのを忘れないようにしましょう。
IAMでのロールの作成

Lambda関数の登録と並行して、IAMロールというものを作っておきます。画面左上の”サービス”メニュー内のセキュリティ、アイデンティティ項目内のIAMを選びます。

(この画面は既にロールが作成された後のものです)。青い”新しいロールの作成”からロールを作成します。ロールタイプの選択画面内に、”Greengrass_ServiceRole”があるのでそれを選びます。どうやら今回のサンプルではロールは使ってないらしいです(私もあまり良くわかっていません)。
さて、Lambda関数とロールを作成し終わったら、再びgreengrassの設定に戻ります。
グループへのLambdaの追加

先ほど作成したGreengrassのグループ”GreengrassTest4″を選択し、サブメニューの”Lambda”を選択します(この画面は既に追加された状態)。

“Lambdaの追加”を選択すると、GreengrassグループへのLambdaの追加、という画面になります。ここでは”既存のLambdaの使用”を選びます。すると先に作成したLambdaが選択できますので、2つとも追加するよう(2回)作業します。

グループへのロールの追加

ロールは、Greengrassグループの設定項目の中から登録します。一番上の「…」から登録できます。

グループへのサブスクリプションの追加

最後にサブスクリプションの設定です。デベロッパーガイドのCreate a Subscription Definitionを参照しながらサブスクリプションを登録していきます。全部で11個あり似てるのが多くて間違いやすいので注意します。

ドキュメント上の”Switch_Thing-arn”は”ソースとターゲットの選択”画面における”デバイス”の”Switch_Thing”に、”GGShadowService”は同様に”サービス”の”Local Shadow Service”に、”uptimeLambda-arn”は”Lambda”の”uptimeLambda”に、”cloud”は”サービス”の”IoT Cloud”に、それぞれ対応しています。

以上で、AWS IoT(クラウド)側でGreengrassを使うための枠組みができたことになります。この後、実際にデバイス側で作業をして、デバイス実体をクラウド側と結びつけていく作業をしていきます。

2. Greengrass_Coreの設定

Greengrass_coreとして動作させるラズパイ(今回の構成では192.168.1.102)上で作業します。

使用するパッケージ等のインストール

ドキュメントにある通りに設定コマンドを投入します。特に波乱はありません。(以下、投入するコマンドだけ書いていますが、実際には各コマンドがそれぞれ作業経過を画面出力します。また[Y/n]などと聞かれる場合がありますが、Yで進めていきます。)

pi@raspberrypi: sudo adduser --system ggc_user
pi@raspberrypi: sudo addgroup --system ggc_group
pi@raspberrypi: sudo apt-get install rpi-update
pi@raspberrypi: sudo rpi-update
pi@raspberrypi: sudo apt-get install sqlite3
pi@raspberrypi: sudo apt-get install cmake

/etc/apt/sources.list.d/raspi.listにレポジトリを追加。一番下が追加した行。

  • /etc/apt/sources.list.d/raspi.list
deb http://archive.raspberrypi.org/debian/ jessie main ui
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://archive.raspberrypi.org/debian/ jessie main ui
deb http://ftp.debian.org/debian jessie-backports main

で、update。

pi@raspberrypi: sudo apt-get update

ただ、apt-get updateではNO_PUBKEYエラーが出ますので、ここで説明されているとおりに解消策を実施します。エラーになっていたのは8B48AD6246925553, 7638D0442B90D010の2つなので、以下のように4行分入力。

pi@raspberrypi: gpg --keyserver pgpkeys.mit.edu --recv-key 8B48AD6246925553
pi@raspberrypi: gpg -a --export 8B48AD6246925553 | sudo apt-key add -
pi@raspberrypi: gpg --keyserver pgpkeys.mit.edu --recv-key 7638D0442B90D010
pi@raspberrypi: gpg -a --export 7638D0442B90D010 | sudo apt-key add -

更に続き。

pi@raspberrypi: sudo apt-get -t jessie-backports install libssl-dev

最後に、/etc/sysctl.d/98-rpi.confに以下の設定(下2行)を追加しておきます。

kernel.printk = 3 4 1 3
vm.min_free_kbytes = 16384
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

ここまでできたら、core本体を入れます。

Greengrass Coreソフトウェアのインストール、設定

コアソフトウェアは、AWS IoTコンソール上でGGグループを作成した際に証明書と共に手元端末にダウンロードしていると思いますが、別途明示的にダウンロードすることもできます。

ダウンロードしたコアソフトウェアをラズパイの/以下に展開。

pi@raspberrypi:~ $ sudo tar -zxf greengrass-platform-version.tar.gz -C /

/etc/fstabを編集。一番下の行が追記した分。

  • /etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=fa579550-01  /boot           vfat    defaults          0       2
PARTUUID=fa579550-02  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that
cgroup  /sys/fs/cgroup  cgroup  defaults        0       0

AWS IoTコンソールでデバイス(GreengrassTest4_core)を登録した際に作成されて、手元にダウンロードしておいたはずの証明書と秘密鍵をラズパイ上の/greengrass/configuration/certsにコピーします。その他、ルート証明書(root-CA.pem)も置きます。 (ここでは公開鍵も置いてしまっていますが本来は必要ありません。)

pi@raspberrypi:/greengrass/configuration/certs $ ls -l
total 36
-rw-r--r-- 1 ggc_user ggc_group 1224 Jun 21 16:13 xxxxxxxxxx-certificate.pem.crt
-rw-r--r-- 1 ggc_user ggc_group 1675 Jun 21 16:13 xxxxxxxxxx-private.pem.key
-rw-r--r-- 1 ggc_user ggc_group  451 Jun 21 16:13 xxxxxxxxxx-public.pem.key
-rw-r--r-- 1 ggc_user ggc_group   45 Jun  6 02:52 README
-rw-r--r-- 1 ggc_user ggc_group 1758 Jun 16 17:31 root-CA.pem
pi@raspberrypi:/greengrass/configuration/certs $

/greengrass/configuration/config.jsonを編集します。xxxxの部分はすぐ上の記述で配置した証明書と秘密鍵のファイル名を、yyyyの部分はAWS IoTコンソール上で設定したGreengrassTest4_CoreのARNを、zzzzの部分は自分のAWS IoTのカスタムエンドポイントのホスト名を指定します。GreengrassTest4_Coreの部分は、AWS IoTコンソール上でGreengrassグループを作成した時に指定したコアノードの名前を指定します。useSystemdはラズパイの場合”yes”です。

  • /greengrass/configuration/config.json (太字部分が編集したところ)
{
    "coreThing": {
        "caPath": "root-CA.pem",
        "certPath": "xxxxxxxxxx-certificate.pem.crt",
        "keyPath": "xxxxxxxxxx-private.pem.key",
        "thingArn": "arn:aws:iot:us-west-2:yyyyyyyyyyyy:thing/GreengrassTest4_Core",
        "iotHost": "zzzzzzzzzzzzz.iot.us-west-2.amazonaws.com",
        "ggHost": "greengrass.iot.us-west-2.amazonaws.com"
    },
    "runtime": {
        "cgroup": {
            "useSystemd": "yes"
        }
    }
}

ここまでできたら、いよいよCoreを起動。

pi@raspberrypi:/greengrass $ sudo ./greengrassd start
Setting up greengrass daemon
Validating execution environment
Found cgroup subsystem: cpu
Found cgroup subsystem: cpuacct
Found cgroup subsystem: blkio
Found cgroup subsystem: memory
Found cgroup subsystem: devices
Found cgroup subsystem: freezer
Found cgroup subsystem: net_cls
Starting greengrass daemon.....
Greengrass daemon started with PID: 1240
pi@raspberrypi:/greengrass $

設定を間違っていなければ、以下のようになるはずです(PIDの数字は都度変わる)。うまくいかない場合はcrash.logにログが出ます。

なおクリーンインストールする場合は関係ありませんが、一度Coreインストールして設定・稼働させて、別設定でやり直したりする場合には、.gzファイルを再度展開(上書きで可)しないとうまく動かない場合があるようです(ありました)。

3. Thingの設定

2台のThingの設定をします。2台で設定の仕方はほとんど同じなので、1台分(RobotArm_Thing)のみ説明します。Switch_Thingについても同様に設定しましょう。

利用パッケージ等のインストール

aws-iot-device-sdk-cppをダウンロードしてインストールできるように準備します。cmake, libssl-devを入れます。そのために/etc/apt/sources.list.d/raspi.listを編集したりgpgコマンドを入力したりする必要があります(GreenGrass_Coreノードと同じように作業すればOKです)。その他、サンプルコードがgitにあるためgitコマンドをインストールしておきます。

pi@raspberrypi: sudo apt-get install git
aws-iot-device-sdk-cppのインストール、設定

 上記準備ができたら、サンプルコードを持ってきてコンパイルします。

pi@raspberrypi: git clone https://github.com/aws/aws-iot-device-sdk-cpp.git
pi@raspberrypi: cd aws-iot-device-sdk-cpp/
pi@raspberrypi: mkdir build
pi@raspberrypi: cd build/
pi@raspberrypi: cmake ../.
pi@raspberrypi: make robot-arm-sample

AWS IoTコンソールで端末登録した際に生成され、手元端末にダウンロードしておいた証明書と秘密鍵、root証明書をラズパイの以下のところに置きます。

pi@raspberrypi:~/aws-iot-device-sdk-cpp/build/bin/certs/robotArm $ ls -l
total 16
-rw-r--r-- 1 pi pi 1224 Jun 21 16:36 aaaaaaaaaa-certificate.pem.crt
-rw-r--r-- 1 pi pi 1679 Jun 21 16:36 aaaaaaaaaa-private.pem.key
-rw-r--r-- 1 pi pi  451 Jun 21 16:36 aaaaaaaaaa-public.pem.key
-rw-r--r-- 1 pi pi 1758 Jun 21 16:40 root-ca.pem
pi@raspberrypi:~/aws-iot-device-sdk-cpp/build/bin/certs/robotArm $

/home/pi/aws-iot-device-sdk-cpp/build/bin/config/RobotArmConfig.jsonに、証明書等の場所を指定します。

  • /home/pi/aws-iot-device-sdk-cpp/build/bin/config/RobotArmConfig.json (太字部分が編集したところ)
{
"endpoint": "greengrass.iot.us-west-2.amazonaws.com",
"mqtt_port": 8883,
"https_port": 443,
"greengrass_discovery_port": 8443,
"root_ca_relative_path": "certs/robotArm/root-ca.pem",
"device_certificate_relative_path": "certs/robotArm/aaaaaaaaaaa-certificate.pem.crt",
"device_private_key_relative_path": "certs/robotArm/aaaaaaaaaa-private.pem.key",
"tls_handshake_timeout_msecs": 60000,
"tls_read_timeout_msecs": 2000,
"tls_write_timeout_msecs": 2000,
"aws_region": "",
"aws_access_key_id": "",
"aws_secret_access_key": "",
"aws_session_token": "",
"client_id": "RobotArm_Thing",
"thing_name": "RobotArm_Thing",
"is_clean_session": true,
"mqtt_command_timeout_msecs": 20000,
"keepalive_interval_secs": 30,
"minimum_reconnect_interval_secs": 1,
"maximum_reconnect_interval_secs": 128,
"maximum_acks_to_wait_for": 32,
"action_processing_rate_hz": 5,
"maximum_outgoing_action_queue_length": 32,
"discover_action_timeout_msecs": 300000
}

これですべての準備完了!

サンプルの動かし方

ではサンプルを動かしてみましょう。まずはGreengrass_coreに、ThingsやLambda関数などの設定をデプロイします。AWS IoTコンソール上で作業します。この画面は既に何回かデプロイした後ですが、初回には履歴が表示されていないと思います。

“アクション”のところのデプロイコマンドを発行すると、30秒ほどで、ステータスのところが「デプロイメントが正常に…」と変わります。この時点で、Greengrass_coreノード(ラズパイ)上で例えば/greengrass/lambdaを見てみると自分が先に設定したLambda関数がダウンロードされているのが確認できます(下記の下2行)。

pi@raspberrypi:/greengrass/lambda $ ls -l
total 36
drwxr-xr-x 2 ggc_user ggc_group 4096 Jun  6 02:52 arn:aws:lambda:::function:GGConnManager
drwxr-xr-x 2 ggc_user ggc_group 4096 Jun  6 02:52 arn:aws:lambda:::function:GGDeviceCertificateManager
drwxr-xr-x 2 ggc_user ggc_group 4096 Jun  6 02:52 arn:aws:lambda:::function:GGIPDetector:1
drwxr-xr-x 2 ggc_user ggc_group 4096 Jun  6 02:52 arn:aws:lambda:::function:GGRouter
drwxr-xr-x 2 ggc_user ggc_group 4096 Jun  6 02:52 arn:aws:lambda:::function:GGShadowService
drwxr-xr-x 2 ggc_user ggc_group 4096 Jun  6 02:52 arn:aws:lambda:::function:GGShadowSyncManager
drwxr-xr-x 2 ggc_user ggc_group 4096 Jun  6 02:52 arn:aws:lambda:::function:GGTES
drwxr-xr-x 5 ggc_user ggc_group 4096 Jun 21 16:21 arn:aws:lambda:us-west-2:yyyyyyyyyyyyy:function:messageLambda:1
drwxr-xr-x 5 ggc_user ggc_group 4096 Jun 21 16:21 arn:aws:lambda:us-west-2:yyyyyyyyyyyyy:function:uptimeLambda:1
pi@raspberrypi:/greengrass/lambda $

さて、端末(RobotArm_Thing)で、robot-arm-sampleコマンドを実行します。

pi@raspberrypi:~/aws-iot-device-sdk-cpp/build/bin $ ./robot-arm-sample
[INFO] Fri Jun 23 15:50:14 2017
:413 [Discover] [1995509760] Discover Read from Network Succeeded!
[INFO] Fri Jun 23 15:50:14 2017
:414 [Sample - RobotArm] [1995509760] GGC connectivity information found for this Device! 400

[INFO] Fri Jun 23 15:50:14 2017
:416 [Sample - RobotArm] [1995509760] Attempting Connect with:
GGC Endpoint : 192.168.201.199
GGC Endpoint Port : 8883

[INFO] Fri Jun 23 15:50:14 2017
:416 [Sample - RobotArm] [1995509760] Using CA at : /home/pi/greengrass_things/aws-iot-device-sdk-cpp/build/bin/xxxxxxxxxxx-0236-4d3f-9620-ae95279b8ff3_root_ca1.pem

[INFO] Fri Jun 23 15:50:14 2017
:941 [Network Read] [1981764688] Network Connect Response. Success : SDK Code 0.
[INFO] Fri Jun 23 15:50:15 2017
:441 [Sample - RobotArm] [1995509760] Connected to GGC arn:aws:iot:us-west-2:yyyyyyyyyyyyy:thing/GreengrassTest4_Core in Group xxxxxxxxxx-0236-4d3f-9620-ae95279b8ff3!!

Sending Inital State -------
{"state":{"reported":{"myState":"off"}}}
Waiting for an update!

無事にGGC(Greengrass_Core)と接続でき、待ち状態になっていることがわかります。

この状態でもう一台の端末(Switch_Thing)で、以下のコマンドを実行します。

pi@raspberrypi:~/aws-iot-device-sdk-cpp/build/bin $ ./switch-sample
[INFO] Fri Jun 23 15:55:00 2017
:133 [Discover] [1995587584] Discover Read from Network Succeeded!
[INFO] Fri Jun 23 15:55:00 2017
:133 [Sample - Switch] [1995587584] GGC connectivity information found for this Device!!

[INFO] Fri Jun 23 15:55:00 2017
:135 [Sample - Switch] [1995587584] Attempting Connect with:
GGC Endpoint : 192.168.201.199
GGC Endpoint Port : 8883

[INFO] Fri Jun 23 15:55:00 2017
:135 [Sample - Switch] [1995587584] Using CA at : /home/pi/aws-iot-device-sdk-cpp/build/bin/xxxxxxxxxxx-0236-4d3f-9620-ae95279b8ff3_root_ca1.pem

[INFO] Fri Jun 23 15:55:01 2017
:419 [Network Read] [1981842512] Network Connect Response. Success : SDK Code 0.
[INFO] Fri Jun 23 15:55:01 2017
:919 [Sample - Switch] [1995587584] Connected to GGC arn:aws:iot:us-west-2:yyyyyyyyyyy:thing/GreengrassTest4_Core in Group xxxxxxxxxx-0236-4d3f-9620-ae95279b8ff3!!

Please enter 1 (turn on) or 0 (turn off) to control the robot arm, q to quit:

こちらもGGCと接続できています。この状態で、”1″もしくは”0″を入力すると…

RobotArm_Thing側に状態が伝わっています!

-- Published state to /topic/metering (Should be routed to uptimelambda!) --
------- Robot Arm State --------
on
-- Published state to /topic/metering (Should be routed to uptimelambda!) --
------- Robot Arm State --------
off
-- Published state to /topic/metering (Should be routed to uptimelambda!) --
------- Robot Arm State --------
on

やりました!

このサンプルではLambda関数を経由してクラウド側とも状態を交換しているので、AWS IoTコンソール上でテスト用のMQTTクライアントを起動し、/topic/meteringに加入(subscript)すると、状態が通知されて見えます。

簡単な分析、感想

基本的な動作は確認できたので、もう少し挙動を追ってみました。

Greengrass_Coreとクラウド間の通信が切れてもOKか?

ちょっと荒っぽいやり方ですが、GGCノードで以下のようにデフォルト経路を消して、AWS IoTと通信できない状態にしてみます。

pi@raspberrypi:/greengrass $ sudo route del default gw 192.168.201.254
pi@raspberrypi:/greengrass $ netstat -r
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
^C
pi@raspberrypi:/greengrass $

こういう状態ですね。

この状態でも、RobotArm_ThingとSwitch_Thingの間は通信できていることを確認しました。(端末動作画面は代わり映えしないので載せていません。)

この時、当然ですが、クラウド側とは切れているため、AWS IoTコンソール上のMQTTクライアントでは状態が通知されません。

Greengrass_Coreとクラウド間の通信が復旧したら?

GGCノードを通信できるように復旧させると、しばらくしてAWS IoTコンソール上でも状態が受信できる様になることを確認しました。ただ復旧には少し時間がかかるようです。このあたりは、greengrass_coreのconfigで調整可能ではないかと思われるのですが、まだ細かいところを確認できていません。

今回のテストでは、GGCノードのクラウドとの通信を切って復旧させたときにGGCノードのIPアドレスが変わりました(図における192.168.201.199が別のアドレスに)。その時、端末側ではGGCノードとの通信ができていないことを検出しており、しかも変化に追従していっています。優秀ですね。端末はクラウド側とも通信しており、GGCノードの状態(接続先IPアドレス)を動的に受け取って、対応しているように見えます(まだ詳細は追えていません)。

[WARN] Fri Jun 23 16:11:57 2017
:355 [Shadow] [1981764688] Update request rejected for shadow : RobotArm_Thing
[INFO] Fri Jun 23 16:12:31 2017
:343 [KeepAlive] [1971319888] Initial value of reconnect timer : 1!!
[INFO] Fri Jun 23 16:12:31 2017
:344 [KeepAlive] [1971319888] Max backoff value : 128!!
[INFO] Fri Jun 23 16:12:31 2017
:344 [KeepAlive] [1971319888] Attempting Reconnect
[ERROR] Fri Jun 23 16:14:41 2017
:762 [OpenSSL Wrapper] [1971319888] TCP Connection error
[ERROR] Fri Jun 23 16:14:41 2017
:763 [KeepAlive] [1971319888] Reconnect failed. TCP Error occurred while opening a socket : SDK Code -300.
[INFO] Fri Jun 23 16:14:41 2017
:763 [KeepAlive] [1971319888] Current value of reconnect timer : 1!!
[INFO] Fri Jun 23 16:14:41 2017
:763 [KeepAlive] [1971319888] Updated value of reconnect timer : 2!!
[INFO] Fri Jun 23 16:14:43 2017
:763 [KeepAlive] [1971319888] Attempting Reconnect
[INFO] Fri Jun 23 16:14:51 2017
:257 [Network Read] [1981764688] Network Connect Response. Success : SDK Code 0.

-- Published state to /topic/metering (Should be routed to uptimelambda!) --
------- Robot Arm State --------
on
-- Published state to /topic/metering (Should be routed to uptimelambda!) --
------- Robot Arm State --------
off
-- Published state to /topic/metering (Should be routed to uptimelambda!) --
------- Robot Arm State --------
on

なお、ログは取れていませんが、別のタイミングでテストしたときは、端末側でコマンド(robot-arm-sample, switch-sample)が強制終了してしまうケースもありました。何らかタイムアウトが発生したのではないかと想定されますが(端末側でクラウドと通信できなくなったなど)、追えていません。

アンデプロイ(撤収)できない

現状では、GGCノードにデプロイした構成やLambda関数はアンデプロイできないようです。(更新はできます。)

Thingも起動時にAWS IoT(クラウド)への接続が必須

Thingノードの動作状況やConfig(このページの上の方にあります)を見る限り、Thingノードは起動時にはクラウドへの接続が必須のようです。クラウドに接続して、自分が接続しに行くGGCノードの接続先情報を取ってくる構造になっているようです。Configにも、接続先GGCノードの情報を明示的に記入する項目がありません。

これはすなわち、ネット接続的にスタンドアローンなThingノードは構成できない、ということを意味するように思えます。ここは考え方が現れるところですね。Greengrassの思想としては、GGCはクラウド側の機能(特にLambda関数の実行)をエッジ側に張り出させることを主眼としていて、あくまでもThingノードはAWS IoTのエコシステム内に収容するものだ、ということなのかなと推測しています(エッジ側にクラウド側から見えない端末が存在することを許容しない)。もちろんこれにはメリットもあって、例えば上記のように動的な構成変更に追従可能だったりするので、簡単に是非を言えるものではないと思います。

このあたりは面白いところなので、また今の時点ではまだ調査が十分ではないので、もう少し継続して見ていきたいところです。

参考にしたWebページなど

以下のページを参考にしました。ありがとうございます。

おわりに

今回はAWS Greengrassをとりあえず試した程度ですが、さくらインターネット研究所では今後も、エッジコンピューティング関連技術の調査・評価を継続していく予定です。