1. 本練習の概要
AWSのサーバーレスサービスを活用し、画像がアップロードされたら自動的にリサイズ処理を行うシステムを構築する。
本プロジェクトは、生成AIを技術ペアプログラマーとして活用した実践演習を実施。IAMアカウント作成からPythonコードの実装、トラブルシューティングまで、AIとの対話を通じて遂行した。
2. 利用サービス
- Compute: AWS Lambda (Python 3.12 / x86_64)
- Storage: Amazon S3 (Input Bucket, Output Bucket)
- Security: IAM (Roles & Policies), S3 Block Public Access
- Dev Tools: AWS CloudShell (Linux環境でのデプロイ), Boto3 (AWS SDK), Pillow (画像処理ライブラリ)
3. 簡単な流れ
- S3: 入力用と出力用のバケットを2つ作成する
- IAM: LambdaがS3とSNSを操作できる権限(ロール)を作成する
- Lambda: 関数の枠を作成し、タイムアウト等の設定を行う
- Deploy: AWS CloudShellを使い、コードとライブラリをパッケージ化してデプロイする
- Trigger: S3へのアップロードをトリガーにLambdaが動くよう設定する
4. 詳細手順
4.1 AWS アカウント作成
4.1.1 AWS IAMユーザー作成
前提:ルートユーザーの作成が完了したこと
- ルートユーザーでログインする
- IAMダッシュボードへ移動し、AWSコンソールの検索窓で「IAM」と検索し、サービスを開きます
- 左メニューの「ユーザー」をクリック → 「ユーザーの作成」 オレンジ色のボタンをクリック
- ユーザー名: 「HaoAdmin」と入力
- 「AWSマネジメントコンソールへのユーザーアクセスを提供する」にチェックを入れる
- コンソールパスワード: 「カスタムパスワード」を選び、自分でパスワードを設定(または自動生成)
- 「次へ」をクリック
- 許可の設定をする
- 許可のオプション: 「ポリシーを直接アタッチする」 を選択
- 許可ポリシーのリストから: 検索窓に Admin と入力
- 「AdministratorAccess」というポリシーが表示されるので、チェックを入れる
※ こちらのポリシーは、「請求情報以外はほぼ何でもできる管理者権限」です。
- 「次へ」をクリック
- 内容を確認して 「ユーザーの作成」 をクリック
- ログイン情報の保存:
- .csv ファイルをダウンロードするボタンが表示され、ダウンロードして保管する
4.1.2 セキュリティー設定(二段階認証MFA)
前提:IAMユーザーでログインし、MFAを設定する
- 作成したIAMユーザーでログインし直す
- 右上のユーザー名をクリック → 「セキュリティ認証情報」
- 「多要素認証 (MFA)」の 「MFA デバイスの割り当て」 から設定
- デバイスを識別できるように、「デバイス名」を入力(自分のMacを利用したので、MyMacで入力した)
- パスキーを選択し、MacBookの指紋認証を行う
- 設定完了
4.2 S3バケット作成(入力用と出力用)
- AWSコンソールで S3 を開く
- 「バケットを作成」をクリック
- 「バケット名」に「hao-image-resize-input」
- 他の設定は、デフォルトのままで問題なし
- 同様に「hao-image-resize-output」のバケットを作成
4.3 IAMロールの作成(権限設定)
概要:
Lambdaが「S3から画像を読み込む」「S3に画像を書き込む」「ログを出す」ための許可証(ロール)を作る
手順:
- AWSコンソールで IAM を開く -> ロール -> ロールを作成
- 【ステップ1:】
- 信頼されたエンティティタイプ: AWSのサービス
- ユースケース: Lambda を選択して「次へ」
- 【ステップ2:】
- 許可ポリシーで以下を検索してチェックを入れる
- AWSLambdaBasicExecutionRole (ログ出力用)
- AmazonS3FullAccess(S3操作用)
※ 本来は特定のバケットのみに絞るのがベストですが、練習なのでFullAccessで進む
- 許可ポリシーで以下を検索してチェックを入れる
- 【ステップ3:】
- 名前に「LambdaResizeRole」を入力し
- 「ロールを作成」を押下
4.4 Lambda関数の作成
- AWSコンソールで Lambda を開く -> 関数の作成
- 「一から作成」を選択
- 関数名: ImageResizerFunction
- ランタイム: Python 3.12
- アーキテクチャ: x86_64
- 「デフォルトの実行ロールを変更」を展開 -> 既存のロールを使用する -> 先ほど作った LambdaResizeRole を選択
- 「関数の作成」をクリック
4.5 コードの作成とライブラリの準備(ローカル作業)
- CloudShellを開く
- 以下のコマンドを順番に実行してください
# 1. 作業フォルダへ移動
cd deploy_work
# 2. Python 3.12 用のライブラリをインストール
pip install Pillow -t . --platform manylinux2014_x86_64 --only-binary=:all: --python-version 3.12 --upgrade
# 3. 圧縮
zip -r deploy.zip .
# 4. 更新
aws lambda update-function-code --function-name ImageResizerFunction --zip-file fileb://deploy.zip
hello()
- 結果を確認する
コマンドの最後に表示されるJSONで、以下のようになっているか確認してください。
"Runtime": "python3.12"
4.6 トリガーの設定(S3 → Lambda)
- Lambda画面の上部にある図(関数の概要)の左側にある 「+ トリガーを追加」 をクリック
- ソースを選択: プルダウンから S3 を選択
- バケット: 作った 「入力用バケット」(...-input の方)を選択
- イベントタイプ: 「すべてのオブジェクト作成イベント」を選択
- サフィックス: .jpg と入力
- 「私は、入力と出力の両方に同じ S3 バケットを使用することは推奨されておらず、この設定により、再帰呼び出しが生じ、それに伴い Lambda の使用量増加、コスト増大の可能性があることを了承します。」にチェックを入れる
- 右下の 「追加」 ボタンをクリック
4.7 テスト
- AWSコンソール で S3の画面を別タブで開きます
- 「入力用バケット(input)」 を開きます
- 適当な 画像ファイル(.jpg) をアップロードします
- アップロード完了後、「出力用バケット(output)」 の方に移動して中身を確認します
4.8 実行失敗(トラブルシューティング)
前提:
最初は、開発環境(Mac)と実行環境(AWS Linux)の差異に起因するトラブルがあった。そして、Lambda関数作成の際に、「ランタイム: Python 3.14」だったので、開発中(または超最新)のバージョンで、ライブラリ(Pillow)側がまだ正式に対応していないか、CloudShellがインストールしたバージョン(恐らく3.9か3.11)とバージョンの不一致を起こしていた。
CloudWatchのエラーメッセージ:
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': cannot import name '_imaging' from 'PIL' (/var/task/PIL/__init__.py)
Traceback (most recent call last):
REPORT RequestId: aaad7136-102a-43e6-9f43-bdbfea6baf17 Duration: 301.13 ms Billed Duration: 302 ms Memory Size: 128 MB Max Memory Used: 71 MB Status: error Error Type: Runtime.ImportModuleError
🕵️♂️ 原因:Mac語とLinux語の違い/Pythonバージョンの問題
解決策:
Lambda側の設定を 3.12 に戻す
1. AWSコンソールで Lambda の関数 ImageResizerFunction を開きます。
2. 「コード」 タブの下にある 「ランタイム設定」 の枠を見つけて、右の 「編集」 をクリック。
3. ランタイムを Python 3.12 に変更して保存します。
4.9 質問
- Q:料金について、かかりますか?
A:今回の練習範囲なら、ほぼ間違いなく0円です。- Lambda: 月に100万回のリクエスト、40万GB秒の実行時間が無料(永久無料枠)。今回数回テストしただけなので 0円。
- S3: 最初の12ヶ月は5GBまで無料。画像数枚なら数MBなので 0円。
- CloudWatch Logs: 5GBまで無料。テキストログだけなら 0円。