こちらの記事はAWS Lambda 実践入門 Advent Calendar 2025 6日目の記事になります。
はじめに
AWS Lambda を GUI でポチポチ作っていると、本番運用で必ずこうなります。
- 設定が環境ごとに微妙に違う(いわゆるドリフト)
- IAM 権限がどこで変わったか分からない
- Lambda のバージョン管理が破綻
- チーム内で再現できない(属人化)
これをまとめて解決するのが AWS SAM(Serverless Application Model) です。
SAM は「Lambda を作るツール」ではなく、Lambda 運用に必要なものを IaC で一括管理するための型です。この記事では、Lambda 開発者なら必ず知っておくべき SAM の基礎を、最短で実務導入できる形で説明します。
対象読者
- Lambda を触ったことはあるが、設定がコンソール依存で不安
- 手動変更が増えてきて、環境差分や権限差分が追えなくなってきた
- CI/CD(GitHub Actions / CircleCI など)に繋げたい
AWS SAM とは?
AWS SAM は「サーバーレス専用の CloudFormation 拡張」です。
つまり SAM を使うと、Lambda 周辺のリソースをまとめて CloudFormation Stack として管理できます。
SAM が得意なもの(例):
- Lambda(Function)
- Lambda Layer
- API Gateway / Lambda Function URL 連携
- EventBridge / SQS / S3 などのイベントソース
- IAM ロール・ポリシー(最小権限の明文化)
- 環境変数、メモリ、タイムアウト、ログ、トレーシング 等の運用設定
→ これらを template.yaml に書き、sam deploy で 誰でも同じ環境を再現できます。
SAM の強みは「再現性」と「差分が見える」こと
GUI 運用の怖さは「いま本番がどういう状態か」を、コードから復元できないことです。
SAM(=CloudFormation)だと、以下が標準で手に入ります。
- 変更が Stack の差分(Change Set)として見える
- いつ誰が何を変えたか追いやすい(IaC+CI/CD前提)
- 本番・検証・開発で 同一テンプレートを使える(パラメータで分岐)
SAM の基本コマンド(最低限これだけ)
SAM による開発フローは大きく 3 ステップです。
sam build
sam validate
sam deploy
それぞれの意味:
| コマンド | 意味 |
|---|---|
| sam build | ランタイムに必要な依存をビルド(Python なら requirements の解決、成果物の生成) |
| sam validate | template.yaml の構文チェック(早期にミスを潰す) |
| sam deploy | CloudFormation にデプロイ(Stack として反映) |
最初の1回だけ:sam deploy --guided
初回は guided が鉄板です。デプロイに必要な情報(Stack名、リージョン、パラメータ等)を対話で埋めてくれます。
sam deploy --guided
ここで生成される samconfig.toml が重要です。
以降は sam deploy だけで同条件のデプロイが再現できます(CI/CD にも載せやすい)。
よく使う開発コマンド(ローカル検証)
SAM は「デプロイ」だけでなく、ローカルでの動作確認が非常に強いです。
単発で関数を実行する
sam local invoke MyFunction --event events/s3.json
API をローカル起動する(API Gateway 連携を試す)
sam local start-api
ローカル実行ができるようになると、次のメリットが出ます。
- “デプロイしてから気づく” を減らせる
- イベント JSON を固定し、再現性のあるテスト ができる
- チーム内で「同じイベントで同じ結果」が揃う
template.yaml の構造(最低限 + よく使う要素)
SAM の土台となる IaC が template.yaml です。
最低限の例に Globals / Outputs を足すと、現場で使える形になります。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: python3.12
Timeout: 30
MemorySize: 256
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: app.handler
CodeUri: src/
Environment:
Variables:
LOG_LEVEL: INFO
Outputs:
MyFunctionName:
Value: !Ref MyFunction
ここだけ押さえるポイント
-
Transform: AWS::Serverless-2016-10-31が “SAM である” 宣言 -
Globalsは全関数に共通の設定を寄せられる(Day7 で深掘り) -
Resourcesが本体(Function / Layer / API など) -
Outputsは「デプロイ後に何を参照すべきか」を明示できる(運用が楽)
プロジェクト構成(迷ったらこの形)
初心者が詰まりやすいのが「どこに何を置くか」です。最初はシンプルでOKです。
.
├── template.yaml
├── samconfig.toml # sam deploy --guided で生成される(重要)
├── src/
│ ├── app.py
│ └── requirements.txt
└── events/
└── s3.json # sam local invoke 用のイベント
この形にしておくと、ローカル実行・CI/CD・本番デプロイが一直線になります。
SAM を使うメリット(実務目線で)
- 環境差分がゼロに近づく(テンプレが真実になる)
- チーム全員が同じ設定を再現できる(属人化しにくい)
- CI/CD と統合しやすい(テンプレ+samconfig で自動化しやすい)
- 手動操作が減り事故が減る(変更がコードレビュー対象になる)
- 障害調査が速くなる(「設定がどうなっているか」をテンプレから追える)
図解:SAM → CloudFormation → Lambda の流れ
SAM は最終的に CloudFormation として展開され、Stack として管理されます。
付録:よくあるハマりどころ3選
1) samconfig.toml をどこまで管理するか
sam deploy --guided で生成される samconfig.toml は便利ですが、運用方針を決めないと事故ります。
-
チーム開発では基本コミット推奨(再現性・CI/CD 連携が楽)
-
ただし、以下は入れない(または環境変数・SSM に逃がす)
- 秘密情報(キー類、トークン類)
- 個人PC固有のパスやプロファイル依存
-
環境(dev/stg/prod)を分けるなら
-
samconfig.tomlの 環境セクションで分岐する(次回 Day7 の Parameters 設計に直結)
-
2) CodeUri と requirements の置き方
初心者が最初に壊すのはここです。「ビルドは通るのにデプロイで落ちる」「ローカルと本番で挙動が違う」が起きがちです。
-
CodeUriは 関数コードのルートを指す(src/など) -
requirements.txtは CodeUri 配下に置くのが基本(Python の依存解決が迷子にならない) -
Layer を使うなら責務分離する
-
layers/xxx/python/...(共通ロジック) -
src/(関数固有の薄いハンドラ)
→ Day7 の Resources 設計で「何を Layer に寄せるか」議論につながります
-
3) Stack 名と環境の命名規則
Stack 名は「あとから変えにくい識別子」です。命名が弱いと運用が破綻します。
-
推奨:-- で固定
- 例:
acme-receipt-prod/acme-receipt-stg
- 例:
-
関数名(FunctionName)まで固定するなら env を含める
- 例:
receipt-converter-prod
- 例:
-
逆に、Stack 名に 日付・個人名・ブランチ名を混ぜると管理不能になります
→ Day7 の Parameters / Mappings で「環境差分はテンプレ側で吸収」が基本方針
まとめ
- SAM は Lambda 運用で必須の IaC(CloudFormation 拡張)
- template.yaml に設定を集約し、環境を再現可能にする
-
build → validate → deployが基本の流れ - 初回は
sam deploy --guidedで samconfig.toml を作ると運用が楽 - 次回は template.yaml の設計原則(Globals/Parameters/Resources)へ