AWS Systems Manager による AWS IoT Greengrass デバイスサポートを試してみる

地味なアップデートだけど面倒な手順が省略できるようになった嬉しいアップデートです
2021.12.10

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

先日の re:Invent 2021 期間中に AWS Systems Manager が AWS IoT Greengrass デバイスをサポートするアップデートがありましたので試してみました。

従来のマネージドインスタンス登録との違い

これまで、オンプレミスサーバや Raspberry Pi などのエッジデバイスでも要件(OSがサポート対象である等)が合えば、エッジデバイスでも AWS Systems Manager のマネージドインスタンスとして登録することが可能でした。

今回のアップデートで AWS Systems Manager Agent (SSM Agent) が AWS IoT Greengrass (V2)のコンポーネントとして提供されることになったので、このコンポーネントをデプロイするだけで「AWS Systems Manager Agent のインストール」と「アクティベーション」を自動で実行してくれるようになりました。

注意点

今回のリリースで提供される Systems Manager Agent コンポーネント がサポートするプラットフォームは下記のとおりです。Greengrass コア自体は Armv7 や Windows をサポートしていますが、このコンポーネントが動作できる環境は限定的なので注意が必要です。

  • 64bit Linux 上の Greengrass コアデバイス
  • Armv8(AArch64)または x86_64

検証環境

今回は下記の環境で動作検証を行いました。

  • Raspberry Pi 4B
  • ubuntu 20.04.3 LTS 64bit

上記の環境に Greengrass (V2) 環境を用意していますが、本記事では Greengrass コアデバイスのセットアップは省略します。具体的な手順については下記を参考にしてみてください。

それでは、ここから実際の手順を見ていきたいと思います。

IAM の設定

まずは必要な IAM の設定を行います。デバイスが AWS Systems Manager と通信するために IAM のサービスロールを作成します。まず手元のPCで適当なディレクトリで下記の json ファイルを用意します。

  • SSMService-Trust.jsonとして作成
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": {
            "Service": "ssm.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
    }
}

作成したポリシーの JSON ファイルに対して AWS CLI で IAM Role を作成します。

$ aws iam create-role \
    --role-name SSMServiceRole \
    --assume-role-policy-document file://SSMService-Trust.json

次に、デバイスがAWS SystemsManager サービスのコア機能を使用できるように AmazonSSMManagedInstanceCore という AWS マネージドポリシーを、先程作成した IAM Role にアタッチします。

$ aws iam attach-role-policy \
    --role-name SSMServiceRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

26-ssm-policy

最後に、Greengrass コアデバイスで利用する IAM Role である Token Exchange Service(TES)に Systems Manager を利用する権限を追加します。
Greengrass コアソフトインストール時のデフォルト設定では、TES の IAM Role 名は GreengrassV2TokenExchangeRole になります。

