はじめに

AWS lambda で S3 の画像を圧縮する チュートリアル を試したので、それに関するメモ。

TL;DR

  • チュートリアル 通りにやれば OK
  • 事前に aws-cli のセットアップをしておく必要あり
    • インストール: pip install awscli
    • 設定: aws configure
  • 調子に乗ってランタイムを Node.js 8.10 から Node.js 10.x に変えると動かないので注意

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. 事前準備
      1. aws-cli のセットアップ
    2. チュートリアル
      1. プロジェクト初期化
      2. ロールの作成
      3. Buckets の作成
      4. index.js の作成
      5. 必要なパッケージのインストール
      6. lambda function の作成
      7. lambda function のテスト
      8. 関数の呼び出しポリシー 設定
      9. S3 → lambda の連携を設定
  5. まとめ
  6. その他・メモ
  7. 参考文献

環境・条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.5
BuildVersion: 18F132

$ pyenv --version
pyenv 1.2.13

$ pyenv global
anaconda3-5.0.0
2.7.16

$ python --version
Python 3.6.2 :: Anaconda, Inc.

$ pip show awscli
Name: awscli
Version: 1.16.215

詳細

GitHub: 17number/aws-lambda-resize-s3-image-tutorial

事前準備

aws-cli のセットアップ

インストール

公式: Installation

pip install awscli でインストール。

1
$ pip install awscli
コマンド補完の有効化

公式: Command Completion

[Tab] キーによるコマンド補完を有効にするために、以下コマンドを実行。

1
$ complete -C aws_completer aws
コンフィグ

公式: Getting Started

インストール後、aws configureaws コマンドを使うための準備を行う。アクセスキーなどは IAM で発行しておく。

1
2
3
4
5
$ aws configure
AWS Access Key ID [None]: YourAccessKeyId
AWS Secret Access Key [None]: YourSecretAccessKey
Default region name [None]: ap-northeast-1 # 東京
Default output format [None]: json # json, text, table が指定可能

設定した内容は ~/.aws/config~/.aws/credentials に書き出される。環境変数やその他コンフィグについては 公式: Other Configurable Variables を参照。

チュートリアル

チュートリアル の内容通りに進めれば OK。

プロジェクト初期化

ディレクトリを作成。+α で作業ログを Git で残していくために、Git の初期化と空コミット。

git init
1
2
$ mkdir lambda-s3 && cd lambda-s3
$ git init && git commit --allow-empty -m "init"
.gitignore

gibo.gitignore を作成。

1
2
$ gibo dump node macos >> .gitignore
$ git add .gitignore && git commit -m "chore: .gitignore"
npm init

npm の初期化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ npm init
package name: (lambda-s3)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /Users/r17n/development/github/lambda-s3/package.json:
{
"name": "lambda-s3",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

ロールの作成

IAM Management Console - Roles で以下のロールを作成。

  • [信頼されたエンティティ] – [AWS Lambda]。
  • [Permissions (アクセス許可)] – [AWSLambdaExecute]。
  • ロール名 – lambda-s3-role

Buckets の作成

S3 Management Console で Bucket を 2つ作成。

チュートリアルでは、mybucketmybucketresized になっているが、正直文字区切りが分かりづらいので source-bucketsource-bucket-r という -r で区別するようにした。

Bucket 作成後、source-bucket に適当な画像をアップロード。

index.js の作成

lambda function の元となる関数が書かれたファイル index.js をローカルで作成。

1
2
$ code index.js
# VSCode で編集

チュートリアル のコードを以下の通りに変更した

  • リサイズ後画像を格納する Bucket 名: xxxxresizedxxxx-r
  • リサイズ後画像名: xxxx.jpgr-xxxx.jpg

必要なパッケージのインストール

async, gm, aws-sdk をインストール。

1
$ npm install async gm aws-sdk

lambda function の作成

function.zip という名前で index.jsnode_modules を圧縮。

1
$ zip -r function.zip index.js node_modules

aws lambda create-funciton で、lambda function を作成。

  • --role arn:aws:iam::...ロール管理画面 から lambda-s3-role に移動して表示されたものを使用
  • --timeout 10--memory-size 1024 は必要に応じて調整
  • --runtime nodejs10.x だと、うまく動作しない(しなかった)ので注意
1
2
3
4
5
6
7
$ aws lambda create-function --function-name CreateThumbnail \
--zip-file fileb://function.zip \
--handler index.handler \
--runtime nodejs8.10 \
--timeout 10 \
--memory-size 1024 \
--role arn:aws:iam::123456789012:role/lambda-s3-role
補足: lambda function の更新

もし作成後の lambda function を更新したい場合には、aws lambda update-function-codeaws lambda update-function-configuration を使う。

タイムアウトなどのコンフィグ更新
1
2
$ aws lambda update-function-configuration --function-name CreateThumbnail \
--timeout 30
ソースコードの更新
1
2
$ aws lambda update-function-code --function-name CreateThumbnail \
--zip-file fileb://function.zip

lambda function のテスト

inputFile.txt を作成し、*** の部分を修正。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
"Records":[
{
"eventVersion":"2.0",
"eventSource":"aws:s3",
"awsRegion":"us-west-2",
"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":"***sourcebucket***",
"ownerIdentity":{
"principalId":"A3NL1KOZZKExample"
},
"arn":"arn:aws:s3:::***sourcebucket***"
},
"object":{
"key":"***uploadedImageFile***",
"size":1024,
"eTag":"d41d8cd98f00b204e9800998ecf8427e",
"versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko"
}
}
}
]
}

