AWS CLIを使ってAWS LambdaでPythonスクリプトを動かしてみましたので、書き残したいと思います。
AWS CLIの設定は以前書いた「IAM Identity Centerで運用管理ユーザのAWS CLIが使えるまで」をご参考ください。
実行ロールを作成
Lambda実行できるようにロールを付けます
まず次のようなawsコマンドを利用してロールを作成します。
aws iam create-role --role-name lambda-ex --assume-role-policy-document '{"Version": "2012-10-17","Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
実行結果は次のようになります。
{
"Role": {
"Path": "/",
"RoleName": "lambda-ex",
"RoleId": "AROAUNUO7TBJ7ZDKPVKTF",
"Arn": "arn:aws:iam::123456789012:role/lambda-ex",
"CreateDate": "2024-01-10T15:26:21+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
}
}
次に以下のコマンドでロールにLambdaのポリシーを付与します。
aws iam attach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
特にエラーができれば結果は何も表示されません。
Lambda関数を作成
まず、実行するPythonのスクリプトを下記書きます。
次のように簡単な200応答をhello-world.py
として保存します。
import json
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
次に、下記コマンドhello-world.py
をfuncion.zipとして圧縮します。
zip function.zip hello-world.py
最後に、function.zipで配置しているディレクトリで、次のコマンドを実行してLambdaの関数を作成します。
aws lambda create-function \
--function-name my-function \
--zip-file fileb://function.zip \
--handler hello-world.lambda_handler \
--runtime python3.11 \
--role arn:aws:iam::123456789012:role/lambda-ex
実行結果は次のようになると思われます。
{
"FunctionName": "my-function",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:my-function",
"Runtime": "python3.11",
"Role": "arn:aws:iam::123456789012:role/lambda-ex",
"Handler": "hello-world.lambda_handler",
"CodeSize": 311,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2024-01-10T15:31:03.432+0000",
"CodeSha256": "UUzgcbLtWmzeQ6r1LRb7njgIEjQuasRtzN8rc/tIktA=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "86e16c4b-1b7f-48db-887a-8d5d81997208",
"State": "Pending",
"StateReason": "The function is being created.",
"StateReasonCode": "Creating",
"PackageType": "Zip",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 512
},
"SnapStart": {
"ApplyOn": "None",
"OptimizationStatus": "Off"
},
"RuntimeVersionConfig": {
"RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:a3304f2b48f740276b97ad9c52a9cc36a0bd9b44fecf74d0f1416aafb74e92fc"
},
"LoggingConfig": {
"LogFormat": "Text",
"LogGroup": "/aws/lambda/my-function"
}
}
Lambda関数を実行
次のコマンで上で作ったLambda関数を実行します。
aws lambda invoke --function-name my-function out --log-type Tail
実行結果は次のように表示されます。
{
"StatusCode": 200,
"LogResult": "U1RBUlQgUmVxdWVzdElkOiA4MWI2Nj...",
"ExecutedVersion": "$LATEST"
}
ここのLogResultはBase64でエンコードされますので、以下のコマンドでそれをデコードできます。
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text | base64 -d
そうしますと、実行結果は次のように表示されます。
START RequestId: 3127268e-97e4-4bc7-bffb-40d94604de09 Version: $LATEST
END RequestId: 3127268e-97e4-4bc7-bffb-40d94604de09
REPORT RequestId: 3127268e-97e4-4bc7-bffb-40d94604de09 Duration: 1.19 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 41 MB
ちなみに、参考サイト1では、上記--handler hello-world.lambda_handler
を--handler hello-world.lambda-handler
で書かれてしまったせいで、関数を実行するときに、次のようなエラーになります。
aws lambda invoke --function-name basic-lambda-func out --log-type Tail \
--query 'LogResult' --output text | base64 -d
# 実行結果:
START RequestId: c5dfa447-8295-4e87-ae99-cca4669bdb9f Version: $LATEST
[ERROR] Runtime.HandlerNotFound: Handler 'lambda-handler' missing on module 'hello-world'
Traceback (most recent call last):END RequestId: c5dfa447-8295-4e87-ae99-cca4669bdb9f
REPORT RequestId: c5dfa447-8295-4e87-ae99-cca4669bdb9f Duration: 16.69 ms Billed Duration: 17 ms Memory Size: 128 MB Max Memory Used: 41 MB
ですので、もし上記のようなRuntime.HandlerNotFound
が出ましたら、--handler
の引数を確認してみてください。
Lambda関数を更新
何故かログ取れなかったので、前述hello-world.py
をログ出力するに以下のように変えてみます。
import json
import os
def lambda_handler(event, context):
print('## ENVIRONMENT VARIABLES')
print(os.environ['AWS_LAMBDA_LOG_GROUP_NAME'])
print(os.environ['AWS_LAMBDA_LOG_STREAM_NAME'])
print('## EVENT')
print(event)
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
function.zipも同じように再圧縮します。
zip function.zip hello-world.py
Lambda関数のソースコード更新は次のコマンドになります。
aws lambda update-function-code \
--function-name my-function \
--zip-file fileb://function.zip
実行結果は次のように表示されます。
{
"FunctionName": "my-function",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:my-function",
"Runtime": "python3.11",
"Role": "arn:aws:iam::123456789012:role/lambda-ex",
"Handler": "hello-world.lambda_handler",
"CodeSize": 395,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2024-01-10T15:45:13.000+0000",
"CodeSha256": "ZrphDct4N2aF//kE0tvGJdaEuMCE4QhHQfqQmRxDalU=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "e1291a7a-d1b9-463a-95f5-c5e41a617a8a",
"State": "Active",
"LastUpdateStatus": "InProgress",
"LastUpdateStatusReason": "The function is being created.",
"LastUpdateStatusReasonCode": "Creating",
"PackageType": "Zip",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 512
},
"SnapStart": {
"ApplyOn": "None",
"OptimizationStatus": "Off"
},
"RuntimeVersionConfig": {
"RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:a3304f2b48f740276b97ad9c52a9cc36a0bd9b44fecf74d0f1416aafb74e92fc"
},
"LoggingConfig": {
"LogFormat": "Text",
"LogGroup": "/aws/lambda/my-function"
}
}
そしたら再実行します。
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text | base64 -d
実行結果は次のように変わります。
START RequestId: 98f35feb-a6e0-4304-8ab3-464252eb7c73 Version: $LATEST
## ENVIRONMENT VARIABLES
/aws/lambda/my-function
2024/01/10/[$LATEST]15dc4f14087f4fc0af06c7ea94339025
## EVENT
{}
END RequestId: 98f35feb-a6e0-4304-8ab3-464252eb7c73
REPORT RequestId: 98f35feb-a6e0-4304-8ab3-464252eb7c73 Duration: 1.35 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 40 MB Init Duration: 112.76 ms
それでも、次のようにログは取れませんでした。。まあ、ログは今回の本題じゃないので、一旦スルーします。
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name $(cat out) --limit 5
# Result:
2024-01-11 00:43:19.778 Python[30707:16337649] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon or value in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolonOrValue to debug.
2024-01-11 00:43:19.778 Python[30707:16337649] CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon or value in dictionary on line 1. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolonOrValue to debug.
usage: aws [options] [ ...] [parameters]
To see help text, you can run:
aws help
aws help
aws help
Unknown options: body:, \Hello, from, Lambda!\}, 200,
Lambda関数を削除
Lambda関数の削除は次のコマンドになります。
aws lambda delete-function --function-name my-function
正常終了した場合は特に何も表示されないので、削除されたかどうかを確認するには、次のコマンドで関数の一覧を取って確認するといいでしょう。
aws lambda list-functions
関数が1つもない場合は次のように表示されます。
{
"Functions": []
}
実行ロールを削除
最後にきれいするため、作成したロールも削除したいところですが、何故か参考1や公式には紹介されませんでした。
調べたところ、参考4の順で削除する必要があり、それなりに面倒だったのが紹介されなかった理由かもしれません。
- まず次のコマンドでロールを確認します。
aws iam list-roles
実行結果はそれになり長くなりますが、該当部分を抜粋すると以下になります。
... { "Path": "/", "RoleName": "lambda-ex", "RoleId": "AROAUNUO7TBJ7ZDKPVKTF", "Arn": "arn:aws:iam::123456789012:role/lambda-ex", "CreateDate": "2024-01-10T15:26:21+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600 }, ...
- 次に該当ロール最後のアクセス詳細を確認します。
aws iam generate-service-last-accessed-details --arn arn:aws:iam::123456789012:role/lambda-ex # このarnは1つ前の実行結果にある"Arn"で置き換えてください
実行結果は次のようになります。
{ "JobId": "58c67a0b-fae7-585d-6b68-0e3608342811" }
- そしたら、このジョブの詳細を確認します。
aws iam get-service-last-accessed-details --job-id 58c67a0b-fae7-585d-6b68-0e3608342811 # このjob-idは1つ前の実行結果にある"JobId"で置き換えてください
実行結果は次のようになります。
{ "JobStatus": "COMPLETED", "JobType": "SERVICE_LEVEL", "JobCreationDate": "2024-01-10T15:57:40.174000+00:00", "ServicesLastAccessed": [ { "ServiceName": "Amazon CloudWatch Logs", "LastAuthenticated": "2024-01-10T15:46:18+00:00", "ServiceNamespace": "logs", "LastAuthenticatedEntity": "arn:aws:iam::123456789012:role/lambda-ex", "LastAuthenticatedRegion": "ap-northeast-1", "TotalAuthenticatedEntities": 1 } ], "JobCompletionDate": "2024-01-10T15:57:43.088000+00:00", "IsTruncated": false }
CloudWatch Logsが使ってましたとのことですが、、何故かログ確認できなかったんですよね。。
- 参考サイトには、次のようなインスタンスプロファイルの確認がありましたが、私の環境では該当するものはありませんでした。
aws iam list-instance-profiles-for-role --role-name lambda-ex
実行結果は次のようになります。
{ "InstanceProfiles": [] }
- 次のコマンドでロールに付与したポリシーを取得します。
aws iam list-attached-role-policies --role-name lambda-ex
実行結果は次のようになります。
{ "AttachedPolicies": [ { "PolicyName": "AWSLambdaBasicExecutionRole", "PolicyArn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } ] }
- 次のコマンドでロールに付与したポリシーを削除します。
aws iam detach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
実行結果は何も表示されません。
- 最後に次のコマンドを実行してロールを削除します。
aws iam delete-role --role-name lambda-ex
特にエラーにならなければ、実行結果はありません。
ちなみに、前述のポリシーを削除しないで直接
delete-role
を実行すると、次のようなエラー応答が返ってきます。An error occurred (DeleteConflict) when calling the DeleteRole operation: Cannot delete entity, must detach all policies first.
このエラーメッセージを見る限り、付与されてポリシーさえ削除してあげれば、ロールを削除できるかもしれません。
コメントを残す