先程と同じように下記内容のポリシーを記載した JSON ファイルを作成します。(ssm-agent-component-policy.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:PassRole"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:iam::[YOUR_AWS_ACCOUNT_ID]:role/SSMServiceRole"
      ]
    },
    {
      "Action": [
        "ssm:AddTagsToResource",
        "ssm:RegisterManagedInstance"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

次にポリシーを作成します。ポリシー名は「GreengrassSSMAgentComponentPolicy」としました。

$ aws iam create-policy \
  --policy-name GreengrassSSMAgentComponentPolicy \
  --policy-document file://ssm-agent-component-policy.json

IAM ポリシーが作成できたら、Greengrass の IAM Role である GreengrassV2TokenExchangeRole にアタッチします。ポリシーの ARN は利用環境に合わせてください。

$ aws iam attach-role-policy \
  --role-name GreengrassV2TokenExchangeRole \
  --policy-arn arn:aws:iam::[YOUR_AWS_ACCOUNT_ID]:policy/GreengrassSSMAgentComponentPolicy

34-attach-iam-role-to-GreengrassV2TokenExchangeRole

AWS Systems Manager Agent のインストール

今回利用するコンポーネントはエージェントのインストールも自動で行ってくれるので、エージェントの事前インストールは必要ありません。 もし事前に手動でインストールする場合は下記ページを参考にしてください。(下記は Ubuntu 環境へのインストール手順です)

(事前にエージェントをインストールする場合は)上記ドキュメントにある通り、Snap パッケージとしてインストールします。

$ sudo snap install amazon-ssm-agent --classic

AWS Systems Manager Agent コンポーネントのデプロイ

最後に AWS Systems Manager Agent コンポーネントをデプロイを行います。
まず、AWS IoT Greengrass のコンソールで「コンポーネント」の画面から「パブリックコンポーネント」タブを開いて、「aws.greengrass.SystemsManagerAgent」コンポーネントをクリックします。

01-select-ssm-component

「aws.greengrass.SystemsManagerAgent」コンポーネントの画面が開いたら、そのまま「デプロイ」ボタンをクリックしてデプロイ作業に進みます。

02-deploy-ssm-component

デプロイする対象を選択します。今回は既存のものを選択しました。

03-select-deploy-device

ターゲットの指定は必要に応じて変更してください。

04-set-target

次の画面でデプロイするコンポーネントを選択します。下側の「パブリックコンポーネント」に「aws.greengrass.SystemsManagerAgent」にチェックが入っていることを確認します。

05-set-public-component

次の画面でコンポーネントの設定を行いますので、「aws.greengrass.SystemsManagerAgent」を選択して「コンポーネントを設定」ボタンをクリックします。

06-config-component

「マージする設定」欄に要件に応じた内容で設定します。

40-no-intall-ssm-agent-deployment-2

AWS Systems Manager がインストールされていない場合は下記の内容で設定します。

{
"SSMRegistrationRole": "SSMServiceRole",
"SSMResourceTags": [
  {
    "Key": "Greengrass",
    "Value": "true"
  }
],
"SSMOverrideExistingRegistration": false
}
  • SSMRegistrationRole:AWS Systems Manager を利用するために最初に作成した IAM Role 名
  • SSMResourceTags:AWS Systems Manager に登録されたノードを管理するタグ(オプション)
  • SSMOverrideExistingRegistration:コンポーネントではなく手動でエージェントを実行している場合、エージェント登録を上書きします。
    • エージェントは未インストールなので false にセットします。

事前に手動でエージェントをインストールした場合は "SSMOverrideExistingRegistration": true とします。

公式ドキュメントには SSMOverrideRegistration というパラメータが書かれており、SSMOverrideExistingRegistrationに関する記載がありません。
しかし、コンポーネントのデフォルト設定では、SSMOverrideExistingRegistrationが書かれているので、SSMOverrideExistingRegistrationが正しいパラメータになります。
実際に SSMOverrideRegistrationではマネージドインスタンスとして登録できないケースがありました。

{
  "SSMRegistrationRole": "SSMServiceRole",
  "SSMResourceTags": [
    {
      "Key": "Greengrass",
      "Value": "true"
    }
  ],
  "SSMOverrideExistingRegistration": true
}

コンポーネントの設定ができたら「変更済み?」列が「Yes」になります。

08-yes-next

「詳細設定を構成」の画面では、IoT Jobs の設定です。必要に応じて設定してください。
(今回はそのまま次へ進みました)

09-jobs-config

最後にこれまでの設定をレビューして問題無ければ「デプロイ」をクリックします。

10-review-and-deploy

コンポーネントのデプロイは IoT Jobs の機能が使われるので、デプロイ開始後は「デプロイ」画面の「IoT ジョブ」のリンクから実行状況が確認できます。

11-jobs-result

ジョブのステータスが「成功しました」になればデプロイ完了です。

12-job-ok

デプロイの途中状況や結果は、デバイス側のログからも確認可能です。デバイス側はデフォルトで /greengrass/v2/logs/greengrass.log に実行結果が表示されます。 下記のようなログが出ていればデプロイ成功です。

2021-12-09T07:19:52.254Z [INFO] (Thread-3) com.aws.greengrass.deployment.IotJobsHelper: Job status update was accepted. {Status=SUCCEEDED, ThingName=xxxxx, JobId=004a0ffc-xxxxxxxxxxxxxxxx}

/greengrass/v2/logs/aws.greengrass.SystemsManagerAgent.log は、コンポーネント単体のログになります。こちらにもデプロイ時の詳細が出ています。下記のようなログが出ていれば正常にデプロイできています。

2021-12-09T07:19:38.253Z [INFO] (Copier) aws.greengrass.SystemsManagerAgent: Startup script exited. {exitCode=0, serviceName=aws.greengrass.SystemsManagerAgent, currentState=STARTING}

デプロイ結果の確認

正常にコンポーネントのデプロイが完了していれば、AWS IoT Greengrass のコンソール側から確認が可能です。対象のデプロイ画面にある「コアデバイス名」のリンクからコアデバイスの詳細画面を開きます。

13-core-device

正常にコンポーネントがデプロイされてAWS Systems Manager に登録されると、下記画像のように「Systems Manager インスタンス」という項目が新たに表示されるようになります。

14-core-device-ssm-instance

リンクをクリックすると、AWS Systems Manager の画面を開くことができます。
フリートマネージャーの画面で、登録されたデバイスを確認することができました。エージェント経由で OS の種類やデバイスのIPアドレスを確認することができます。

15-fleet-manager

今回のアップデートの内容は以上までとなりますが、せっかくなので AWS Systems Manager を使って少し遊んでみたいと思います。

AWS Systems Manager からコマンドを実行する

それでは、試しに「Run Command」を試してみたいと思います。先程の画面で「インスタンスアクション」のプルダウンから「Execute Run command」をクリックすると、Run Command の画面が開きます。

16-pulldown-run-command

AWS Systems Manager のメニューから「Run Command」をクリックしても同じ画面に遷移できます。

16-2-run-command

Run Command の画面が開いたら、実行したいコマンドドキュメントを指定します。
今回は Linux のコマンドを実行したいので、検索画面に「RunShellScript」といったワードで検索して対象のコマンドドキュメントを探します。

17-query-command

検索で見つかった「AWS-RunShellScript」 というコマンドドキュメントを選択して、「コマンドのパラメータ」というテキストエリアに実行したいコマンドを入力します。

18-input-commands

今回は下記のようなコマンドを実行してみたいと思います。

echo "##### release info #####"
lsb_release -a

echo "##### hostname #####"
hostname

次にコマンドを実行するターゲットを指定します。コンポーネントのデプロイ時に対象デバイスにタグを付けたので、そのタグが付いているデバイスを対象にしたいと思います。
今回は1台だけですが、同じタグの付いた複数のデバイスをターゲットにすることも可能になります。(複数のタグがデバイスに付いていれば、ターゲットの指定でも複数のタグをセットすることが可能です)

最後に「Add」ボタンをクリックするのを忘れないようにしましょう。

19-set-target-tag

タグの指定ができれば、下記のような表示になります。

20-set-target-tag-submit

その他の出力オプションやSNS通知などの設定はデフォルトのままにして「実行」します。

21-default-output-run-command

コマンドの実行中は下記のように「実行中」のステータスになります。ステータスは実行ターゲット毎に表示されます。(今回は1台だけなので1つしか表示されていません)

22-output-run-command

コマンドの実行が終わるとステータスが「成功」になります。

23-success-run-command

コマンドの実行結果はコンソール上で確認可能です。対象のインスタンス ID をクリックするか、「出力の表示」をクリックします。

24-check-output

出力画面で、標準出力と標準エラー出力の内容を確認できます。
今回実行した lsb_release コマンドはポイントリリースの適用状態を表示するものですが、LSBパッケージがインストールされていないと、下記のようにエラーも返ります。

25-result-output

参考までに、デバイス上で同じコマンドを実行すると下記のようになります。

$ lsb_release -a

No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.3 LTS
Release:	20.04
Codename:	focal

AWS Cloudwatch Logs に結果を出力する

AWS Systems Manager のコンソールでは、コマンド実行結果の最初の2500文字までしか表示することができません。 2500文字を超える場合、実行結果の全体を確認するには Amazon S3 や AWS CloudWatch Logs から結果を確認する必要があります。
Amazon S3 への出力は以前から対応していましたが オブジェクトをダウンロードして確認するなど少々面倒な部分がありました。AWS CloudWatch Logs であればコンソールでほぼリアルタイムに気軽に確認できるので便利です。

AWS Cloudwatch Logs 出力に必要な IAM の権限を追加

これまでの設定では AWS Cloudwatch Logs に出力する権限が無いので、最初に作った IAM Role SSMServiceRole に AWS マネージドポリシーである CloudWatchAgentServerPolicy ポリシーを追加でアタッチします。

$ aws iam attach-role-policy \
    --role-name SSMServiceRole \
    --policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy

追加したポリシー CloudWatchAgentServerPolicy は下記のような権限を持っているので、実行結果をログストリームに書き込んだり、指定されたロググループが無ければ新規にロググループを作成することができるようになります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData",
                "ec2:DescribeVolumes",
                "ec2:DescribeTags",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams",
                "logs:DescribeLogGroups",
                "logs:CreateLogStream",
                "logs:CreateLogGroup"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameter"
            ],
            "Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*"
        }
    ]
}

