AWS IoT Greengrass V2 の使い方の基本 〜 Greengrass のインストールからコンポーネントのデプロイまで

2023.12.20

今回、Greengrass を使う際の基本的な流れを確認する機会があったので、初期セットアップからコンポーネントのデプロイまでを一通りまとめてみました。

作業対象の環境

今回利用したデバイスは「Raspberry Pi 3B+」です。
OS や 言語の詳細は下記のとおりです。(すぐに用意できる環境で試したので若干古いです)

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 11 (bullseye)
Release:	11
Codename:	bullseye
$ python -V
Python 3.9.2

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

デバイス自体の初期セットアップは終わっているものとして、Greengrass Core ソフトウェアのインストールから始めていきましょう。

インストール作業で必要な IAM Role の作成

最初に、Greengrass Core ソフトウェアのインストールに必要な IAM ポリシーを作成します。このポリシーを持つ IAM Role はインストール時に一時的に利用されるものです。

IAM Policy を以下の内容で作成します。

  • 16 行目 〜 17 行目の account-id は利用環境のものに変更してください
  • 16 行目 〜 17 行目の GreengrassV2TokenExchangeRole の箇所は、この後で実行するインストーラーの引数で指定したものと同じ値をセットしてください。
    • ここで指定している IAM Role と IAM Policy は、Greengrass コアデバイスのインストール後にデバイスが各種 AWS サービスとやり取りするための AWS 認証情報を取得するために使用するものになります。
    • この IAM Role と IAM Policy がインストーラーで指定した値でインストーラーにより作成されます。
  • ポリシー名は適当なものを付けてください
    • 今回は ggv2-install-min-policy-20231219 としました。
  • 2つポリシーを記載していますが、2つ目の方は実際に利用したものを載せています。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CreateTokenExchangeRole",
            "Effect": "Allow",
            "Action": [
                "iam:AttachRolePolicy",
                "iam:CreatePolicy",
                "iam:CreateRole",
                "iam:GetPolicy",
                "iam:GetRole",
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::account-id:role/GreengrassV2TokenExchangeRole",
                "arn:aws:iam::account-id:policy/GreengrassV2TokenExchangeRoleAccess"
            ]
        },
        {
            "Sid": "CreateIoTResources",
            "Effect": "Allow",
            "Action": [
                "iot:AddThingToThingGroup",
                "iot:AttachPolicy",
                "iot:AttachThingPrincipal",
                "iot:CreateKeysAndCertificate",
                "iot:CreatePolicy",
                "iot:CreateRoleAlias",
                "iot:CreateThing",
                "iot:CreateThingGroup",
                "iot:DescribeEndpoint",
                "iot:DescribeRoleAlias",
                "iot:DescribeThingGroup",
                "iot:GetPolicy"
            ],
            "Resource": "*"
        },
        {
            "Sid": "DeployDevTools",
            "Effect": "Allow",
            "Action": [
                "greengrass:CreateDeployment",
                "iot:CancelJob",
                "iot:CreateJob",
                "iot:DeleteThingShadow",
                "iot:DescribeJob",
                "iot:DescribeThing",
                "iot:DescribeThingGroup",
                "iot:GetThingShadow",
                "iot:UpdateJob",
                "iot:UpdateThingShadow"
            ],
            "Resource": "*"
        }
    ]
}

今回は、デバイスに付与するロール名を 20231219-GreengrassV2TokenExchangeRole とした(後でインストーラー実行時に指定)ので下記の内容で IAM Policy を作成しました。
account-id は利用環境のものに変更します)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CreateTokenExchangeRole",
            "Effect": "Allow",
            "Action": [
                "iam:AttachRolePolicy",
                "iam:CreatePolicy",
                "iam:CreateRole",
                "iam:GetPolicy",
                "iam:GetRole",
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::account-id:role/20231219-GreengrassV2TokenExchangeRole",
                "arn:aws:iam::account-id:policy/20231219-GreengrassV2TokenExchangeRoleAccess"
            ]
        },
        {
            "Sid": "CreateIoTResources",
            "Effect": "Allow",
            "Action": [
                "iot:AddThingToThingGroup",
                "iot:AttachPolicy",
                "iot:AttachThingPrincipal",
                "iot:CreateKeysAndCertificate",
                "iot:CreatePolicy",
                "iot:CreateRoleAlias",
                "iot:CreateThing",
                "iot:CreateThingGroup",
                "iot:DescribeEndpoint",
                "iot:DescribeRoleAlias",
                "iot:DescribeThingGroup",
                "iot:GetPolicy"
            ],
            "Resource": "*"
        },
        {
            "Sid": "DeployDevTools",
            "Effect": "Allow",
            "Action": [
                "greengrass:CreateDeployment",
                "iot:CancelJob",
                "iot:CreateJob",
                "iot:DeleteThingShadow",
                "iot:DescribeJob",
                "iot:DescribeThing",
                "iot:DescribeThingGroup",
                "iot:GetThingShadow",
                "iot:UpdateJob",
                "iot:UpdateThingShadow"
            ],
            "Resource": "*"
        }
    ]
}

