背景
Lambda + API Gateway + DynamoDBのメモアプリAPIを、SAMを使わずAWSコンソールだけで構築しました。SAMのDynamoDBCrudPolicyやEvents: Type: Apiが実際どれだけの作業を肩代わりしているかが分かります。
1. zip圧縮時のパスに注意する
Lambdaのコードをzipアップロードする際、フォルダごと圧縮するとハンドラーが見つからなくなります。
NG: src/ フォルダごと右クリックしてzip化
→ zip内のパスが src/app.py になる
OK: src/ フォルダの中身(app.py, requirements.txt)を選択してzip化
→ zip内のパスが app.py になる
LambdaはCodeUri直下にapp.pyがあることを期待するため、フォルダごと圧縮するとHandler: app.lambda_handlerが見つからずエラーになります。
2. デフォルトハンドラー名を変更する
Lambdaのデフォルトハンドラーはlambda_function.lambda_handler(lambda_function.pyを参照)です。app.pyで書いている場合は、ランタイム設定でハンドラーをapp.lambda_handlerに変更しないとNo module named 'lambda_function'エラーになります。
3. DynamoDB CRUD権限はインラインポリシーで手動作成
SAMのDynamoDBCrudPolicy(1行)が自動付与する権限を、コンソールでは以下のJSONをインラインポリシーとして作成します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem", "dynamodb:PutItem",
"dynamodb:UpdateItem", "dynamodb:DeleteItem",
"dynamodb:Scan", "dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:ap-northeast-1:*:table/memo-api-dynamodb-stack-Memos"
}
]
}
管理ポリシーAWSLambdaBasicExecutionRoleのアタッチとは別に、この6アクションを個別に許可する必要があります。
4. Lambdaプロキシ統合は「オン」一択
API Gatewayでメソッドを作成する際、「Lambda プロキシ統合」をオンにすると、HTTPリクエスト全体(メソッド・パス・ボディ・ヘッダー)がそのままLambdaのeventに渡されます。オフのままだとマッピングテンプレートの個別設定が必要になり手順が大幅に増えるため、SAMもデフォルトでプロキシ統合を使用しています。
POST /memos, GET /memos, GET /memos/{id}, PUT /memos/{id}, DELETE /memos/{id}
5エンドポイント分、この設定を毎回オンにする必要があるのがコンソール作業の面倒なところです。
5. パスパラメータは波括弧ごと入力する
/memos/{id}のようなリソースを作る際、{id}は波括弧ごと入力します。これによりAPI Gatewayがパスパラメータとして認識し、Lambda側でevent['pathParameters']['id']として受け取れるようになります。
6. SAMとの対比
| SAMの記述 | コンソールでの実体 |
|---|---|
BillingMode: PAY_PER_REQUEST |
DynamoDB作成時に「オンデマンド」を選択 |
DynamoDBCrudPolicy |
IAMロール作成 + インラインポリシーのJSON作成 |
Handler: app.lambda_handler |
zipアップロード + ハンドラー設定変更 + 環境変数設定 |
Events: Type: Api(5エンドポイント) |
リソース2個 + メソッド5個をそれぞれ手動作成・プロキシ統合オン |
sam delete |
API Gateway・Lambda・IAMロール・DynamoDBを依存関係の逆順に個別削除 |
まとめ
API Gatewayのリソース・メソッド作成が最も手数のかかる部分でした(5エンドポイント×複数設定)。SAMのEvents:セクション数行がこれを肩代わりしていることが体感できました。