27-add-policy-for-put-log-cloudwatch-logs

IAM の設定ができたら、コマンド実行の「出力オプション」で下記のようにロググループを指定せずにコマンドを実行した場合を見てみます。

21-output-config

この場合は、下記のように AWS CloudWatch Logs に /aws/ssm/SystemsManagerDocumentName という形式で自動的にロググループを作成します。今回は /aws/ssm/AWS-RunShellScript というロググループになります。

ログストリームは下記のようになります。

  • CommandID/InstanceID/PluginID/stdout
  • CommandID/InstanceID/PluginID/stderr

28-list-log-streams

ログストリームの中身を見ると、コマンドの実行結果を確認することができました。

29-cwlogs-stdout

こちらは標準エラー出力の結果です。標準出力と標準エラー出力でそれぞれのログストリームに結果が書き込まれていることが確認できました。

30-cwlogs-stderr

コマンド実行時にロググループを指定することもできます。存在しないロググループ名であれば、自動的に作成されます。

32-output-custom-log-group-name

コマンドを実行すると、指定したロググループ(greengrass-device-myubuntu-ssm )が作成されてログストリームを確認することができました。

33-custom-log-groups

AWS CloudWatch Logs への出力を有効にしていると、コマンドの実行結果にあるリンクから直接 AWS CloudWatch Logs の画面に遷移することもできます。
下記のように、標準出力と標準出力エラーのリンクがそれぞれのログストリームに対応しています。

31-access-cwlogs-from-command-result

最後に

今回のアップデートでは、AWS IoT Greengrass のコアデバイスに対して、より簡単に AWS Systems Manager が利用できるようになったというものです。

オンプレミスサーバや IoTデバイス における AWS Systems Manager の利用自体は以前から可能でしたが、AWS IoT Greengrass を利用していれば簡単に導入できるようになったので、ぜひ試していただければと思います。