AWS re:Invent 2017 では今年も多数の新サービスが発表されましたね。その中には IoT や AI 関連のものも多く、 エッジデバイス上で Machine Learning の推論が実行できる AWS Greengrass ML Inference などはとても興味深いです。が、そもそも Greengrass に今まで触ったことがなかったので、今更ではありますが Raspberry Pi で Greengrass を動かしてみました。基本的に下記の公式ドキュメントのチュートリアルの実行です。
Raspberry Pi での環境設定
Raspberry Pi の基本的な環境構築は終わっているものとして、 Greengrass を動かすための設定を行います。まずは Greengrass Core 用の Linux ユーザとグループを作成し、 sqlite3 をインストールします。
pi@raspberrypi:~ $ sudo adduser --system ggc_user Adding system user `ggc_user' (UID 117) ... Adding new user `ggc_user' (UID 117) with group `nogroup' ... Creating home directory `/home/ggc_user' ... pi@raspberrypi:~ $ pi@raspberrypi:~ $ sudo addgroup --system ggc_group Adding group `ggc_group' (GID 122) ... Done. pi@raspberrypi:~ $ pi@raspberrypi:~ $ sudo apt-get install sqlite3 Reading package lists... Done Building dependency tree Reading state information... Done Suggested packages: sqlite3-doc The following NEW packages will be installed: sqlite3 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 99.6 kB of archives. After this operation, 139 kB of additional disk space will be used. Get:1 http://mirrordirector.raspbian.org/raspbian/ jessie/main sqlite3 armhf 3.8.7.1-1+deb8u2 [99.6 kB] Fetched 99.6 kB in 1s (91.6 kB/s) Selecting previously unselected package sqlite3. (Reading database ... 104790 files and directories currently installed.) Preparing to unpack .../sqlite3_3.8.7.1-1+deb8u2_armhf.deb ... Unpacking sqlite3 (3.8.7.1-1+deb8u2) ... Processing triggers for man-db (2.7.5-1~bpo8+1) ... Setting up sqlite3 (3.8.7.1-1+deb8u2) ... pi@raspberrypi:~ $
Greengrass Core では起動時にOSでハードリンク/ソフトリンクの保護が有効か確認しているため、この保護を有効にしておきます。 /etc/sysctl.d/98-rpi.conf
に設定を追加します。追加前後の差分は下記の通りです。
pi@raspberrypi:~ $ diff /etc/sysctl.d/98-rpi.conf.20171220 /etc/sysctl.d/98-rpi.conf 2a3,4 > fs.protected_hardlinks = 1 > fs.protected_symlinks = 1 pi@raspberrypi:~ $
設定を追加したら一度再起動します。
pi@raspberrypi:~ $ sudo reboot
再起動したら下記のように確認するとハードリンク/ソフトリンクの保護が有効になっていることがわかります。
pi@raspberrypi:~ $ sudo sysctl -a | grep 'fs.protected' fs.protected_hardlinks = 1 fs.protected_symlinks = 1 sysctl: reading key "net.ipv6.conf.all.stable_secret" sysctl: reading key "net.ipv6.conf.default.stable_secret" sysctl: reading key "net.ipv6.conf.eth0.stable_secret" sysctl: reading key "net.ipv6.conf.lo.stable_secret" sysctl: reading key "net.ipv6.conf.wlan0.stable_secret"
Greengrass Group と Greengrass Core の作成
Greengrass のデバイスには Core デバイスと、 Core デバイスに接続するそれ以外のデバイスがあり、Core デバイスが AWS IoT や Greengrass のクラウドサービスと通信します。また、それらのデバイスと設定情報をひとまとまりにしたものが Greengrass Group になります。まずはコンソールから Greengrass Group を作成しますが、その前にコンソールから Greengrass を操作するための権限を追加しておきます。今回はお試しということでとりあえず Greengrass へのフルアクセス権限を追加してしまいます。
それでは Greengrass Group を作成します。AWS IoT のコンソールのメニューから Greengrass
を選択します。
ようこそ画面が表示されるので、「Greengrass グループの定義」の 今すぐ始める
をクリックします。
グループの作成方法の選択画面が表示されますので、 簡単な作成の使用
を選択します。この方法だと Core デバイスがクラウドサービスにアクセスするために必要な証明書やキーペアの作成なども自動で行ってくれます。
グループ名の入力画面で任意のグループ名を設定します。
続けて Core デバイスの名前も決めます。デフォルトだとグループ名に _Core がついたものになっているので今回はそのまま使用します。
実行する内容が表示されるので、 グループとコアの作成
をクリックします。
Group と Core が作成され、証明書のダウンロード画面が表示されますので、ダウンロードしておきます。
また、同じ画面で Greengrass ソフトウェアパッケージもダウンロードできますので、CPUアーキテクチャとして ARMv7l を選択し、ダウンロードして、 完了
をクリックします。
これで Greengrass Group と Greengrass Core の作成は完了です。
Greengrass Core のインストール
Raspberry Pi に先ほどダウンロードした Greengrass ソフトウェアパッケージをインストールします。ソフトウェアパッケージを Raspberry Pi 上に配置したら展開します。
pi@raspberrypi:~ $ sudo tar zxf greengrass-linux-armv7l-1.3.0.tar.gz -C / pi@raspberrypi:~ $ pi@raspberrypi:~ $ ls -l /greengrass/ total 16 drwxr-xr-x 2 nobody 99 4096 Nov 21 08:09 certs drwxr-xr-x 2 nobody 99 4096 Nov 21 08:09 config drwxr-xr-x 5 nobody 99 4096 Nov 21 08:09 ggc drwxr-xr-x 3 nobody 99 4096 Nov 21 08:09 ota
Lambda の cgroup を自動的に設定するために、 /etc/fstab
に下記設定を追加します。
cgroup /sys/fs/cgroup cgroup defaults 0 0
追加後の fstab は下記のようになります。設定を追加したら一度再起動しておきます。
pi@raspberrypi:~ $ tail /etc/fstab proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 2 /dev/mmcblk0p2 / 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
続いて証明書を配置します。先ほど展開したディレクトリ内の certs ディレクトリに、Versign からルートCA証明書をダウンロードして配置します。
pi@raspberrypi:/greengrass/certs $ pwd /greengrass/certs pi@raspberrypi:/greengrass/certs $ pi@raspberrypi:/greengrass/certs $ sudo wget http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem -O root-ca-cert.pem --2017-12-20 15:30:39-- http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem Resolving www.symantec.com (www.symantec.com)... 72.247.61.29 Connecting to www.symantec.com (www.symantec.com)|72.247.61.29|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 1758 (1.7K) [text/plain] Saving to: ‘root-ca-cert.pem’ root-ca-cert.pem 100%[===========================================================================================================================================>] 1.72K --.-KB/s in 0s 2017-12-20 15:30:39 (37.7 MB/s) - ‘root-ca-cert.pem’ saved [1758/1758]
続けて、 Group と Core 作成時にダウンロードした証明書の圧縮ファイルに含まれる証明書とプライベートキーを同じディレクトリに配置します。
pi@raspberrypi:~ $ tar zxf dbb10e0817-setup.tar.gz
pi@raspberrypi:~ $ ls certs/
dbb10e0817.cert.pem dbb10e0817.private.key dbb10e0817.public.key
pi@raspberrypi:~ $
pi@raspberrypi:~ $ sudo cp certs/dbb10e0817.private.key /greengrass/certs/.
pi@raspberrypi:~ $ sudo cp certs/dbb10e0817.cert.pem /greengrass/certs/.
次に、コンソールから Greengrass 用のサービスロールを作成します。 IAM のコンソールから ロールの作成
をクリックします。
サービスのリストから Greengrass を選択して 次のステップ
をクリックします。
ポリシーの選択画面で AWSGreengrassResourceAccessRolePolicy を選択して 次のステップ
をクリックします。
任意のロール名を入力して ロールの作成
をクリックします。
ロールが作成されたら ARN を記録しておきます。
続いて今作成したサービスロールをアカウントに紐づけます。 Mac 上から AWS CLI で下記のようにコマンドを実行します。
Greengrass $ aws greengrass associate-service-role-to-account --role-arn arn:aws:iam::365361468908:role/Greengrass 2017-12-20T15:53:26Z
最後に Raspberry Pi 上の Greengrass 設定ファイルを下記のように編集します。各証明書などへのパスはフルパスではなくファイル名だけでOKです。
pi@raspberrypi:/greengrass/ggc/packages/1.3.0 $ cat /greengrass/config/config.json { "coreThing": { "caPath": "root-ca-cert.pem", "certPath": "dbb10e0817.cert.pem", "keyPath": "dbb10e0817.private.key", "thingArn": "arn:aws:iot:ap-northeast-1:365361468908:thing/MyGroup_Core", "iotHost": "xxxxxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com", "ggHost": "greengrass.iot.ap-northeast-1.amazonaws.com" }, "runtime": { "cgroup": { "useSystemd": "yes" } }, "managedRespawn": false }
Greengrass Core の起動
それでは Raspberry Pi 上の Greengrass Core を起動します。 Greengrass のソフトウェアパッケージのディレクトリ(今回は /greengrass/ggc/packages/1.3.0
)で下記のようにコマンドを実行します。
pi@raspberrypi:/greengrass/ggc/packages/1.3.0 $ sudo ./greengrassd start Setting up greengrass daemon Validating hardlink/softlink protection 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 successfully started with PID: 1917
成功するとデーモンが起動します。
pi@raspberrypi:/greengrass/ggc/packages/1.3.0 $ ps aux | grep greengrass | grep -v grep root 1304 0.7 1.4 940632 13900 pts/0 Sl Dec20 0:38 /greengrass/ggc/packages/1.3.0/bin/daemon -core-dir=/greengrass/ggc/packages/1.3.0 -port=8000 -connectionManager=true -router=true -shadow=true -shadowSync=true -tes=true -deviceCertificateManager=true ggc_user 1472 0.8 1.1 31308 10796 ? Ssl Dec20 0:45 python2.7 /runtime/python2.7/lambda_runtime.py --handler=greengrassHelloWorld.function_handler
Lambda Function の作成
Greengrass Core デバイスで動作させるための Lambda Function を作成します。 Lambda のコンソールから 関数の作成
をクリックします。
今回はあらかじめ用意されているサンプルを使用しますので、「設計図」から「greengrass-hello-world」を選択して 設定
をクリックします。
任意の Function 名とロールを選択します。今回は以前作成していたロールを使用していますが、作成していなかった場合は新たに作成します。
Core デバイスで Lambda Function を実行するには新しいバージョンを発行しておく必要があるので、「アクション」メニューから 新しいバージョンを発行
をクリックします。
バージョンの説明を入力して 発行
をクリックします。
Greengrass Group に Lambda Function を追加
作成した Lambda Function を Greengrass Group に追加します。 Greengrass Group のコンソールの Lambda メニューから、 最初の Lambda を追加する
をクリックします。
Lambda の追加方法の選択画面が表示されますので、 既存の Lambda の使用
を選択します。
Lambda Function の選択画面が表示されますので、先ほど作成した Lambda Function を選択して 次へ
をクリックします。
先ほど発行したバージョンを選択して 完了
をクリックします。
Lambda Function が追加されたら、設定を変更するために 設定の編集
をクリックします。
設定項目の中の「Lambda のライフサイクル」の項目で「存続期間が長く無制限に稼働する関数にする」を選択して 更新
をクリックします。
Greengrass Group にサブスクリプションを追加
Greengrass Core が MQTT プロトコルでメッセージをやりとりするためのサブスクリプションを追加します。サブスクリプションは、メッセージの送信元であるソース、メッセージの送信先であるターゲット、それとトピックから構成されます。 Greengrass のサブスクリプションメニューから、 最初のサブスクリプションを追加
をクリックします。
ソースの選択で先ほど作成した Lambda Function を選択し、ターゲットの選択では IoT Cloud を選択して 次へ
をクリックします。
今回は対象のトピックを hello/world に限定するため、「オプションのトピックフィルター」に hello/world を入力して 次へ
をクリックします。
最後に 完了
をクリックしてサブスクリプションの追加は完了です。
Greengrass Group のデプロイ
ここまででクラウド上での Greengrass Group の設定は完了したので、これを Greengrass Core デバイスにコピーします。 Greengrass Group のデプロイのコンソールのアクションから デプロイ
を選択します。
検出方法の設定画面になりますので、 自動検出
を選択します。
これまでの設定が正しく行われ、 Core デバイス上でデーモンが正しく稼働していれば、少し経つとデプロイが完了します。
動作確認
それでは Greengrass Core デバイス上で Lambda Function が正しく実行されているか確認します。AWS IoT コンソールから「テスト」を選択し、 hello/world トピックにサブスクライブします。
Lambda Function が正しく実行されていれば、下記のようにトピックにメッセージが発行されていきます。
まとめ
今回はチュートリアルの内容をそのまま追っただけになってしまいましたが、 Greengrass Core デバイス(今回は Raspberry Pi)上で Lambda Function を動かせることが確認できました。今回はここまでで長くなってしまいましたが、まだ Core デバイスに接続している他のデバイスとの連携は試せていないので、次回以降で試してみたいと思います。