AWS IoT GreengrassをMacで少し試す
普段なかなか使わないけど、気になっていたサービスを触ってみる個人的な備忘録です。
みなさん、AWS IoT Greengrassはご存知ですか??
私は業務の中でIoT関連を扱うことがあるのですが、AWS IoT Greengrassはほとんど触れたことがなく、AWSのIoT系のサービスの中でもレベル400的なハードル感があります(個人的見解です)。
というのも、Linuxを積んだマシン(例えば、Raspberry Pi)とかを実際に用意しないといけなかったりするので、Cloud9がサ終になる今、なかなか気軽に試せないサービスだなーと思ったりしていました。
ただ、別の用件で、MacでGreengrassを調査する必要があったので、タイトル通り、Macで無理やり試してみました。
参考: AWS Black Belt Online Seminar
参考: AWS IoT Greengrass V2 入門ハンズオン
参考: AWS IoT Greengrass V2 の使い方の基本
環境
Apple M1
macOS Sequoia 15.2
Greengrassをセットアップ
セットアップはほぼ公式のハンズオン通りに進めました。ロールやポリシーはハンズオンの設定をそのまま反映。Greengrassの設定は、AWSコンソールからAWS IoTに移動し、Greengrassのコアデバイスを選択。
コアデバイスをセットアップを押して、デバイスの情報を入力していきます。
コアデバイス名:<任意の名前を入力>
モノのグループ:GrrengrassQuickStartGroup
Greengrassコアソフトの選択:Nucleus Classic
オペレーティングシステム:Linux
デバイスのセットアップ方法ですが、いくつか選択することができます。
ここでは、Macに直接ダウンロードすることを目的にインストーラのダウンロードでデバイスをセットアップするを選びました。
すると、丁寧に次のステップを記載してくれています。
Javaをインストールするんですね。Java使ったことないや、、、
Javaをインストールする
どうやらいろんなところからJDKが出ているのですが、ここではAmazon Corretoでインストールしてみます
brew install --cask corretto
java --version
openjdk 23.0.2 2025-01-21
OpenJDK Runtime Environment Corretto-23.0.2.7.1 (build 23.0.2+7-FR)
OpenJDK 64-Bit Server VM Corretto-23.0.2.7.1 (build 23.0.2+7-FR, mixed mode, sharing)
ふむふむ。これで入ったみたいですね。
AWS IoTモノを作成して接続キットをダウンロード
[モノを作成]ボタンを押すと自動でポリシーやロール関係が設定れれて作成済みになります。
Thingを訳して[モノ]と表現するのもなかなかの違和感ですが、[ブツ]と表現するよりはマシかな。
続いて、[接続キットをダウンロード]ボタンを押してローカルにzipファイルをダウンロード。
インストーラーをダウンロード
[インストーラをダウンロード]ボタンを押してローカルにzipファイルをダウンロードします。
ダウンロードをデバイスに転送してセットアップ
コンソール上では、デバイスへのダウンロードの仕方を丁寧に説明してくれています。
ですが、今回は、Macに直接インストールするので、少し修正をしました。
sed -i 's|{{config_dir}}|/greengrass/v2|g; s|{{nucleus_component}}|aws.greengrass.Nucleus|g' /greengrass/v2/config.yaml && sudo -E java -Droot="/greengrass/v2" -Dlog.store=FILE -jar ./GreengrassInstaller/lib/Greengrass.jar --init-config /greengrass/v2/config.yaml --component-default-user ggc_user:ggc_group --setup-system-service true
これをMacで実行します。
Creating group ggc_group
ggc_group created
Added ggc_user to ggc_group
Launching Nucleus...
Launched Nucleus successfully.
と出て、どうやらうまくいったようです。よしよし。
別のターミナルを立ち上げて状況を見てみます。
ps aux | grep greengrass
とすると、
59565 0.0 0.0 38537680 3384 s007 S+ Sat06PM 0:43.25 /usr/bin/java -Droot=/Users/okunisan/Documents/dev/aws/self_greengrass_test/greengrass/v2 -Dlog.store=FILE -jar /Users/okunisan/Documents/dev/aws/self_greengrass_test/GreengrassInstaller/greengrass-nucleus-latest/lib/Greengrass.jar --init-config /Users/okunisan/Documents/dev/aws/self_greengrass_test/greengrass/v2/config.yaml --component-default-user ggc_user:ggc_group --setup-system-service false
root 59564 0.0 0.0 410289616 880 s007 S+ Sat06PM 0:00.04 sudo -E java -Droot=/Users/okunisan/Documents/dev/aws/self_greengrass_test/greengrass/v2 -Dlog.store=FILE -jar /Users/okunisan/Documents/dev/aws/self_greengrass_test/GreengrassInstaller/greengrass-nucleus-latest/lib/Greengrass.jar --init-config /Users/okunisan/Documents/dev/aws/self_greengrass_test/greengrass/v2/config.yaml --component-default-user ggc_user:ggc_group --setup-system-service false
okunisan 11964 0.0 0.0 410218224 1376 s009 S+ 9:42PM 0:00.01 grep greengrass
おお!どうやら動いている様子ですね。
AWS IoTのコンソールで、Greengrassデバイスでコアデバイスを確認できました。
デバイスの証明書には下記のポリシーがアタッチされていますね。
でもローカル開発で必要となるgreengrass-cliがインストールされませんでした。どうやら、コアソフトウェアのインストール時に、
--deploy-dev-tools true
このオプションを付けてなかったのが原因でした。そこで、今回は、クラウド側からデバイス(今回は手元のMac)に対して、デプロイを試します。
greengrass.Cliコンポーネントのデプロイ
そもそも、greengrass-cliとはなんぞや?って話なんですが、
IoTの場合は、現場にデバイスが置かれるのでクラウド側からソフトウェア更新する場面が多いのですが、開発フェーズだと直接デバイス側でコードをいじったり試したりすることが多く、その時にローカルにデプロイしたり、デバッグするのに役立つのがgreengrass-cliです。
このCLIを導入するには、先ほどのダウンロード時にオプションをつけてインストールするほか、AWS IoTコンソールのGreengrassにおいて、パブリックコンポーネントとしてもあらかじめ用意されており、クラウド側から現場デバイスにデプロイすることができます。(便利!)
参考: UbuntuにAWS IoT GreengrassV2をインストールする - Qiita
この通りにやると、greengrass/v2/binの中にgreengrass-cliが入りました。
❯ greengrass/v2/bin/greengrass-cli --version
Greengrass CLI Version: 2.13.0
しっかり入ってますね。
Greengrassの起動・停止、再起動など各種操作
ということで、無事にGreengrassが入りました。
ところで、Greengrassって、稼働状態を見たり、停止や再起動ってどうするんだろうと気になり、調べました。
❯ ps aux | grep greengrass
root 19023 0.0 0.0 38849384 3252 ?? S 27 125 17:19.44 /usr/bin/java -Dlog.store=FILE -Dlog.store=FILE -Droot=/Users/okunisan/Documents/dev/aws/self_greengrass_test/greengrass/v2 -jar /Users/okunisan/Documents/dev/aws/self_greengrass_test/greengrass/v2/alts/current/distro/lib/Greengrass.jar --setup-system-service false
okunisan 92215 0.0 0.0 410218224 1376 s006 S+ 9:37PM 0:00.00 grep greengrass
ふむふむ。rootで何か動いてそう。
❯ sudo lsof -i | grep java
java 19023 root 21u IPv4 0xcc99d19c9095ffa4 0t0 TCP 192.168.100.30:51084->ec2-35-74-159-248.ap-northeast-1.compute.amazonaws.com:8883 (ESTABLISHED)
通信もしてそうですね。
停止する場合
# Greengrassのプロセスを確認
ps aux | grep greengrass
# 見つかったプロセスIDを使って停止(例:プロセスIDが19023の場合)
sudo kill 19023
無理やり止めます。笑。
再起動する場合
# もしルートディレクトリにいて、配下にgreengrass/v2ディレクトリが存在している場合
sudo greengrass/v2/alts/current/distro/bin/loader
greengrass-cliを使った各種確認
動いているコンポーネントの状況を確認してみます。こういうときにgreengrass-cliが役立ちます。
❯ sudo greengrass/v2/bin/greengrass-cli component list
Password:
Components currently running in Greengrass:
Component Name: aws.greengrass.Nucleus
Version: 2.13.0
State: FINISHED
Configuration: {"awsRegion":"ap-northeast-1","componentStoreMaxSizeBytes":"10000000000","deploymentPollingFrequencySeconds":"15","envStage":"prod","fipsMode":"false","fleetStatus":{"periodicStatusPublishIntervalSeconds":86400.0},"greengrassDataPlaneEndpoint":"","greengrassDataPlanePort":"8443","httpClient":{},"iotCredEndpoint":"<iotCredEndpoint>.credentials.iot.ap-northeast-1.amazonaws.com","iotDataEndpoint":"<iotDataEndpoint>-ats.iot.ap-northeast-1.amazonaws.com","iotRoleAlias":"GreengrassV2TokenExchangeCoreDeviceRoleAlias","jvmOptions":"-Dlog.store=FILE","logging":{},"mqtt":{"spooler":{}},"networkProxy":{"proxy":{}},"platformOverride":{},"runWithDefault":{"posixUser":"ggc_user:ggc_group"},"s3EndpointType":"GLOBAL","telemetry":{}}
Component Name: FleetStatusService
Version: 0.0.0
State: RUNNING
Configuration: null
Component Name: UpdateSystemPolicyService
Version: 0.0.0
State: RUNNING
Configuration: null
Component Name: aws.greengrass.Cli
Version: 2.13.0
State: RUNNING
Configuration: {"AuthorizedPosixGroups":null,"AuthorizedWindowsGroups":null}
Component Name: TelemetryAgent
Version: 0.0.0
State: RUNNING
Configuration: null
Component Name: DeploymentService
Version: 0.0.0
State: RUNNING
Configuration: null
ほほう。こんなのがコンポーネントに入っているんですね。
greengrass-cliさん、便利です。
(オプション)コンポーネントを作成してみる
さて、Macに入れて動かすという初期の目的は達成しましたが、ここからは、入門ハンズオンで説明されていたコンポーネントの作成を試してみます。
ところでGreengrassでいうコンポーネントって何のことでしょうか?
ここがGreengrassのわかりにくいところなんですよね(私的に)
AWS Black Beltを読み返し、自分の中でも概念を整理してみました。
AWS Greengrass コアデバイス
|---- AWS IoT Greengrass Coreソフトウェア
| |---- Nucleus (必須)
| |---- Greengrass CLI (ローカル開発ツール)
| |---- そのほかいろいろ
|
|---- AWS IoT Greengrass コンポーネント
| |---- カスタムコンポーネント1
| | |---- レシピ
| | |---- アーティファクト
| |---- カスタムコンポーネント2
| | |---- レシピ
| | |---- アーティファクト
|
|---- Operating System
コンポーネントとは、カスタムで作れるソフトウェアモジュールなんですね。コンポーネントはレシピとアーティファクトによって定義・設定されます。
レシピ:
- 設定パラメータ、依存関係、ライフサイクル、互換性を指定するメタ情報が書かれたもので、YAMLまたはJSONファイル
アーティファクト:
- スクリプト、バイナリ、静的リソースそのもの。S3とかECRに置いてデバイスにダウンロードもできる(レシピで指定する)
ふむふむ。少しわかった気がします。
さて実際に、入門ハンズオンで書いているコンポーネント作成をやってみます。greengrass-cliを使い、ローカルデプロイを試みます。
Macのどこかのディレクトリでアーティファクトのフォルダと空のスクリプトファイルを作成します。
mkdir -p artifacts/com.example.HelloWorld/1.0.0
touch artifacts/com.example.HelloWorld/1.0.0/hello_world.py
ここで大事なのは、アーティファクトのパスというのは下記のようにする必要があります。
artifacts/componentName/componentVersion/
なお、componentNameとcomponentVersionは後ほど作る任意の名前になります。
そんで、hello_world.pyの中身は下記とします。
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
import sys
import datetime
import time
while True:
message = f"Hello, {sys.argv[1]}! Current time: {str(datetime.datetime.now())}."
# Print the message to stdout.
print(message)
# Append the message to the log file.
with open('/tmp/Greengrass_HelloWorld.log', 'a') as f:
print(message, file=f)
time.sleep(1)
コンポーネントレシピの作成とローカルデプロイメント
レシピは各種パラメーターが書かれた定義書です。YAMLかJSONで作成するのですが、今回はJSONで作成してみます。
早速,com.example.HelloWorld-1.0.0.jsonを作成します。
mkdir recipes
touch recipes/com.example.HelloWorld-1.0.0.json
com.example.HelloWorld-1.0.0.jsonの中身
{
"RecipeFormatVersion": "2020-01-25",
"ComponentName": "com.example.HelloWorld",
"ComponentVersion": "1.0.0",
"ComponentDescription": "My first AWS IoT Greengrass component.",
"ComponentPublisher": "Amazon",
"ComponentConfiguration": {
"DefaultConfiguration": {
"Message": "world"
}
},
"Manifests": [
{
"Platform": {
"os": "Darwin"
},
"Lifecycle": {
"Run": "python3 -u {artifacts:path}/hello_world.py '{configuration:/Message}'\n"
}
}
]
}
では、ついにコアデバイスにローカルデプロイしてみましょう
❯ sudo bin/greengrass-cli deployment create --recipeDir recipes --artifactDir artifacts --merge "com.example.HelloWorld=1.0.0"
Password:
Local deployment submitted! Deployment Id: a2f14f38-9ade-435f-922f-74443ddf2707
これでローカルにデプロイできました。やった。簡単ですね!
うまくいけば、HelloWorldのlogが出るようですが、、、、
あれ、、?エラーだ。。。
Macでやっていたため、たくさんのエラーが吐かれてしまい、うまくいかず。。。ここから数時間、沼にハマりました。
と言うことで今回はここで断念。いつかまた。。。笑
Discussion