AWSのLambdaファンクションの作成、実行、削除をコマンドラインから操作する
S3にファイルがアップロードされたことを検知して、処理を行うような仕組みを作り必要がありました。
処理の部分のロジックはまだ未決定事項が多いため、とりあえずは
Lambdaファンクション呼び出しからCloudWatchLogへログを吐き出すところまでの仕組みを作成してみることにしました。
※作成したLambdaファンクションをS3へのファイルアップロードのつなぎこみは次回調査
aws-cli
(AWSコマンドの利用可能な環境づくり)
AWSコマンドを使うための環境をDockerを使って構築(Mac/Linux/WindowsでもPythonなしで動くよ) | ゲンゾウ用ポストイット で環境構築済み。
AWS Lambdaファンクションの作成
AWS Lambda については以下の記事がわかりやすかった。
Lambda作成にあたってやらないといけないことは以下の2つ。
- Lambdaファンクションの実行ロールを作成する
- Lambdaファンクションを作成する
実行ロールの作成
まずは初期ポリシーファイルを作成します。
Lambdaファンクションの実行に関するフル権限を与えました。
# ファイル名は何でも良い
$ cat <<EOF >logging-function-role-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
作成したポリシーファイルを元に、ロールを作成。
--role-name
オプションに今回作成するロール名を指定します。--assume-role-policy-document
オプションに先ほど作成したポリシーファイルを指定します。 file://
プロトコルの指定は必須。これなしだとエラーになってしまうので注意しましょう。
$ aws iam create-role \
--role-name logging-function-role \
--assume-role-policy-document file://logging-function-role-policy.json
{
"Role": {
"Path": "/",
"RoleName": "logging-function-role",
"RoleId": "AROAI5BO3KLUTIOT4H4A4",
"Arn": "arn:aws:iam::642942901536:role/logging-function-role",
"CreateDate": "2019-02-25T03:49:50Z",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
}
}
実行時に出力されたJSONメッセージのうち、 Arn
の部分 ( arn:aws:iam::642942901536:role/logging-function-role
) は後々必要となるためメモしておきます 。
実行結果を CloudWatch Log
として保存したいので、以下の既存ポリシーを追加で付与します。
# arn:aws:iam::aws:policy/CloudWatchLogsFullAccess が "CloudWatchLogsFullAccess" のリソース識別子を新たしている
$ aws iam attach-role-policy \
--role-name logging-function-role \
--policy-arn arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
関数を作成
CloudWatch Logs にログを記録するLambdaファンクションのサンプルコードがあったので、そちらを流用させてもらいましょう。
例) index.js
$ cat <<EOF >index.js
console.log('Loading function');
exports.handler = function(event, context, callback) {
console.log('value1 =', event.key1);
console.log('value2 =', event.key2);
console.log('value3 =', event.key3);
callback(null, "Success");
};
EOF
このjsファイルを使ってLambdaファンクションを作成。
# 【重要!】jsファイルには忘れずに読み取り可能権限を付与しておく
$ chmod 644 index.js
# デプロイパッケージを作成します。
$ zip function.zip index.js
# create-function コマンドを使用して Lambda 関数を作成します。
$ aws lambda create-function \
--function-name logging-function \
--zip-file fileb://function.zip \
--handler index.handler \
--runtime nodejs8.10 \
--role "arn:aws:iam::642942901536:role/logging-function-role"
{
"FunctionName": "logging-function",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:642942901536:function:logging-function",
"Runtime": "nodejs8.10",
"Role": "arn:aws:iam::642942901536:role/logging-function-role",
"Handler": "index.handler",
"CodeSize": 307,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2019-02-25T03:50:50.928+0000",
"CodeSha256": "XXvquA+6ckcnnRiKe5T6uov/yBXFIqDZTULBJ9TPfvw=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "ab7440f3-1443-4e73-b2f6-10bd85b6e0c2"
}
実行してみる
コマンドラインから実行してみます。(通常通り、マネージメントコンソールページから実行してもよいか、コマンドラインの世界が好きなので。)
$ aws lambda invoke \
--function-name logging-function \
--log-type Tail \
--payload '{"key1":"value1", "key2":"value2", "key3":"value3"}' \
outputfile.txt
{
"StatusCode": 200,
"LogResult": "U1RBUlQgUmVxdWVzdElkOiAxNWQzOTE2NC1mMjJjLTQxNDMtYjI3OS0zZWM1YjcyMThmNTggVmVyc2lvbjogJExBVEVTVAoyMDE5LTAyLTI1VDAzOjU5OjE0LjM5NloJMTVkMzkxNjQtZjIyYy00MTQzLWIyNzktM2VjNWI3MjE4ZjU4CXZhbHVlMSA9IHZhbHVlMQoyMDE5LTAyLTI1VDAzOjU5OjE0LjM5NloJMTVkMzkxNjQtZjIyYy00MTQzLWIyNzktM2VjNWI3MjE4ZjU4CXZhbHVlMiA9IHZhbHVlMgoyMDE5LTAyLTI1VDAzOjU5OjE0LjM5NloJMTVkMzkxNjQtZjIyYy00MTQzLWIyNzktM2VjNWI3MjE4ZjU4CXZhbHVlMyA9IHZhbHVlMwpFTkQgUmVxdWVzdElkOiAxNWQzOTE2NC1mMjJjLTQxNDMtYjI3OS0zZWM1YjcyMThmNTgKUkVQT1JUIFJlcXVlc3RJZDogMTVkMzkxNjQtZjIyYy00MTQzLWIyNzktM2VjNWI3MjE4ZjU4CUR1cmF0aW9uOiAwLjQwIG1zCUJpbGxlZCBEdXJhdGlvbjogMTAwIG1zIAlNZW1vcnkgU2l6ZTogMTI4IE1CCU1heCBNZW1vcnkgVXNlZDogNzIgTUIJCg==",
"ExecutedVersion": "$LATEST"
}
# 実行結果ファイルの中身を確認
$ cat outputfile.txt
"Success"
正常に動作している用に見える。
※(余談)僕は、初回に index.js
の読み取り可能権限の付与をしておらず、 index.js
の権限がないよ!と起こられてしまった。
ハマった人は chmod
の実行をお忘れなく。
# ワンライナーJSONはみにくいので `jq` でフォーマット
$ cat outputfile.txt | jq .
{
"errorMessage": "EACCES: permission denied, open '/var/task/index.js'",
"errorType": "Error",
"stackTrace": [
"Object.fs.readFileSync (fs.js:551:33)",
"Object.Module._extensions..js (module.js:662:20)",
"Module.load (module.js:565:32)",
"tryModuleLoad (module.js:505:12)",
"Function.Module._load (module.js:497:3)",
"Module.require (module.js:596:17)",
"require (internal/module.js:11:18)"
]
}
CloudWatchLogが正しく書き出されているかを確認
以下のページにログインしてみて、ログが出力されているかを確認してみたところ、無事書き出しされていました。
https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logs:
ゴミ掃除
検証が終わったらゴミ掃除。
# Lambdaファンクションの削除
$ aws lambda delete-function --function-name logging-function
# IAMロールの削除
$ aws iam detach-role-policy \
--role-name logging-function-role \
--policy-arn arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
$ aws iam delete-role \
--role-name logging-function-role
ひとこと
次回 はようやくS3へファイルをアップロードした際のイベントとLambdaを紐付ける設定をしてみます。
ディスカッション
コメント一覧
まだ、コメントがありません