Raspberry Pi 5をセットアップ後、Systems Managerに登録して、AWSからコマンドを実行する
AWS Systems ManagerはEC2インスタンスだけでなく、ハイブリッドおよびマルチクラウド環境下のサーバも管理することができます。
本ページでは、Raspberry Pi 5をオンプレサーバに見立てて、Systems Managerに登録します。
登録後、Systems Managerの機能を使用して、AWS側からRaspberry Pi 5ににおいてコマンドを実行します。
構築する環境
Raspberry Pi 5の初期セットアップを行います。
具体的には以下の通りです。
- 必要な物品の調達
- OSインストール
- 組み立てと初回起動
なおRaspberry PiにインストールするOSはRaspberry Pi OSとします。
またOSインストール等の作業はMacbook Air(M1, 2020) Sonoma 14.3.1を使用します。
Raspberry PiをSystems Managerで管理するために、SSMハイブリッドアクティベーションを作成します。
用意したアクティベーションIDとコードを使用しつつ、Raspberry PiにSSM Agentをインストールします。
Systems ManagerでRaspberry Piが管理できるようになった後は、Systems Managerの機能を使用して、Raspberry Piにおいてコマンドを実行します。
今回は検証用ということで、テストファイルを作成するコマンドを実行します。
CloudFormationテンプレートファイル
上記の構成において、AWS側の構成に関しては、CloudFormationを使用して構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/152
Raspberry Pi 5初回セットアップ
必要な物品の調達
今回、私は以下の物品をAmazonで購入しました。
Raspberry Pi 5
1つ目はRaspberry Pi 5本体です。
今回はメモリが8GBタイプのものを購入しました。
SDカード
2つ目はSDカードです。
容量は128GBのものを選びました。
ケース
3つ目はRaspberry Piのケースです。
基盤を剥き出しにした状態で運用することは好ましくなく、またRaspberry Pi 5は発熱が激しいという話を聞いたため、冷却用ファン付きケースを用意しました。
Micro HDMI to HDMI変換アダプタ
4つ目はMicro HDMI to HDMI変換アダプタです。
Raspberry Pi 5が持っている映像用ポートはMicro HDMIです。
手元には同ポート用のケーブルがなかったため、通常のHDMIケーブルに変換するためのアダプタを購入しました。
OSインストール
SDカード準備
Raspberry PiはSDカードをストレージとして使用します。
ですからSDカードにOSをインストールします。
まず梱包されているSDカードを取り出します。
micro SDカードにアダプターを装着します。
最近のMacbook AirにはSDカード用のスロットがないため、Macbook用のドックを使用します。
以下の通りにMacbookとSDカードを接続します。
Raspberry Pi Imagerを使用してSDカードにOSインストール
Macbookを使用して、SDカードにOSをインストールします。
OSインストールはRaspberry Pi Imagerを使用します。
https://www.raspberrypi.com/software/
Raspberry Pi Imagerを使用するためには、同ソフトウェアをMacbookにインストールする必要があります。
上記ページからインストーラをダウンロードします。
ダウンロードされたインストーラをダブルクリックし、Raspberry Pi ImagerをApplicationsにドラッグアンドドロップします。
これでRaspberry Pi Imagerがインストールされます。
インストールされたRaspberry Pi Imagerを起動します。
3つの項目を指定します。
左の項目はOSを起動するデバイスに関するものです。
「Rasberry Pi 5」を選択します。
真ん中の項目はOSの種類やOSのビット数に関するものです。
「Raspberry Pi OS (64-bit)」を選択します。
右の項目はOSをインストールするSDカードに関するものです。
先ほど接続したSDカードを選択します。
3項目の選択が完了した後に、「次へ」を押下すると、追加の設定変更に関するページ(Use OS customization?)が表示されます。
「設定を編集する」を押下します。
3つのタブが表示されます。
それぞれ以下の通りに設定しました。
「保存」を押下すると、再びUse OS customization?のページが表示されますので、「はい」を押下して、設定を確定させます。
するとSDカードへOSインストールが開始されます。
しばらく待つとOSインストールが完了します。
この表示が出た後に、SDカードを取り外します。
ケース組み立て
Raspberry Piを箱から出します。
次にケースを箱から取り出します。
ケースがネジで固定されていますが、取り外すと2つに分解できます。
ケースの中にはネジやヒートシンクがパッケージングされています。
4つのヒートシンクをRaspberry Piに装着します。
ヒートシンクは両面テープで固定される形となります。
下部ケースにネジを装着します。
このネジはRaspberry Piの基盤をケースに固定するためのものです。
このネジにRaspberry Piの穴を通します。
さらに基盤の上からネジを装着し、ケースと基盤を固定します。
上部ケースのファン用ケーブルを基盤に接続します。
接続口はカバーがされているため、取り外す必要があるとにご注意ください。
ケースをネジで固定してケースの組み立ては完成です。
初回起動
先ほどOSをインストールしたSDカードをRaspberry Piに接続します。
加えてケーブル類を接続します。
マウス・キーボードをUSBポートに接続します。
Micro HDMI変換アダプタを使用してHDMIケーブルを接続します。
電源ケーブルをType-Cポートに接続します。
電源ケーブルを接続すると自動的にRasberry Piが起動します。
起動しない場合は側面のボタンを押下してください。
Raspberry PiをSystems Managerに登録する
Raspberry PiをSystems Managerに登録するためには、以下の手順を踏みます。
- ハイブリッドアクティベーションを作成する。
- 用意したアクティベーションIDとコードを使用しつつ、Raspberry PiにSSM Agentをインストールする。
ハイブリッドアクティベーションを作成する
ハイブリッドアクティベーションを作成する方法は、以下のAWS公式ページで説明されています。
ここではCloudFormationを使用して、ハイブリッドアクティベーションを作成する上でのポイントをご紹介します。
SSM用IAMサービスロールを作成する
以下の通り、ハイブリッドアクティベーションを作成するためには、SSM用のIAMロールを作成する必要があるとされています。
ハイブリッドおよびマルチクラウド環境の非 EC2 (Amazon Elastic Compute Cloud) マシンでは、AWS Systems Manager サービスと通信するために AWS Identity and Access Management (IAM) サービスロールが必要です。ロールは、Systems Manager サービスに AWS Security Token Service (AWS STS) AssumeRole の信頼を付与します。
ステップ 1: ハイブリッドおよびマルチクラウド環境に IAM サービスロールを作成する
Resources:
SSMServiceRole:
Type: AWS::IAM::Role
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ssm.amazonaws.com
Condition:
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
ArnEquals:
aws:SourceArn: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:*"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Code language: YAML (yaml)
上記のページを参考に、IAMロールを作成しました。
本ロールにAWS管理ポリシーAmazonSSMManagedInstanceCoreをアタッチしているところがポイントです。
CloudFormationカスタムリソースを使用して、アクティベーションを作成/削除する
ハイブリッドアクティベーションを作成すると、アクティベーションIDとアクティベーションコードが返されます。
これらはRaspberry PiにSSM Agentインストールする際に使用します。
マネージメントコンソールやAWS CLI等を使用することで、ハイブリッドアクティベーションの作成/削除は可能です。
しかしCloudFormationには該当するリソースが用意されていないため、直接アクティベーションを作成することはできません。
ですからCloudFormationカスタムリソースを使用して、スタック作成/削除時にLambda関数を呼び出し、アクティベーションを作成/削除します。
Resources:
CustomResource:
Type: Custom::CustomResource
Properties:
ServiceToken: !GetAtt Function.Arn
Function:
Type: AWS::Lambda::Function
Properties:
Architectures:
- !Ref Architecture
Environment:
Variables:
PREFIX: !Ref Prefix
REGION: !Ref AWS::Region
SSM_SERVICE_ROLE: !Ref SSMServiceRole
Code:
ZipFile: |
import boto3
import cfnresponse
import os
prefix = os.environ['PREFIX']
region = os.environ['REGION']
ssm_service_role = os.environ['SSM_SERVICE_ROLE']
CREATE = 'Create'
DELETE = 'Delete'
response_data = {}
physical_resource_id = ''
key_name_id = 'ActivationId'
key_name_code = 'ActivationCode'
ssm_client = boto3.client('ssm', region_name=region)
def lambda_handler(event, context):
print(event)
try:
if event['RequestType'] == CREATE:
ssm_response = ssm_client.create_activation(
DefaultInstanceName=prefix,
IamRole=ssm_service_role
)
physical_resource_id = ssm_response[key_name_id]
response_data[key_name_id] = ssm_response[key_name_id]
response_data[key_name_code] = ssm_response[key_name_code]
elif event['RequestType'] == DELETE:
physical_resource_id = event['PhysicalResourceId']
ssm_response = ssm_client.delete_activation(
ActivationId=physical_resource_id
)
cfnresponse.send(
event=event,
context=context,
responseStatus=cfnresponse.SUCCESS,
responseData=response_data,
physicalResourceId=physical_resource_id
)
except Exception as e:
print(e)
cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
FunctionName: !Sub "${Prefix}-function"
Handler: !Ref Handler
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Timeout: !Ref Timeout
FunctionRole:
Type: AWS::IAM::Role
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: LambdaFunctionPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- iam:PassRole
- ssm:CreateActivation
- ssm:DeleteActivation
Resource: "*"
Code language: YAML (yaml)
CloudFormationカスタムリソースに関する基本的な事項については以下のページをご確認ください。
今回はランタイム環境がPython3.12のLambda関数を実行します。
実行するコードの内容を確認します。
boto3のSSM用のクライアントオブジェクトを作成後、スタック作成時はcreate_activationメソッド、スタック削除時はdelete_activationメソッドを実行します。
それぞれハイブリッドアクティベーションを作成/削除します。
スタック作成時、つまりアクティベーション作成時は、アクティベーションIDおよびアクティベーションコードが取得できます。
これらをcfnresponse.send関数を実行する際の引数responseDataの一部として渡します。
こうすることによって、これらをCloudFormationスタックのOutputsに設定し、スタック作成後に値を確認することができます。
加えてアクティベーションIDを同関数を実行する際の引数physicalResourceIdに指定します。
これはスタック削除時、つまりアクティベーション削除時にアクティベーションIDを参照できるようにするためです。
このアイデアは以下のページを大いに参考にしました。
https://dev.classmethod.jp/articles/on-premise-ubuntu-cloudfomation-aws-systems-manager-activation/
この設定の優れている点は、スタック削除時もこの値を参照することができることです。
先述のresponseDataの値はCloudFormationテンプレートファイル側からはアクセス可能ですが、カスタムリソース側からはスタック削除時にアクセスできません。
しかしphysicalResourceIdはスタック作成時に設定した値をスタック削除時にも参照することができます。
よってphysicalResourceIdにアクティベーションIDを格納することによって、スタック削除時にこのIDを参照して、アクティベーションを削除することができます。
CloudFormationスタック作成
AWS CLIを使用して、CloudFormationスタックを作成します。
上記のテンプレートファイルを任意のS3バケットに設置した上で、以下のコマンドを実行します。
aws cloudformation create-stack \
--stack-name fa-152-01 \
--template-url https://[bucket-name].s3.[region].amazonaws.com/fa-152/fa-152-01.yaml \
--capabilities CAPABILITY_IAM
Code language: Bash (bash)
スタック作成の詳細については、以下のページをご確認ください。
作成されたリソースを確認します。
IAMロールを確認します。
確かにIAMロールが作成されています。
このIAMロールはSSM用サービスロールです。
Lambda関数を確認します。
正常に関数が作成されています。
この関数の実行ログを確認します。
確かに関数が実行されています。
つまりCloudFormationカスタムリソースによって、スタック作成時に自動的にこの関数が呼び出されたということです。
ログ内のレスポンスの内容を見ると、DataにハイブリッドアクティベーションのIDとコードが設定されてることがわかります。
加えてPhysicalResourceIdの値がアクティベーションIDであることもわかります。
Dataに両データを設定しているため、CloudFormationのOutputsでも確認することができます。
確かにアクティベーションIDとコードが表示されています。
Systems Managerを確認します。
確かにハイブリッドアクティベーションが作成されています。
このようにCloudFormationカスタムリソースを使用することによって、自動的にハイブリッドアクティベーションを作成することが可能です。
Raspberry PiにSSM Agentをインストールする
Raspberry PiにSSM Agentをインストールする方法は以下のページで紹介されています。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-install-managed-linux.html
今回はRaspberry Piで以下のコマンドを実行しました。
sudo apt-get -y update
sudo apt-get -y upgrade
sudo apt-get -y install libc6:armhf
mkdir /tmp/ssm
curl https://amazon-ssm-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/debian_arm/ssm-setup-cli -o /tmp/ssm/ssm-setup-cli
sudo chmod +x /tmp/ssm/ssm-setup-cli
sudo /tmp/ssm/ssm-setup-cli -register -activation-code "[activation-code]" -activation-id "[activation-id]" -region "ap-northeast-1"
Code language: Bash (bash)
下4行は上記のページで紹介されていたコマンドで、上4行は私が追加したコマンドです。
これは私の手元の環境ですと、依存関係のエラーが発生し、SSM Agentを正常にインストールできなかったためです。
最後のコマンドの引数として、先ほど確認したハイブリッドアクティベーションのIDとコードを指定します。
なお上記コマンドを実行する方法ですが、私はRaspberry PiにSSHして実行しました。
Raspberry Piにマウス・キーボードを直接接続していれば上記コマンドを実行することも可能ですが、これではコマンドを手打ちしなければならなくなります。
ですからRaspberry Piの無線LAN側に設定されたIPアドレスを確認後(nmcli device showコマンド等)、同アドレス向けにSSHして上記コマンドをコピペして実行することとしました。
SSM Agentのインストールが正常に完了すると、同エージェントが自動的に起動します。
awstut@raspberrypi:~ $ sudo systemctl status amazon-ssm-agent
● amazon-ssm-agent.service - amazon-ssm-agent
Loaded: loaded (/lib/systemd/system/amazon-ssm-agent.service; enabled; preset: enabled)
Active: active (running) since Sun 2024-03-10 14:20:20 JST; 28s ago
Main PID: 3709 (amazon-ssm-agen)
Tasks: 19 (limit: 9250)
CPU: 309ms
CGroup: /system.slice/amazon-ssm-agent.service
├─3709 /usr/bin/amazon-ssm-agent
└─3725 /usr/bin/ssm-agent-worker
Mar 10 14:20:20 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:20 INFO [amazon-ssm-agent] amazon-ssm-agent - v3.2.2303.0
Mar 10 14:20:20 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:20 INFO [amazon-ssm-agent] OS: linux, Arch: arm
Mar 10 14:20:20 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:20 INFO [amazon-ssm-agent] Starting Core Agent
Mar 10 14:20:20 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:20 INFO [CredentialRefresher] credentialRefresher has started
Mar 10 14:20:20 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:20 INFO [CredentialRefresher] Starting credentials refresher loop
Mar 10 14:20:20 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:20 INFO [CredentialRefresher] Credentials ready
Mar 10 14:20:20 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:20 INFO [CredentialRefresher] Next credential rotation will be in 29.9927887592 mi>
Mar 10 14:20:21 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:21 INFO [amazon-ssm-agent] [LongRunningWorkerContainer] [WorkerProvider] Worker ss>
Mar 10 14:20:21 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:21 INFO [amazon-ssm-agent] [LongRunningWorkerContainer] [WorkerProvider] Worker ss>
Mar 10 14:20:22 raspberrypi amazon-ssm-agent[3709]: 2024-03-10 14:20:21 INFO [amazon-ssm-agent] [LongRunningWorkerContainer] Monitor long running worke>
Code language: Bash (bash)
改めてAWS側を確認します。
SSM Feet ManagerのManaged Nodeのページを確認します。
確かに1台Managed Nodeが追加されています。
アクティベーションIDを見ると、確かに先ほどCloudFormationカスタムリソースによって作成されたものであることがわかります。
このようにハイブリッドアクティベーションを使用しつつSSM Agentをインストールすることによって、Raspberry PiをSystems Managerに登録することができます。
AWS Systems Managerを使用して、Raspberry Piにおいてコマンドを実行する
SSM関連付けを作成する
前項まででRaspberry PiをSystems Managerで管理できる状態になりました。
本ページでは管理の一例として、Systems Managerの機能を使用して、Raspberry Piにおいてコマンドを実行します。
ここでもCloudFormationを使用して、SSM関連付けを作成し、Run Commandで実行します。
Resources:
RunShellScriptAssociation:
Type: AWS::SSM::Association
Properties:
AssociationName: !Sub "${Prefix}-shellscript-association"
Name: AWS-RunShellScript
Parameters:
commands:
- "touch /tmp/test.txt"
Targets:
- Key: InstanceIds
Values:
- !Ref NodeId
WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)
ターゲットに対してSSMドキュメントAWS-RunShellScriptを実行する内容です。
ポイントは2点です。
1点目は実行するスクリプトの内容です。
今回は検証ということで、touchコマンドを使用して、/tmpディレクトリにtest.txtを作成します。
2点目はインスタンスの指定方法です。
Targetsプロパティで対象のインスタンスを指定します。
通常、本プロパティにはEC2インスタンスのIDを指定しますが、今回はハイブリッドアクティベーションを有効化したRaspberry Piに割り当てられたManaged NodeのIDを指定します。
今回は「mi-0eb22a29750efc73c」です。
CloudFormationスタック作成
今回もAWS CLIを使用して、CloudFormationスタックを作成します。
上記のテンプレートファイルを任意のS3バケットに設置した上で、以下のコマンドを実行します。
aws cloudformation create-stack \
--stack-name fa-152-02 \
--template-url https://[bucket-name].s3.[region].amazonaws.com/fa-152/fa-152-02.yaml
Code language: Bash (bash)
作成されたリソースを確認します。
SSM State Managerを確認します。
確かにManaged NodeであるRaspberry PiとSSMドキュメントAWS-RunShellScriptとの間にアソシエーションが作成されています。
SSM Run Commandを確認します。
こちらを見るとRaspberry Piに対してRun Commandが実行されて、正常に完了したことがわかります。
つまりState Managerを通じてRun Commandが実行されたということです。
最後にRaspberry Piにアクセスして、Run Commandの実行結果を確認します。
awstut@raspberrypi:~ $ ls /tmp
ssh-XXXXXX1IKqpP
ssm
systemd-private-17099a81f2ff43059a22854d9f6f1f63-bluetooth.service-Z7slQf
systemd-private-17099a81f2ff43059a22854d9f6f1f63-ModemManager.service-SWnEDs
systemd-private-17099a81f2ff43059a22854d9f6f1f63-systemd-logind.service-44pZrv
systemd-private-17099a81f2ff43059a22854d9f6f1f63-systemd-timesyncd.service-kTxxXi
test.txt
tmp.iATINIcQGt
Code language: Bash (bash)
確かにRaspberry Piの/tmpディレクトリにtest.txtが配置されています。
Systems Managerの機能を使用して、Raspberry Piにおいてコマンドを実行できたことが確認できました。
まとめ
Raspberry Pi 5の初期セットアップ方法を確認しました。
CloudFormationカスタムリソースを使用することで、SSMハイブリッドアクティベーションの作成/削除方法を確認しました。
Raspberry Piにアクティベーションを使用しつつ、SSM Agentをインストールすることで、Systems Managerに登録する方法を確認しました。
Raspberry PiをSystems Managerで管理する一例として、Systems Managerの機能を使用して、Raspberry Piにおいてコマンドを実行する方法を確認しました。