次に IAM Role を作ります。

  • 適当な名前で IAM Role を作成
    • 今回は ggv2-install-role-20231219 で作成しました。
  • 作成した IAM Role に先程の IAM Policy をアタッチ
  • IAM Role の信頼関係は以下のようにセットします。
    • Principal は作業者の IAM リソースに合わせて修正してください。
      • IAM User で作業する場合は "AWS": "arn:aws:iam::account-id:user/user-name" となります。
      • スイッチロールしている場合は、スイッチ先の IAM Role を指定して下さい。
        • "AWS": "arn:aws:iam::account-id:role/role-name"
      • account-iduser-namerole-name は適宜修正してください。
  • 下記は IAM User で作業している場合の例です。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::account-id:user/user-name"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
  • 下記はスイッチロールしている場合の例です。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::account-id:role/role-name"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

一時クレデンシャルの取得

次にインストーラー実行時に必要な一時クレデンシャルを取得します。この作業は先程作成した IAM Role の信頼関係で指定した Principal の内容で作業を行います。 つまり、Principal に IAM User を指定した IAM Role を作成した場合は、その Principal で指定した IAM User で作業を行います。
IAM Role の場合も同様です。

ここでの作業の流れは以下のとおりです。

  • 作成した IAM Role の内容で一時クレデンシャルを取得する
  • 取得したクレデンシャルをインストーラーを実行するデバイスの環境変数にセットする
  • クレデンシャルの取得には AWS CLI を使うので Amazon CloudShell を使う
    • そのため作業している IAM User には CloudShell の利用権限が必要です

一時クレデンシャルの取得は、CloudShell 以外の環境で実施しても問題ありません。普段利用している PC で AWS CLI が利用できる等、他の手段で実行できるなら CloudShell を使う必要はありません。

ここでは、AWS CLI が利用できる環境を用意する手間や環境依存の問題を考慮して、CloudShell を使っています。

それでは、次のコマンドを CloudShell で実行します。

echo "############ Set environment ############"
IAM_ROLE_NAME="ggv2-install-role-20231219"
ACCOUNT_ID=`aws sts get-caller-identity --query "Account" --output text`

echo "############ Get temporary credential ############"
OUTPUT=`aws sts assume-role \
--role-arn arn:aws:iam::${ACCOUNT_ID}:role/${IAM_ROLE_NAME} \
--role-session-name "RoleSession01"
`

echo "############ Copy and Paste the following credential to Greengrass Core Divice! ############" ; \
echo "export AWS_ACCESS_KEY_ID=`echo $OUTPUT | jq -r .Credentials.AccessKeyId`" ; \
echo "export AWS_SECRET_ACCESS_KEY=`echo $OUTPUT | jq -r .Credentials.SecretAccessKey`" ; \
echo "export AWS_SESSION_TOKEN=`echo $OUTPUT | jq -r .Credentials.SessionToken`" ; \
echo ""

やっていることは以下のとおりです。

  • 一時クレデンシャル情報を取得するために、作成済みの IAM Role と対象の AWS アカウント ID を環境変数にセット
  • sts assume-role コマンドで一時クレデンシャルを取得
  • デバイスで Greengrass コアソフトをインストールする際に、コピペでシェルに環境変数をセットできるように出力内容を指定

実行すると次のような結果になります。最後の3行をコピペしてデバイスの環境変数にセットします。

01-cloudshell

デバイスに環境変数をセット

次に Greengrass Core ソフトウェアをインストールするデバイスに環境変数をセットします。先程 CloudShell で出力されたものをコピペするだけで OK です。(以下は省略して記載しています)

