NVIDIA Jetson TX2でGreengrassを動かしてみた

NVIDIAのJetson TX2をGreengrass用にセットアップしてLambda(Python 2.7)を動かします。
2018.08.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

まえがき

Jetson TX2の上でGreengrassを動かします。具体的にはLambda(Python2.7)でHello Worldをやってみます。 この作業を行う場合は、2時間程時間を確保しておく事をおすすめします。 モジュール 1: Greengrass の環境設定 - AWS Greengrass 上記のドキュメントを参考に進めました。

やってみた

作業はSSHなど使用せず、Jetson上で直接行ってください。SSHする場合は事前にX11の設定をした上で作業しましょう。

要件の確認

AWS Greengrass(以降、Greengrass)の要件はこちらで確認できます。 AWS Greengrass とは - AWS Greengrass

Githubにチェックするためのスクリプトが公開されているので確認してみましょう。

cd ~/
git clone https://github.com/aws-samples/aws-greengrass-samples.git
cd aws-greengrass-samples
cd greengrass-dependency-checker-GGCv1.5.0 
sudo ./check_ggc_dependencies

実行した結果

==========================Checking script dependencies==============================
The device has all commands required for the script to run.

========================Dependency check report for GGC v1.5=========================
System configuration:
Kernel architecture: aarch64
Init process: /lib/systemd/systemd
Kernel version: 4.4
C library: Ubuntu GLIBC 2.23-0ubuntu10
C library version: 2.23
Directory /var/run: Present
/dev/stdin: Found
/dev/stdout: Found
/dev/stderr: Found

--------------------------------Kernel configuration--------------------------------
Kernel config file: /proc/config.gz

Namespace configs:
CONFIG_IPC_NS: Enabled
CONFIG_UTS_NS: Enabled
CONFIG_USER_NS: Not enabled
CONFIG_PID_NS: Enabled

Cgroup configs:
CONFIG_CGROUP_DEVICE: Not enabled
CONFIG_CGROUPS: Enabled
CONFIG_MEMCG: Not enabled

Other required configs:
CONFIG_POSIX_MQUEUE: Not enabled
CONFIG_OVERLAY_FS: Not enabled
CONFIG_HAVE_ARCH_SECCOMP_FILTER: Enabled
CONFIG_SECCOMP_FILTER: Enabled
CONFIG_KEYS: Not enabled
CONFIG_SECCOMP: Enabled

------------------------------------Cgroups check-----------------------------------
Cgroups mount directory: /sys/fs/cgroup

Devices cgroup: Not enabled
Memory cgroup: Not enabled

----------------------------Commands and software packages--------------------------
Python version: 2.7.12
NodeJS 6.10: Not found
Java 8: Not found
OpenSSL version: 1.0.2
wget: Present
realpath: Present
tar: Present
readlink: Present
basename: Present
dirname: Present
pidof: Present
df: Present
grep: Present
umount: Present

---------------------------------Platform security----------------------------------
Hardlinks_protection: Enabled
Symlinks protection: Enabled

-----------------------------------User and group-----------------------------------
User ggc_user: Not found
Group ggc_group: Not found

------------------------------------Results-----------------------------------------
Note:
1. It looks like the kernel uses 'systemd' as the init process. Be sure to set the
'useSystemd' field in the file 'config.json' to 'yes' when configuring Greengrass core.

Missing optional dependencies:
1. The 'devices' cgroup is not enabled on the device.

Greengrass lambdas with Local Resource Access(LRA) configurations will not be allowed
to open device files.

2. Could not find the binary 'nodejs6.10'.

If NodeJS 6.10 or later is installed on the device, name the binary 'nodejs6.10' and
add its parent directory to the PATH environment variable. NodeJS 6.10 or later is
required to execute NodeJS lambdas on Greengrass core.

3. Could not find the binary 'java8'.

If Java 8 or later is installed on the device name the binary 'java8' and add its
parent directory to the PATH environment variable. Java 8 or later is required to
execute Java lambdas on Greengrass core.

Missing required dependencies:
1. The kernel is missing the following required configs:
CONFIG_USER_NS
CONFIG_CGROUP_DEVICE
CONFIG_MEMCG
CONFIG_POSIX_MQUEUE
CONFIG_OVERLAY_FS
CONFIG_KEYS

2. The 'memory' cgroup is not enabled on the device.
Greengrass will fail to set the memory limit of user lambdas.

3. User ggc_user, required to run Greengrass core, is not present on the device.
Refer to the official Greengrass documentation to fix this.

4. Group ggc_group, required to run Greengrass core, is not present on the device.
Refer to the official Greengrass documentation to fix this.

----------------------------------Exit status---------------------------------------
Either the script failed to verify all dependencies or the device is missing one or
more of the required dependencies for Greengrass version 1.5.

Refer to the 'Errors' and 'Missing required dependencies' sections under 'Results'
for details.

