AWS Lambda はイベントドリブンな「関数」を登録できるサービスです。例えば S3 に画像がアップロードされたときにサムネイル用のサイズに加工する処理が記述された関数を登録できます。基本的な使い方をまとめます。
関数の登録はブラウザで AWS コンソールにログインして行うこともできますが、本ページではこちらのページで使い方を把握した AWS CLI コマンドで行うことにします。専用の IAM を新規に登録して、AWSLambdaFullAccess
など AWS Lambda に関する Permission を Attach します。以下のように ~/.aws/credentials
ファイルに認証情報を設定します。
[default]
...
[lambda-test-user-20170929]
aws_access_key_id = XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
region = ap-northeast-1
正常に設定されていれば以下のコマンドで空の結果が返されます。
$ aws lambda list-functions --profile lambda-test-user-20170929
{
"Functions": []
}
list-functions
の他に以下のようなサブコマンドが利用できます。
具体例を通して AWS Lambda 関数のコーディング方法を把握します。
ここでは Node.js を利用することにします。こちらのページなどを参照してインストールしてから以下のコマンドを実行します。
ディレクトリの作成
mkdir examplefolder
cd examplefolder
パッケージのローカルインストール
npm install async gm
後述の「関数」を記述する JS ファイルの作成
touch CreateThumbnail.js
vi CreateThumbnail.js
デプロイパッケージの作成
zip -r CreateThumbnail.zip CreateThumbnail.js node_modules/
CreateThumbnail.js
// 依存ライブラリ
var util = require('util');
var async = require('async');
var gm = require('gm').subClass({ imageMagick: true });
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
// 定数定義
var MAX_WIDTH = 100;
var MAX_HEIGHT = 100;
exports.handler = function(event, context, callback) {
// S3 から渡される情報を CloudWatch にログ出力
// https://nodejs.org/dist/latest-v6.x/docs/api/util.html#util_util_inspect_object_options
console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
// 入力バケットと出力バケット
// '+' を ' ' に置換してから URI デコーディング https://www.qoosky.io/techs/ce096d6222
var srcBucket = event.Records[0].s3.bucket.name;
var srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
var dstBucket = srcBucket + "resized";
var dstKey = "resized-" + srcKey;
// 再帰が発生して無限ループにならないようにチェック (リサイズ結果をリサイズ。その結果をリサイズ。その...)
if (srcBucket == dstBucket) {
callback("Source and destination buckets are the same.");
return;
}
// 正規表現で画像の拡張子を特定 https://www.qoosky.io/techs/e15d239fcb
var typeMatch = srcKey.match(/\.([^.]*)$/);
if (!typeMatch) {
callback("Could not determine the image type.");
return;
}
var imageType = typeMatch[1];
if (imageType != "jpg" && imageType != "png") {
callback('Unsupported image type: ${imageType}');
return;
}
// 「ダウンロード、リサイズ、アップロード」の一連の処理を非同期実行
// 結果を CloudWatch にログ出力 https://caolan.github.io/async/docs.html#waterfall
async.waterfall([
function download(next) {
// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property
s3.getObject({
Bucket: srcBucket,
Key: srcKey
}, next);
},
function transform(response, next) {
// https://github.com/aheckmann/gm
gm(response.Body).size(function(err, size) {
// `MAX_WIDTH` または `MAX_HEIGHT` まで引き伸ばす
var scalingFactor = Math.min(
MAX_WIDTH / size.width,
MAX_HEIGHT / size.height
);
var width = scalingFactor * size.width;
var height = scalingFactor * size.height;
this.resize(width, height)
.toBuffer(imageType, function(err, buffer) {
if (err) {
next(err);
}
else {
next(null, response.ContentType, buffer);
}
});
});
},
function upload(contentType, data, next) {
// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property
s3.putObject({
Bucket: dstBucket,
Key: dstKey,
Body: data,
ContentType: contentType
}, next);
}], function(err) {
// 非同期処理が完了した後に実行されるコールバック関数
if (err) {
console.error(
'Unable to resize ' + srcBucket + '/' + srcKey +
' and upload to ' + dstBucket + '/' + dstKey +
' due to an error: ' + err
);
}
else {
console.log(
'Successfully resized ' + srcBucket + '/' + srcKey +
' and uploaded to ' + dstBucket + '/' + dstKey
);
}
// S3 に結果を返す
callback(null, "message");
}
);
};
AWS IAM コンソールで新規 Role を作成して以下の Policy を Attach します。S3 に対する Put/Get アクセスおよび CloudWatch ログのすべての権限が付与されます。
lambda-s3-execution-role
AWSLambdaExecute
以下の create-function コマンドで zip ファイル ./CreateThumbnail.zip
をアップロードします。作成したロールの Amazon Resource Name (ARN) を設定して Lambda 関数を実行するときに利用できるようにします。--profile
は aws lambda
ではなく aws
のためのオプションです。create-function
するために事前準備で AWSLambdaFullAccess
を付与した IAM を指定します。
aws lambda create-function \
--profile lambda-test-user-20170929 \
--region ap-northeast-1 \
--function-name CreateThumbnail \
--zip-file fileb://CreateThumbnail.zip \
--role arn:aws:iam::123412341234:role/lambda-s3-execution-role \
--handler CreateThumbnail.handler \
--runtime nodejs6.10 \
--timeout 10 \
--memory-size 1024
S3 バケットを二つ作成して mysourcebucket20170930
バケットに適当な画像 HappyFace.jpg
をアップロードします。
mysourcebucket20170930
mysourcebucket20170930resized
以下の invoke コマンドによって IAM lambda-test-user-20170929
の権限で Lambda 関数をテスト実行します。実際には S3 から渡される --payload
情報は ./input.txt
で指定します。output.txt
には callback()
で S3 に返される情報が格納されます。
aws lambda invoke \
--profile lambda-test-user-20170929 \
--invocation-type RequestResponse \
--function-name CreateThumbnail \
--region ap-northeast-1 \
--payload file://input.txt \
output.txt
input.txt (参考: eventsources-s3-put)
{
"Records":[
{
"eventVersion":"2.0",
"eventSource":"aws:s3",
"awsRegion":"ap-northeast-1", ★変更箇所
"eventTime":"1970-01-01T00:00:00.000Z",
"eventName":"ObjectCreated:Put",
"userIdentity":{
"principalId":"AIDAJDPLRKLG7UEXAMPLE"
},
"requestParameters":{
"sourceIPAddress":"127.0.0.1"
},
"responseElements":{
"x-amz-request-id":"C3D13FE58DE4C810",
"x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"testConfigRule",
"bucket":{
"name":"mysourcebucket20170930", ★変更箇所
"ownerIdentity":{
"principalId":"A3NL1KOZZKExample"
},
"arn":"arn:aws:s3:::mysourcebucket20170930" ★変更箇所
},
"object":{
"key":"HappyFace.jpg", ★変更箇所
"size":1024,
"eTag":"d41d8cd98f00b204e9800998ecf8427e",
"versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko"
}
}
}
]
}
以下の add-permission コマンドで Lambda 関数に対して許可設定 policy を追加します。--source-account
が保有する --source-arn
バケットから関数を実行できるようになります。
aws lambda add-permission \
--profile lambda-test-user-20170929 \
--function-name CreateThumbnail \
--region ap-northeast-1 \
--statement-id some-unique-id-20170930 \
--action "lambda:InvokeFunction" \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::mysourcebucket20170930 \
--source-account 123412341234
正しく設定されたことは get-policy コマンドで確認できます。
aws lambda get-policy \
--profile lambda-test-user-20170929 \
--function-name CreateThumbnail
最後に S3 バケットに対して通知設定「S3 → mysourcebucket20170930 → Properties → Events → Add notification」を追加します。
MyNotification20170930
ObjectCreate (All)
Lambda Function
CreateThumbnail
mysourcebucket20170930
バケットに画像ファイルをアップロードすると、リサイズされて mysourcebucket20170930resized
バケットに保存されるようになります。
以下のページをご参照ください。
上記具体例で概要を把握した AWS Lambda を用いて開発を行う際に必要となる、詳細情報が記載された資料へのリンク集です。