export AWS_ACCESS_KEY_ID=AS...
export AWS_SECRET_ACCESS_KEY=FQ...
export AWS_SESSION_TOKEN=IQ...

Javaのインストール

Greengrass を利用するには Java の実行環境が必要です。Java 8 以上が必要になるのでインストールします。

sudo apt-get update
sudo apt install default-jdk

確認

java -version
openjdk version "11.0.21" 2023-10-17
OpenJDK Runtime Environment (build 11.0.21+9-post-Raspbian-1deb11u1)
OpenJDK Server VM (build 11.0.21+9-post-Raspbian-1deb11u1, mixed mode)

AWS IoT GreengrassCoreソフトウェアのインストール

ここからは Greengrass Core ソフトのインストール作業になります。最新バージョンのインストーラーをダウンロードします。
(下記はホームディレクトリで実行しています。)

cd ~
curl -s https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-nucleus-latest.zip > greengrass-nucleus-latest.zip

ダウンロードできたら解答します。
GreengrassInstaller はインストーラーを保存するディレクトリの指定です。解凍するとカレントディレクトリに GreengrassInstaller というディレクトリが作成されます。

unzip greengrass-nucleus-latest.zip -d GreengrassInstaller && rm greengrass-nucleus-latest.zip

次にインストーラーを実行して Greengrass Core ソフトウェアをインストールします。各パラメーターは適宜変更して下さい。

  • --aws-region: 利用リージョンを指定
  • --thing-name: Greengrass Core デバイスに付与するデバイス名を指定
  • --thing-group-name: Greengrass Core デバイスの モノ のグループを指定
  • --tes-role-name : Greengrass コアデバイスが一時的な AWS 認証情報を取得するための IAM ロールの名前を指定
  • --tes-role-alias-name: Greengrass コアデバイスが後で一時的な認証情報を取得できるようにする IAM ロールのエイリアス
  • --deploy-dev-tools: デバイス上で利用できる Greengrass CLI をデプロイするかどうかを指定
sudo -E java -Droot="/greengrass/v2" -Dlog.store=FILE \
  -jar ./GreengrassInstaller/lib/Greengrass.jar \
  --aws-region ap-northeast-1 \
  --thing-name MyRpi3b-20231219-GreengrassV2Core \
  --thing-group-name MyRpi3b-20231219-GreengrassV2CoreGroup \
  --thing-policy-name MyRpi3b-20231219-GreengrassV2IoTThingPolicy \
  --tes-role-name 20231219-GreengrassV2TokenExchangeRole \
  --tes-role-alias-name 20231219-GreengrassCoreTokenExchangeRoleAlias \
  --component-default-user ggc_user:ggc_group \
  --provision true \
  --setup-system-service true \
  --deploy-dev-tools true

完了すれば次のようなメッセージが最後に表示されます。 (--deploy-dev-tools を指定していない場合は 4 行目の出力はありません。)

Created device configuration
Successfully configured Nucleus with provisioned resource details!
Creating a deployment for Greengrass first party components to the thing group
Configured Nucleus to deploy aws.greengrass.Cli component
Successfully set up Nucleus as a system service

Greengrass コアソフトウェアのインストール確認

正常にインストールできたか確認してみます。今回は Greengrass CLI を同時にインストールしているので、その動作確認を以てインストールの正常性を確認します。
デフォルトでは /greengrass/v2/bin/ 以下にインストールされるので、コマンドのパスを指定して Greengrass コンポーネントの一覧を表示してみます。

sudo /greengrass/v2/bin/greengrass-cli component list

次のような出力があれば OK です。

Components currently running in Greengrass:
Component Name: aws.greengrass.Nucleus
    Version: 2.12.1
    State: FINISHED
    Configuration: {"awsRegion":"ap-northeast-1","componentStoreMaxSizeBytes":"10000000000","deploymentPollingFrequencySeconds":"15","envStage":"prod","fipsMode":"false","fleetStatus":{"periodicStatusPublishIntervalSeconds":86400.0},"greengrassDataPlaneEndpoint":"","greengrassDataPlanePort":"8443","httpClient":{},"iotCredEndpoint":"xxx.credentials.iot.ap-northeast-1.amazonaws.com","iotDataEndpoint":"xxx-ats.iot.ap-northeast-1.amazonaws.com","iotRoleAlias":"20231219-GreengrassCoreTokenExchangeRoleAlias","jvmOptions":"-Dlog.store=FILE","logging":{},"mqtt":{"spooler":{}},"networkProxy":{"proxy":{}},"platformOverride":{},"runWithDefault":{"posixUser":"ggc_user:ggc_group"},"s3EndpointType":"GLOBAL","telemetry":{}}