aws lambda invoke で lambda function を実行。

1
2
3
4
5
6
$ aws lambda invoke --function-name CreateThumbnail \
--invocation-type Event \
--payload file://inputFile.txt outputFile.txt
{
"StatusCode": 202
}

lambda function 実行後に、リサイズ後画像が Bucket に作成されていれば成功。

関数の呼び出しポリシー 設定

S3 から lambda function を呼び出せるように、権限を設定。

ますは現状のポリシーを確認、未設定なのでエラーとなる。

1
2
3
$ aws lambda get-policy --function-name CreateThumbnail

An error occurred (ResourceNotFoundException) when calling the GetPolicy operation: The resource you requested does not exist.

aws lambda add-permission コマンドで、lambda function の実行条件を設定。

  • --principal s3.amazonaws.com: S3 からの呼び出しを許可
  • --statement-id: お好みで設定(resize-upload-image など)
  • --source-arn: オリジナル画像の保存 Bucket 名
  • --source-account: IAM で Bucket 作成者の ID を確認して設定(arn:aws:iam::123456789012:user/hoge123456789012 部分)

aws_lambda

Bucket 名はグローバルに一意であり、A さんがオーナーの bucket-alpha を削除した後に、B
さんが同名の bucket-alpha を作成することが可能。

--source-arn arn:aws:s3:::my-source-bucket, --source-account 123456789012 と、Bucket 名と所有アカウントを指定することで、特定アカウントからのアップロードのみをトリガに設定できる。

1
2
3
4
5
6
7
8
9
$ aws lambda add-permission --function-name CreateThumbnail \
--principal s3.amazonaws.com \
--statement-id ***some-unique-id*** \
--action "lambda:InvokeFunction" \
--source-arn arn:aws:s3:::***source-bucket*** \
--source-account ***bucket-owner-account-id*** # 12桁
{
"Statement": "{\"Sid\":\"resize-upload-image\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:123456789012:function:CreateThumbnail\",\"Condition\":{\"StringEquals\":{\"AWS:SourceAccount\":\"123456789012\"},\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::source-bucket\"}}}"
}

aws lambda get-policy でポリシーを再確認。

1
2
3
4
$ aws lambda get-policy --function-name CreateThumbnail
{
"Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"default\",\"Statement\":[{\"Sid\":\"resize-upload-image\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:123456789012:function:CreateThumbnail\",\"Condition\":{\"StringEquals\":{\"AWS:SourceAccount\":\"123456789012\"},\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::source-bucket\"}}}]}",
"RevisionId": "b32a0ad9-96dc-4281-ab72-21350d77df1c"

S3 → lambda の連携を設定

S3 コンソール でイベントを有効化。

aws_lambda

aws_lambda

設定後、Bucket に画像をアップロードして、別の Bucket にリサイズ後の画像が作成されれば完了。

まとめ

  • チュートリアル 通りにやれば OK
  • 事前に aws-cli のセットアップをしておく必要あり
    • インストール: pip install awscli
    • 設定: aws configure
  • 調子に乗ってランタイムを Node.js 8.10 から Node.js 10.x に変えると動かないので注意

その他・メモ

以下、チュートリアルとは直接関係ないけど、「lambda 画像 圧縮」とかで調べた参考記事。別途、調べたり試したりする予定。

参考文献

関連記事