前にSession Managerを使用してEC2へ接続する方法を記事にした際に「Lambda関数からEC2にコマンドを実行できるのでは?」と思ったことを検証してみた。AWS Lambda関数を使用してEC2インスタンスにApacheをインストールし、WEBサーバを構築することができたため、気になる人は読んでほしい。ネタみたいな記事だが個人的に結構面白かった。
EC2環境
まずEC2インスタンスを以下設定にて起動する。
項目 | 設定値 |
---|---|
名前 | 任意の名前 |
Amazon マシンイメージ (AMI) | Amazon Linux 2023 |
インスタンスタイプ | t2.micro |
キーペア | 任意のキーペア |
VPC | 任意のVPC |
サブネット | パブリックサブネット |
パブリックIPの自動割り当て | 有効化(後で無効化) |
セキュリティグループ | タイプ:SSH、ソースタイプ:自分のIP |
ストレージ | gp3、8GiB |
IAM インスタンスプロファイル | 事前に作成したIAMロール(AmazonSSMManagedInstanceCoreポリシーをアタッチ) |
事前準備
以前の記事で紹介したとおりSSMできる環境を準備しておく。
今回EC2で設定が必要なのはIAMロール(AmazonSSMManagedInstanceCoreポリシー)をアタッチするのみ。設定方法の詳細は上記の記事を参照してほしい。また、Amazon Linux 2023はデフォルトでSSM Agentがインストールされているためインストール不要となる。あと、パブリックサブネットに配置しているためVPCエンドポイントの設定も不要。
やること
Lambda関数でEC2にApacheをインストールし、WEBサーバを構築する。
現状確認
Session Managerにて接続しApacheがインストールされていないことを確認。
sh-5.2$ sudo systemctl status httpd
Unit httpd.service could not be found.
Lambda関数の設定
関数の作成
まずLambda関数を作成する。以下設定にて「関数の作成」をクリック
項目 | 設定値 |
---|---|
関数名 | 任意の名前 |
ランタイム | Python 3.12 |
アーキテクチャ | x86_64 |
アクセス権限 | 設定不要 |
※後からポリシーを付与 |
IAMポリシーの作成
Lamdba実行ロールがコマンドを送ることができる権限を持つIAMポリシーを作成する。後にLambda実行ロールにアタッチする。
IAMポリシーは以下のとおり。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"ssm:SendCommand"
],
"Resource": [
"arn:aws:ec2:*:<account_id>:instance/*",
"arn:aws:ssm:*::document/AWS-RunShellScript"
]
},
{
"Effect": "Allow",
"Action": [
"ssm:GetCommandInvocation",
"ssm:ListCommandInvocations"
],
"Resource": "*"
}
]
}
Lambda実行ロールにポリシーをアタッチ
作成したLamdbaの「設定」タブから「アクセス権限」タブをクリック。実行ロールからロール名をクリックして対象のIAMロールを表示させる。
IAMロールが表示されたら、「許可を追加 > ポリシーをアタッチ 」から先ほど作成したIAMポリシーをアタッチする。
コード作成
今回はboto3のsend_commandを使用してコードを作成する。
send_command - Boto3 1.34.115 documentation
まずはコマンドが実行できているかテスト
以下コードを実行
import json
import boto3
def lambda_handler(event, context):
# SSMクライアントの作成
ssm_client = boto3.client('ssm')
# コマンドの実行
response = ssm_client.send_command(
InstanceIds=[
'<instance_Id>',
],
DocumentName='AWS-RunShellScript',
Parameters={
'commands': [
'echo "Hello AWS"',
]
}
)
print(response["Command"]["Parameters"])
return {
'statusCode': 200,
'body': json.dumps('Success!')
}
実行結果
実行できていることを確認。
{
"statusCode": 200,
"body": "\\"Success!\\""
}
# レスポンス(コマンドのみ抜粋)
{'commands': ['echo "Hello AWS"']}
複数のコマンドを実行できるように修正
Apacheをインストールして有効にするには複数のコマンドを実行する必要があるためコマンドの数だけコマンド実行をループするよう修正。
import json
import boto3
def lambda_handler(event, context):
# SSMクライアントの作成
ssm_client = boto3.client('ssm')
# コマンドを定義
commands = [
'echo "Hello AWS"',
'echo "Hello Thiamai"'
]
# コマンドの実行
for command in commands:
response = ssm_client.send_command(
InstanceIds=[
'i-05d78cf03b58a6dc1',
],
DocumentName='AWS-RunShellScript',
Parameters={
'commands': [
command
]
}
)
print(response["Command"]["Parameters"])
return {
'statusCode': 200,
'body': json.dumps('Success!')
}
実行結果
ループしていることが確認できる
{
"statusCode": 200,
"body": "\\"Success!\\""
}
# レスポンス
{'commands': ['echo "Hello AWS"']}
{'commands': ['echo "Hello Thiamai"']}
Apacheをインストールするようコードを修正
先ほど紹介したループするコードのコマンド部分のみ以下のとおり修正
# コマンドを定義
commands = [
'sudo dnf update -y',
'sudo dnf install httpd -y',
'sudo systemctl start httpd',
'sudo systemctl enabled httpd'
]
実行結果
全てのコマンドが実行されていることを確認できる。3秒くらいで終了した。
# レスポンス
{'commands': ['sudo dnf update -y']}
{'commands': ['sudo dnf install httpd -y']}
{'commands': ['sudo systemctl start httpd']}
{'commands': ['sudo systemctl enabled httpd']}
Apacheがインストールされていることを確認
sudo systemctl status httpd
でApacheがインストールされており、稼働していることを確認できる。
sh-5.2$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; preset: disabled)
Active: active (running) since Thu 2024-05-30 14:17:00 UTC; 4s ago
Docs: man:httpd.service(8)
Main PID: 27377 (httpd)
Status: "Started, listening on: port 80"
Tasks: 177 (limit: 1114)
Memory: 12.9M
CPU: 65ms
CGroup: /system.slice/httpd.service
├─27377 /usr/sbin/httpd -DFOREGROUND
├─27379 /usr/sbin/httpd -DFOREGROUND
├─27380 /usr/sbin/httpd -DFOREGROUND
├─27381 /usr/sbin/httpd -DFOREGROUND
└─27382 /usr/sbin/httpd -DFOREGROUND
May 30 14:17:00 ip-10-0-14-94.ec2.internal systemd[1]: Starting httpd.service - The Apache HTTP Server...
May 30 14:17:00 ip-10-0-14-94.ec2.internal systemd[1]: Started httpd.service - The Apache HTTP Server.
May 30 14:17:00 ip-10-0-14-94.ec2.internal httpd[27377]: Server configured, listening on: port 80
パブリックIPにアクセス
「It works!」と表示されており問題なく稼働している。
まとめ
ネタではあるがLamdba関数経由でEC2にApacheをインストールし、WEBサーバを構築することができた。少し面白い使い方も思いついているためまた記事にする。