Component Name: TelemetryAgent
    Version: 0.0.0
    State: RUNNING
    Configuration: null

(以下略)

なお、Greengrass Core のログはデフォルトの場合、デバイス上の /greengrass/v2/logs/ に出力されます。

マネジメントコンソールでは Greengrass コアのデバイスとして新たに登録されていることが確認できました。

03-ggc-device

カスタムコンポーネントの作成

Greengrass 環境が構築できたので、次はコンポーネントを作成します。

カスタムコンポーネントの作成と全体像

作業に入る前に Greengrass のコンポーネントの作成とデプロイの流れを簡単に確認しておきます。

まず、コンポーネントのパッケージングと Greengrass サービスへの登録を行います。 この作業は、次で紹介する Greengrass Development Kit (GDK) CLI というツールを使うと便利です。 このツールは開発用の PC にインストールして利用します。

必要な設定ファイルや処理ロジックが書かれたコードを、言語に応じた方法でビルドしてアーティファクトを作成します。(Pythonの場合は zip
次に、開発用 PC 上に作成されたアーティファクトを所定のパス構造で S3 に保存します。S3 上のアーティファクトを指定する形で Greengrass サービス側からアーティファクトをコンポーネントとして登録します。
この際も GDK CLI を使うことでコンポーネント登録に必要なパス構造で S3 にアップロード、Greengrassへの登録まで自動で行ってくれます。

最後にネジメンコンソールや API などからコンポーネントをデバイスにデプロイします。

1001-use-gdk-4

Greengrass Development Kit (GDK) CLI のインストール

Greengrass コンポーネントの作成には GDK CLI を使うと諸々の作業が効率的になります。

MacOS、Windows、Unixライクな開発用のコンピュータ環境にインストール可能です。
前提条件はドキュメントに詳細な記載がありますが、少なくとも下記の環境が必要になります。

  • python3.6 以上がインストールされていること
  • AWS CLI がインストールされていること(AWS CLI V1 でも可)
  • GDK CLI を実行する PC に下記の IAM 権限
    • s3:CreateBucket
    • s3:GetBucketLocation
    • s3:PutObject
    • greengrass:CreateComponentVersion
    • greengrass:ListComponentVersions

インストール作業は下記のリポジトリの説明に則ります。

次のコマンドを実行して最新バージョンのものをインストールします。

pip3 install git+https://github.com/aws-greengrass/aws-greengrass-gdk-cli.git@v1.6.1

動作確認します。下記のように help の内容が正常に出力されていれば OK です。

gdk --help
usage: gdk [-h] [-d] [-v] {component,test-e2e,config} ...

Greengrass development kit - CLI for developing AWS IoT GreengrassV2 components.

positional arguments:
  {component,test-e2e,config}
    component           Initialize, build and publish GreengrassV2 components using this command.
    test-e2e            Test component features using open-source test framework
    config              Populate values in the gdk-config.json configuration file via the CLI.

options:
  -h, --help            show this help message and exit
  -d, --debug           Increase command output to debug level
  -v, --version         show program's version number and exit

コンポーネントフォルダの初期化

GDK CLI がインストールできたので、カスタムコンポーネントを作成していきます。最初に初期化を実施します。
--name で指定した名前のディレクトリが作成され、その配下に必要なファイル群が展開されます。

gdk component init \
  --language python \
  --name Test-20231219 \
  --template HelloWorld

ディレクトリ構成は次のようになっています。

.
└── Test-20231219
    ├── README.md
    ├── gdk-config.json
    ├── main.py
    ├── recipe.yaml
    ├── src
    │   └── greeter.py
    └── tests
        └── test_greeter.py

作成された Test-20231219 に移動して作業を続けます。

cd Test-20231219

構成ファイルの編集

GDK CLI 構成ファイルである gdk-config.json を下記のように編集します。

  • author: 作成者の名前に変更
  • コンポーネント名を com.example.test20231219 に変更
  • bucket: S3 バケットのプレフィックスを指定
  • region: 利用リージョンを指定

バケットのプレフィックスの指定ですが、コンポーネントを Greengrass サービスに登録するときコンポーネントとして実行されるスクリプトやライブラリなどがアーティファクトとして、S3 に保存されます。
その保存先は gdk-config.json の内容をもとに[バケットプレフィックス]-[リージョン]-[アカウントID] という形で作成されます。

ただし、後で紹介するコマンド(gdk component publish)でオプションとしてバケット指定を上書きできます。

gdk-config.json

 {
     "component": {
         "com.example.test20231219": {
             "author": "CM-ICHIDA",
             "version": "NEXT_PATCH",
             "build": {
                 "build_system": "zip"
             },
             "publish": {
                 "bucket": "test20231219",
                 "region": "ap-northeast-1"
             }
         }
     },
     "gdk_version": "1.6.1"
 }

レシピの編集

次にレシピ(recipe.yaml)を修正します。

  • ComponentDescription: 適当な内容に変更
  • DefaultConfiguration: スクリプトの引数に渡すメッセージ。必要に応じて変更。
  • Manifests
    • Artifacts
      • URI: 最後のパスを コンポーネント名.zip の形に修正
    • Lifecycle
      • Run: {artifacts:decompressedPath}/コンポーネント名/main.py となるように修正

recipe.yaml

---
RecipeFormatVersion: "2020-01-25"
ComponentName: "{COMPONENT_NAME}"
ComponentVersion: "{COMPONENT_VERSION}"
ComponentDescription: "This is sample component written in Python."
ComponentPublisher: "{COMPONENT_AUTHOR}"
ComponentConfiguration:
  DefaultConfiguration:
    Message: "test20231219"
Manifests:
  - Platform:
      os: all
    Artifacts:
      - URI: "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.test20231219.zip"
        Unarchive: ZIP
    Lifecycle:
      Run: "python3 -u {artifacts:decompressedPath}/com.example.test20231219/main.py {configuration:/Message}"

ロジックの修正

コンポーネントのメインロジックとなるコード(main.py)を修正します。
今回は次のようなものにしました。デバイスにセンサーなどを繋いでデータを取得する場合は、従来と同じようにコード記述できます。

main.py

import sys
import datetime
import time

while(True):
    # Print the message to stdout.
    message = "Hello, %s! Current time: %s." % (sys.argv[1], datetime.datetime.now())
    print(message)

    # Append the message to the log file.
    with open('/tmp/Greengrass_Test20231219.log', 'a') as f:
        print(message, file=f)
    time.sleep(5)

ビルド

準備ができたのでビルドします。

gdk component build

正常にビルドできたら次のようなメッセージが表示されます。

[2023-12-19 18:24:58] INFO - Discovered 1.2.0 as latest GTF release name.
[2023-12-19 18:24:58] INFO - Building the component 'com.example.test20231219' with the given project configuration.
[2023-12-19 18:24:58] INFO - Using 'zip' build system to build the component.
[2023-12-19 18:24:58] WARNING - This component is identified as using 'zip' build system. If this is incorrect, please exit and specify custom build command in the 'gdk-config.json'.
[2023-12-19 18:24:58] INFO - Validating the file size of recipe /your-folder-path/Test-20231219/recipe.yaml
[2023-12-19 18:24:58] INFO - Copying over the build artifacts to the greengrass component artifacts build folder.
[2023-12-19 18:24:58] INFO - Updating artifact URIs in the recipe.
[2023-12-19 18:24:58] INFO - Validating the recipe against the Greengrass recipe schema.

パブリッシュ

アーティファクトが生成できたら Greengrass へパブリッシュします。
この処理では、次のことが自動で行われます。

  • S3 に所定のパス形式でコンポーネントが put される
    • [S3 バケット] > [コンポーネント名] > バージョン > ZIP ファイル
  • S3 上のアーティファクトに対して Greengrass 側にコンポーネントが登録される
    • バージョンやコンポーネント名は自動で登録されます

下記コマンドのオプション --bucket でアーティファクトの保存先を指定できます。gdk-config.json の内容よりもオプションによる指定が優先されます。

gdk component publish --bucket gg-cmtest-20231219

成功すると次のメッセージが出力されます。

[2023-12-19 18:39:25] INFO - Discovered 1.2.0 as latest GTF release name.
[2023-12-19 18:39:25] INFO - Found credentials in environment variables.
[2023-12-19 18:39:27] INFO - No private version of the component 'com.example.test20231219' exist in the account. Using '1.0.0' as the next version to create.
[2023-12-19 18:39:27] INFO - Publishing the component 'com.example.test20231219' with the given project configuration.
[2023-12-19 18:39:27] INFO - Uploading the component built artifacts to s3 bucket.
[2023-12-19 18:39:27] INFO - Uploading component artifacts to S3 bucket: gg-cmtest-20231219. If this is your first time using this bucket, add the 's3:GetObject' permission to each core device's token exchange role to allow it to download the component artifacts. For more information, see https://docs.aws.amazon.com/greengrass/v2/developerguide/device-service-role.html.
[2023-12-19 18:39:28] INFO - Successfully created the artifacts bucket 'gg-cmtest-20231219' in region 'ap-northeast-1'
[2023-12-19 18:39:28] INFO - Updating the component recipe com.example.test20231219-1.0.0.
[2023-12-19 18:39:28] INFO - Validating the file size of the built recipe /your-folder-path/Test-20231219/greengrass-build/recipes/com.example.test20231219-1.0.0.yaml
[2023-12-19 18:39:28] INFO - Validating the built recipe against the Greengrass recipe schema.
[2023-12-19 18:39:28] INFO - Creating a new greengrass component com.example.test20231219-1.0.0.
[2023-12-19 18:39:29] INFO - Created private version '1.0.0' of the component 'com.example.test20231219' in the account.

AWS IoT Core のマネジメントコンソールで、「Greengrass デバイス」>「コンポーネント」 と辿ってコンポーネント画面を開くと、作成したコンポーネントである com.example.test20231219 が登録されていることが分かります。

04-custom-component

また、S3 をマネジメントコンソールで確認すると、指定したバケットが作成されていて、Greengrass コンポーネント登録に必要なパス形式でアーティファクトが保存されていました。

02-gg-component-artifact

今後、コンポーネントを更新するときは、自動で新しいバージョンのパスが切られてアーティファクトが保存されるようになります。(開発者は S3 側の構造を気にしせず作業に専念できます)

コンポーネントのデプロイ

これまでの作業でカスタムコンポーネントが作成できました。
次は作成したコンポーネントをデバイスにデプロイしてみます。

事前準備 - デバイスからの AWS アクセス権限を追加

今回のコンポーネントはカスタムコンポーネントなので、自作したアーティファクトが S3 に保存されています。コンポーネントのデプロイ時は、この S3 バケットからアーティファクトを取得する必要があるので、デバイスに S3 アクセスの IAM 権限を付与しておく必要があります。

このように Greengrass Core インストール後の Greengrass デバイスが AWS リソースにアクセスする際に利用する IAM Role は、インストーラーの引数 --tes-role-alias-name で指定したものになります。

今回は 20231219-GreengrassV2TokenExchangeRole という IAM Role を指定していました。この Role に S3 へのアクセス権限を追加しておきます。
今回は少し横着して AmazonS3ReadOnlyAccess のポリシーを追加しました。

17-s3-access-iam-role

事前準備 - コンポーネントデプロイ時のログの確認

デプロイする前にデバイス上でログを流しておいて、デプロイの様子を観察できるようにしておきます。

sudo tail -F /greengrass/v2/logs/greengrass.log

ログは tail コマンドで開いたままにしておいて、コンポーネントのデプロイ作業を行います。

コンポーネントのデプロイ方法と注意点

作業を始める前に Greengrass コンポーネントのデプロイで注意点があります。

Greengrass コンポーネントのデプロイは、「既存のデプロイに追加」と「新しいデプロイを作成」の2種類から選択可能です。複数のコンポーネントがすでにデプロイされているデバイスに対して「新しいデプロイ」を実行するときは既存のコンポーネントも全てデプロイ対象に指定しないとデバイスから削除されてしまうので注意が必要です。

既存デプロイを利用したデプロイ

Greengrass Core ソフトウェアのインストールも「デプロイ」の一つとして記録されているので、今回は「既存のデプロイに追加」する手順を実行します。
まず、対象の Greengrass Core デバイスの画面を開きます。

05-select-code-device

次の画面で「デプロイ」タブを開いて「デプロイ名」をクリックします。
このデプロイ「Deployment for MyRpi3b-20231219-GreengrassV2CoreGroup」が今回利用する「既存のデプロイ」ということになります。後で利用するので、このデプロイ名は控えておいてください。

06-specify-deloyment-name

次に、デプロイしたいコンポーネント「com.example.test20231219」の画面を開きます。 画面上部に「デプロイ」ボタンがあるのでクリックします。

10-deploy-component

次の画面で「既存のデプロイに追加」を選択して、先程確認した対象の「デプロイ」を選択して次に進みます。

11-add-deploy

デプロイ名は選択したものがそのまま入力されているので、そのまま次に進みます。

12-set-target

「コンポーネントの選択」でもすでに「新規でデプロイするコンポーネント(com.example.test20231219)」と「既存のコンポーネント(aws.greengrass.cli)」にチェックが入っているので、そのまま進みます。
ここでチェックを外すとデプロイ済みのコンポーネントは削除されます。

13-select-component

次の「コンポーネントを設定」の画面は、今回は何もすることが無いので次に進みます。
(必要に応じて、コンポーネントの処理ロジックに渡すパラメーターや設定を変更してデプロイすることができます)

14-set-config

最後の詳細設定もそのままで次に進みます。Greengrass コンポーネントのデプロイは IoT Jobs が利用されるのですが、そのジョブの動作を定義するオプションです。

15-set-detail

最後のレビュー画面で内容を確認して、問題なければ「デプロイ」をクリックしてデプロイが開始されます。

16-review-deploy

コンポーネントの動作確認

デプロイが正常に終了すると、greengrass.log に次のようなログを確認できます。
(下記は分かりやすさのために抜粋したものになります)

2023-12-19T10:53:49.634Z Current deployment finished. {serviceName=DeploymentService, currentState=RUNNING}
2023-12-19T10:53:50.365Z Stored deployment status. DeploymentStatus=SUCCEEDED}
2023-12-19T10:53:50.367Z Updating status of persisted deployment. {Status=SUCCEEDED, StatusDetails={detailed-deployment-status=SUCCESSFUL}, ThingName=MyRpi3b-20231219-GreengrassV2Core}
2023-12-19T10:53:50.844Z  Job status update was accepted. {Status=SUCCEEDED, ThingName=MyRpi3b-20231219-GreengrassV2Core}
2023-12-19T10:53:51.929Z Received empty jobs in notification . {ThingName=MyRpi3b-20231219-GreengrassV2Core}