Resultsの部分を確認しましょう。色々と足りていないですね。 今回はLambdaでPythonが動けばいいので、JavaとNodeJSはインストールしません。

カーネル設定の確認

diff <(zcat /proc/config.gz | grep -e CONFIG_KEYS -e CONFIG_POSIX_MQUEUE -e CONFIG_OF_OVERLAY -e CONFIG_OVERLAY_FS -e CONFIG_HAVE_ARCH_SECCOMP_FILTER -e CONFIG_SECCOMP_FILTER -e CONFIG_SECCOMP -e CONFIG_DEVPTS_MULTIPLE_INSTANCES -e CONFIG_IPC_NS -e CONFIG_NET_NS -e CONFIG_UTS_NS -e CONFIG_USER_NS -e CONFIG_PID_NS -e CONFIG_CGROUPS -e CONFIG_MEMCG -e CONFIG_CGROUP_FREEZER -e CONFIG_CGROUP_DEVICE) <(echo "# CONFIG_POSIX_MQUEUE is not set
CONFIG_CGROUPS=y
CONFIG_CGROUP_FREEZER=y
# CONFIG_CGROUP_DEVICE is not set
# CONFIG_MEMCG is not set
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
# CONFIG_USER_NS is not set
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y
CONFIG_SECCOMP=y
# CONFIG_OF_OVERLAY is not set
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
# CONFIG_OVERLAY_FS is not set
# CONFIG_KEYS is not set")

何も出力されなければカーネル設定は変更する必要がありません。

パフォーマンスの設定

パフォーマンス設定を変更します。一時的な変更を行った後、Crontabに記載して設定を永続化しておきましょう。

sudo su -
nvpmodel -q
nvpmodel -m 0
echo 255 > /sys/kernel/debug/tegra_fan/target_pwm

crontab -e
#下記コードを追記
exit
@reboot nvpmodel -q
@reboot nvpmodel -m 0
@reboot echo 255 > /sys/kernel/debug/tegra_fan/target_pwm

カーネルの再構築

ここから先の作業はGUIは必要です。Jetsonにディスプレイ他を接続して作業してください。 再構築の為のスクリプトを準備します。

cd /
sudo su - #以降rootで作業します。
sudo wget --no-check-certificate https://github.com/jetsonhacks/buildJetsonTX2Kernel/archive/vL4T28.1.tar.gz
sudo tar zxvf vL4T28.1.tar.gz
cd ~/buildJetsonTX2Kernel-vL4T28.1
cat << EOF > getKernelSources.sh_patchfile
--- /scripts/getKernelSources.sh
+++ /scripts/getKernelSources.sh
@@ -1,12 +1,15 @@
 #!/bin/bash
 apt-add-repository universe
 apt-get update
-apt-get install qt5-default pkg-config -y
+apt-get install qt5-default pkg-config libncurses5-dev libssl-dev -y
 cd /usr/src
 wget http://developer.download.nvidia.com/embedded/L4T/r28_Release_v1.0/BSP/source_release.tbz2
 tar -xvf source_release.tbz2 sources/kernel_src-tx2.tbz2
 tar -xvf sources/kernel_src-tx2.tbz2
 cd kernel/kernel-4.4
+make clean
 zcat /proc/config.gz > .config
-make xconfig
+echo "type something to continue"
+read
+make menuconfig
EOF
patch -p1 < getKernelSources.sh_patchfile

実行します。

./getKernelSources.sh
#"type something to continue" (続行するには何か入力してください) というメッセージが表示されたら、Ctrl + Z キーを押してスクリプトをバックグラウンドで実行します。
vi /usr/src/kernel/kernel-4.4/security/keys/Kconfig
#KEYS と PERSISTENT_KEYRINGS との間に下記のコードを追加します。(コメントアウトは解除して貼り付けてください)
cd /usr/src/kernel/kernel-4.4/ #Kconfigの変更が終わったら実行します
fg
# Enterキーを押す
fg
# ロード可能モジュールのサポートの設定をします。TUI画面が開くので下記の画像を参考に設定します。
make xconfig
# カーネルコンフィグを設定します。GUIが開くので下記画像を参考に設定します。
cd /buildJetsonTX2Kernel-vL4T28.1
./makeKernel.sh #カーネル再構築
./copyImage.sh #既存カーネルを上書き

Kconfig

config KEYS_COMPAT
    def_bool y
    depends on COMPAT && KEYS

ロード可能モジュールのサポート

Enable loadable module support(最初から*はついています)とSelectにカーソルを合わせてEnterキーを押します。

Module signature verificationにカーソルを合わせてSpaceキーを押します。(*が付きます。) Saveにカーソルを合わせてEnterキーを押します。

OKにカーソルを合わせてEnterキーを押します。

Exitにカーソルを合わせてEnterキーを押します。これを3回行います。

カーネルコンフィグ

カーネルコンフィグを設定します。

CONFIG_POSIX_MQUEUE

CONFIG_OF_OVERLAY CONFIG_OVERLAY_FS

CONFIG_USER_NS

CONFIG_MEMCG

CONFIG_CGROUP_DEVICE

設定が完了したら、保存してから終了します。

ユーザー・グループの追加

Greengrass用のユーザー・グループを追加します。

sudo adduser --system ggc_user
sudo addgroup --system ggc_group

Greengrassグループ作成

Greengrass グループにアクセスしてグループを作成しましす。

推奨される簡単な作成の使用でグループを作成します。

グループに名前を付けます。任意の名前でOKです。
あるプロジェクト使っている共有のアカウントなのでオーナーがvわかりやすいように自分の名前で作成しておきました。

デバイスの名前を付けます。任意の名前でOKです。
デバイス名称と連番で作成しました。

グループ作成を実行します。

セキュリティリソースをダウンロードします。これは後ほどJetsonにscpで転送します。

Greengrassソフトウェアをダウンロードします。これも後ほどJetsonにscpで転送します。

完了するとグループの画面が表示されます。

Greengrassの起動

GreengrassコアバイナリファイルとセキュリティリソースをJetsonに転送します。

local device

$ cd <<path-to-downloaded-files>>
$ sudo scp ./greengrass-linux-aarch64-1.6.0.tar.gz nvidia@<<Jetson_TX2_ip_address>>:/home/nvidia/
$ sudo scp ./<<GUID>>-setup.tar.gz  nvidia@<<Jetson_TX2_ip_address>>:/home/nvidia/

ここからは、SSHでJetsonに接続して作業します。
転送した圧縮ファイルをルートフォルダに解凍します。

jetson

$ sudo tar -zxvf greengrass-linux-aarch64-1.6.0.tar.gz -C /
$ sudo tar -zxvf bb5c35dffe-setup.tar.gz -C /greengrass

rootCAをダウンロードします。

jetson

$ cd /greengrass/certs/
$ sudo curl -o root.ca.pem http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem

Greengrassを起動します。

jetson

$ cd /greengrass/ggc/core/
$ sudo ./greengrassd start

表示されたPID番号で実際に動作しているか確認します。

jetson

$ ps aux | grep <<PID_number>>

Lambda関数の作成

サンプルでHello world!し続けるLambda関数を作成します。

Lambda Management Consoleにアクセスして関数を新規作成します。

設計図を選択して、greengrassで検索します。サンプルのgreengrass-hello-worldを選択して設定をクリックします。

関数名とロールを決めます。
ロールはAWS管理ポリシーのAWSLambdaBasicExecutionRoleがアタッチされているものを使用してください。 この画面でロールを新規作成してもOKです。

そのまま関数の作成をクリックして完了します。

GreengrassからLambda関数を参照できるようにします。
アクションから新しいバージョンを発行を実行します。

バージョンの説明を入力して発行します。

アクションからエイリアスの作成を実行します。

名前とバージョンを指定して作成を実行します。

GreengrassのLambda関数の設定

再びGreengrass グループから操作します。
メニューのLambdaを選択します。

最初のLambdaを追加するをクリックします。

既存のLambdaの使用をクリックします。

Greengrass_HelloWorldで検索すると先程作成した、Lambda関数がヒットします。チェックを入れて次へをクリックします。

エイリアス: GG_HelloWorldにチェックを入れて完了します。

Lambda実行の設定を変更します。

タイムアウトを25秒に変更し、ライフサイクルを存続期間が長く無制限に稼働する関数にするにチェックを入れます。
この設定によってデバイスでGreengrassを起動するとLambda関数が自動的に起動して実行し続けます。

作成したLambda関数はhello/worldトピックへメッセージを送信し続けます。これを受け取る設定をします。

メニューのLambdaを選択します。
最初のサブスクリプションを追加するをクリックします。

ソースの選択で選択をクリックします。次にLambdaタブをクリックして作成したLambda関数をクリックします。

ターゲットの選択で選択をクリックします。次にサービスタブをクリックしてIoT Cloudをクリックします。

次へをクリックします。

オプションのトピックのフィルターで、hello/worldと入力して次へをクリックします。 トピック名はLambda関数にハードコートされています。よって任意の名前を指定することができません。ご注意ください。

完了をクリックします。

Greengrassへデプロイ

メニューのデプロイを選択します。
アクションからデプロイをクリックします。

自動検出をクリックします。

正常に完了したか確認します。

HelloWorldを受け取る

AWS IoTの画面に戻りメニューのテストを選択します。
トピックのサブスクリプションにhello/worldと入力します。
MQTTペイロード表示をペイロードを文字列として表示にチェックを入れます。
トピックへのサブスクライブをクリックします。

少し待つと、HelloWorld!が流れてきました!
成功です!

あとがき

カーネルの再構築などわからないことだらけでしたが、なんとかHello Worldまで動かすことができました。 数台なら手作業でOKですが、複数台セットアップしようとすると自動化しないと大変そうです。 以上でした!