前提
せめてS3・Lambda・IAM権を持っているAWSアカウントそれともIAMアカウント用意
概要
こちら記事では詳細な実行を説明させて頂きます。
主な内容が下記のように進めています。
- バケツ作成
1.1 バケツ作成
2.2 ライフサイクル作成 - ポロシー・ロール作成
2.1 ポリシー作成
2.2 ロール作成 - ラムダファンクション作成
3.1 環境作成
3.1.1 初期設定
3.2 ファンクション作成
3.2.1 ロールや処理時間を設定
3.2.2 トリガー設定
3.2.3 環境変数
3.3 ラムダのNode modulesについて - テスト行い
4.1 S3アップロード
4.2 結果をチェック
4.3 ログをチェック
1. バケツ作成
2つのバケツを作成し、そのうち1つを一時的なバケツとして使用します。この一時的なバケツにはライフサイクルを設定します。
一時的なバケツとは、画像を一時的に保存し、ある期間を経過する後にライフサイクルポリシーに従って画像を自動的に削除するバケットのことです。
1.1 バケツ作成
手順
1. S3に入る
2.「バケツ作成」を押下
3.バケツ作成画面に遷移される
4.バケツ名のみを設定して、他の項目をそのままにしてもいいです
第2台目も同じようにしてください
1.2 ライフサイクル作成
1. 一時的なバケツ「temp-images-bucket」を選ぶ
2. マネジメント
3. ライフサイクル作成
3. ライフサイクル作成に遷移された
4. 以下のように設定してくだい
貴方の要件次第でルールを作成してください。
この記事の限りでは載せった画像を5日後削除させます。
ルールについて詳しくAWSドキュメントに参考して下さい。
2. ロール作成
AWSリソースをアクセスするために該当するポリシーが必要です。そして、あんなポリシーをユーザー(ユーザグループ経過※)やロールなどに付けます。
(※)AWSのベストプラクティスによると、ユーザーに直接ポリシーを付与するのではなく、ユーザーをユーザーグループに追加し、ユーザーグループにポリシーを付与する方が良いとされています。
前述の記事では、ユーザーのクレデンシャルを使用してS3へのアップロードやダウンロードを行いましたが、これはベストプラクティスではありません。本番環境では、クレデンシャルが漏れるリスクがあるためです。
ベストプラクティスとしては、適切な権限を持つロールを作成し、そのロールをLambdaやEC2などのAWSリソースに付与することです。
2.1 ボリシー作成
手順
1. IAMサービスに入る -> 左メニューにてポリシーを選ぶ
2. ポリシー作成を押下
3.JSONを選んでください
最小特権アクセス(Least Privilege)によって
サービス | 対象 | 権利 |
---|---|---|
Cloud watch | 全て | ログ記録 |
S3 | 一時的なバケツ temp-images-bucket
|
画像読み込む(GET) |
S3 | 主なバケツ名 final-images-bucket
|
画像アップロード(PUT) |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents",
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::<一時的なバケツ名(貴方次第)>/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::<主なバケツ名(貴方次第)>/*"
}
]
}
4. ポリシー名を設定して完了します。
記事ではdemo-resized-image-s3-policy
を設定しました
2.2ロール作成
手順
1. 左メニューにロールを押下
2.以下のように選択
3.次は上に作成したポリシー```demo-resized-image-s3-policy```を選んでください
(サーチで検索した方がいいです)
4.最後ステップはロール名を設定
3. ラムダファンクション作成
3.1 環境構成
3.1.1 初期設定
手順
1. 以下のように設定
2. Advance settingをそのままにします
以下のSharpライブラなので、Architerture の設定を注意してください。
3.2 ファンクション設定
3.2.1 ロールや処理時間を設定
手順
1. Configuration -> Permission -> Edit
2. 設定画面に遷移します。
項目 | 意味 |
---|---|
Memory | 重い画像を処理する場合は高い値を設定 |
Time out | 画像処理は時間が結構かかって、念の為1分を設定します。設定しない場合は以下のエラーのように出てくる "errorMessage": "2018-04-26T08:40:15.398Z …..Task timed out after 3.00 seconds"
|
Role | ロールをファンクションに付ける 設定しない場合は Access deny というエラーが出て来る |
3.2.2 トリガー設定
手順
1. 左メニューにてTriggers
2. Add trigger
3. 以下のように設定*
バケツはなぜ2台が必要ですか?
理由: recursive invocationを避けます。サークルトリガー形でラムダが繰り替えてトリガーして止まりません。したがって、利用金がすごく発生します
3.2.3環境変数
手順
1. 左メニューにて**Environment variables
2. EDIT
3.以下のように設定
3.3 ラムダのNode modulesについて
ラムダでライブラを輸入するために、Node modulesをアップロードが必要です
方法としては2つあります
- 処理ファイルと
Node modules
を圧縮してアップロードします
こちらファンクションしか利用できません。そのため一番良い方向ではありません。
- Layer の方向
そうしたら他のファンクションに共有できます。ファンクションサイズを下げて料金が下がる
手順
1. ローカルにてライブラリをダウンロード
Sharp は環境によってエラーが発生しますか。しっかりOSとCPUを指摘するのは必要です
## 2. ローカル環境で適当なOSとCPUをダウンロード
npm install --os=linux --cpu=x64 sharp
3.「node_modules」を圧縮します
4.レイヤを作成
5.環境区別のため、「compatible architertures」指摘した方がいいです
私はfor-test-sharpを既に作成ました。
6.ラムダに戻って下スクロールしてレイヤを追加しよう
7.作成したレイヤのARNを貼り付け
3.4 処理ソースコード
- node_modulesがレイヤに保存していますから、先頭のパーツは
/opt/node_modules/<lib>/...
のようにする - デプロイを押下しないと新しいコードが反映されません
import {
S3Client,
GetObjectCommand,
PutObjectCommand,
} from "@aws-sdk/client-s3";
import Sharp from '/opt/node_modules/sharp/lib/index.js';
const IMAGE_HEIGH = parseInt(process.env.IMAGE_HEIGH) || 200;
const IMAGE_WIDTH = parseInt(process.env.IMAGE_WIDTH) || 200;
const DEST_BUCKET_NAME = process.env.DEST_BUCKET_NAME;
const S3 = new S3Client();
export const handler = async (event,context) => {
try {
//GET object name from event
const { eventTime, s3 } = event.Records[0];
const srcKey = decodeURIComponent(s3.object.key.replace(/\+/g, " "));
const srcBucket = s3.bucket.name;
// ログ出す
console.log(`${eventTime} --------- ${srcBucket}/${srcKey}`);
// 画像をダウンロード
const commandGET = new GetObjectCommand({
Bucket: srcBucket,
Key: srcKey,
});
const {Body, ContentType} = await S3.send(commandGET);
//画像処理
const image = await Body.transformToByteArray();
const imageBuffer = await Sharp(image)
.resize({
height: IMAGE_HEIGH,
width: IMAGE_WIDTH,
})
.toBuffer();
// 処理済み画像を主なバケツにアップロード
const commandPUT = new PutObjectCommand({
Bucket: DEST_BUCKET_NAME,
Key: srcKey,
Body: imageBuffer,
ContentType
});
await S3.send(commandPUT);
const message = `Successfully resized ${srcBucket}/${srcKey} and uploaded to ${DEST_BUCKET_NAME}/${srcKey}`;
console.log(message)
return {
statusCode: 200,
body: message,
};
} catch (error) {
console.error('error-------->',error);
}
};
const handler = async (event,context)
どのようにeventの詳細を見ますか?
1. [Test]
2. [Configure test event]
3. TemplateにてS3put 選んで
→ eventはeven JSON に書いていあります。
4テスト行い
4.1 S3アップロード
手順
1. S3サービスに入る
2. 一時的なバケツ(temp-images-bucket)を選ぶ
4.2 結果をチェック
手順
1. 主なバケツに入る(final-images-bucket)
2. 画像を選んで
3. Open押下
4.3 ログをチェック
手順
1.CloudWatch サービスに入る
2.Log groups
3.AWSは既にグループを作成してくれます。
グループのパターン:/aws/lambda/<ラムダファンクション名>
時間合わせてログを開けてログをチェックします
最後
最後までご覧いただき、誠にありがとうございました。
もし記事にご興味や意味を感じていただけましたら、ハートやコメントを残して共有していただけると嬉しいです。