マネジメントコンソールでは、デプロイのステータスを確認できます。今回は1つのデバイスで成功していることが分かります。

18-succeed-deployment

また、コンポーネント単体のログには、次のように5秒間隔で標準出力の内容が出ています。

tail -F com.example.test20231219.log

2023-12-19T10:54:05.400Z [INFO] (Copier) com.example.test20231219: stdout. Hello, test20231219! Current time: 2023-12-19 19:54:05.399372.. {scriptName=services.com.example.test20231219.lifecycle.Run, serviceName=com.example.test20231219, currentState=RUNNING}
2023-12-19T10:54:10.406Z [INFO] (Copier) com.example.test20231219: stdout. Hello, test20231219! Current time: 2023-12-19 19:54:10.405238.. {scriptName=services.com.example.test20231219.lifecycle.Run, serviceName=com.example.test20231219, currentState=RUNNING}
2023-12-19T10:54:15.411Z [INFO] (Copier) com.example.test20231219: stdout. Hello, test20231219! Current time: 2023-12-19 19:54:15.411037.. {scriptName=services.com.example.test20231219.lifecycle.Run, serviceName=com.example.test20231219, currentState=RUNNING}

コンポーネントの Python スクリプト(main.py)で記載したとおり /tmp/Greengrass_Test20231219.log にも 5 秒間隔でメッセージが出力されていることを確認できました。

tail -F /tmp/Greengrass_Test20231219.log
Hello, test20231219! Current time: 2023-12-19 19:54:35.434613.
Hello, test20231219! Current time: 2023-12-19 19:54:40.440488.
Hello, test20231219! Current time: 2023-12-19 19:54:45.446441.

最後に

Greengrass Core ソフトのインストール時にも IAM 権限が必要なので、少し複雑に思う部分はあるかもしれません。
分かりやすさのために専用の IAM User を作成して静的にデバイスにキー情報を配置して使うこともできますが、よりセキュアに利用するため、CloudShell を使って一時クレデンシャルを発行してみました。

また、GDK CLI も以前のバージョンに比べると直感的に使えるようになり、スムーズに作業できたのは良かったと思います。利用に不便を感じることがあれば最新バージョンを試していただくと良いかもしれません。

以上です。