【AWS SAM入門】15分で分かるサーバーレスアプリケーション開発の始め方・基礎・実践手順2024

目次

目次へ

AWS SAMとは?初心者でもわかる基礎知識

AWS SAM(Serverless Application Model)は、サーバーレスアプリケーションを構築するためのオープンソースフレームワークです。AWS Lambda、Amazon API Gateway、DynamoDBなどのサーバーレスリソースを簡単に定義し、デプロイすることができます。

AWS SAMが解決する3つの開発課題

  1. 複雑な設定の簡素化
  • CloudFormationテンプレートの記述量を大幅に削減
  • サーバーレスリソースに特化したシンプルな構文
  • 設定ミスのリスクを低減
  1. ローカル開発環境の統一
  • sam localコマンドによるローカルテスト環境の提供
  • Lambda関数のローカル実行が可能
  • APIのエンドポイントをローカルで確認可能
  1. デプロイメントの効率化
  • シンプルなコマンドでのデプロイ
  • 段階的なデプロイメント戦略の実現
  • ロールバックの容易さ

従来のサーバーレス開発との違い

観点従来の方法AWS SAM
テンプレート記述量多い(詳細な設定が必要)少ない(簡略化された構文)
ローカルテスト困難(実環境が必要)容易(ローカル環境で可能)
デプロイ手順複雑(複数のステップ)シンプル(単一コマンド)
学習コスト高い(多くの知識が必要)低い(直感的な API)

AWS SAMのメリット・デメリット

メリット:

  1. 開発効率の向上
  • シンプルな構文による素早い開発
  • 豊富なサンプルテンプレートの利用
  • 統合されたツールチェーンの提供
  1. コスト削減
  • ローカルテストによる AWS 利用料の削減
  • 効率的なリソース管理
  • 運用コストの最適化
  1. 品質向上
  • 標準化されたベストプラクティス
  • 一貫性のある開発環境
  • 自動化されたテスト環境

デメリット:

  1. 柔軟性の制限
  • SAM特有の制約が存在
  • 一部の高度なカスタマイズが困難
  • すべてのAWSサービスをサポートしているわけではない
  1. 追加の学習コスト
  • SAM特有の概念の理解が必要
  • 新しいツールチェーンの習得
  • トラブルシューティングのスキル
  1. ベンダーロックイン
  • AWS特有の実装への依存
  • 他のクラウドプロバイダーへの移行が困難
  • AWSのサービス更新への追従が必要

AWS SAMは、特にAWSでのサーバーレスアプリケーション開発を始める際の最適な選択肢となります。開発効率の向上とローカルテスト環境の充実により、サーバーレスアプリケーションの開発・運用がより身近なものとなります。ただし、プロジェクトの要件や制約を考慮した上で、採用を検討することが重要です。

AWS SAM環境構築の手順と注意点

AWS SAMを使用するための環境構築について、必要なツールのインストールから認証情報の設定まで、詳しく解説します。

必要なツールのインストール方法

  1. AWS CLIのインストール
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Windows(PowerShell管理者権限)
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
# macOS
brew install awscli
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Windows(PowerShell管理者権限) msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi # macOS brew install awscli # Linux curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install
   # Windows(PowerShell管理者権限)
   msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi

   # macOS
   brew install awscli

   # Linux
   curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
   unzip awscliv2.zip
   sudo ./aws/install
  1. AWS SAM CLIのインストール
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Windows(PowerShell管理者権限)
choco install aws-sam-cli
# macOS
brew tap aws/tap
brew install aws-sam-cli
# Linux
wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
sudo ./sam-installation/install
# Windows(PowerShell管理者権限) choco install aws-sam-cli # macOS brew tap aws/tap brew install aws-sam-cli # Linux wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip unzip aws-sam-cli-linux-x86_64.zip -d sam-installation sudo ./sam-installation/install
   # Windows(PowerShell管理者権限)
   choco install aws-sam-cli

   # macOS
   brew tap aws/tap
   brew install aws-sam-cli

   # Linux
   wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
   unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
   sudo ./sam-installation/install
  1. Dockerのインストール
  • Docker Desktopからインストーラーをダウンロード
  • ローカルでのLambda関数実行に必要
  1. 開発環境の準備
  • VS Code等のテキストエディタ
  • Python, Node.js等の実行環境(使用する言語に応じて)

AWS認証情報の設定ポイント

  1. IAMユーザーの作成
  • AWS Management Consoleにログイン
  • IAMダッシュボードから新規ユーザー作成
  • 必要な権限の付与:
    json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudformation:*", "sam:*", "lambda:*", "apigateway:*", "iam:*", "s3:*" ], "Resource": "*" } ] }
  1. 認証情報の設定
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# AWS CLIの設定
aws configure
# 以下の情報を入力
AWS Access Key ID: [アクセスキーID]
AWS Secret Access Key: [シークレットアクセスキー]
Default region name: [リージョン名(例:ap-northeast-1]
Default output format: json
# AWS CLIの設定 aws configure # 以下の情報を入力 AWS Access Key ID: [アクセスキーID] AWS Secret Access Key: [シークレットアクセスキー] Default region name: [リージョン名(例:ap-northeast-1)] Default output format: json
   # AWS CLIの設定
   aws configure

   # 以下の情報を入力
   AWS Access Key ID: [アクセスキーID]
   AWS Secret Access Key: [シークレットアクセスキー]
   Default region name: [リージョン名(例:ap-northeast-1)]
   Default output format: json
  1. プロファイルの設定(複数環境の場合)
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 開発環境用プロファイル
aws configure --profile dev
# 本番環境用プロファイル
aws configure --profile prod
# 開発環境用プロファイル aws configure --profile dev # 本番環境用プロファイル aws configure --profile prod
   # 開発環境用プロファイル
   aws configure --profile dev

   # 本番環境用プロファイル
   aws configure --profile prod

トラブルシューティング

  1. 一般的なエラーと対処法 エラー 原因 対処法 AWS SAM CLI not found パスが通っていない 環境変数の設定を確認 Docker daemon not running Dockerが起動していない Docker Desktopの起動 Unable to locate credentials 認証情報未設定 aws configureの実行 Permission denied 権限不足 IAMポリシーの確認・修正
  2. 環境別の注意点 Windows:
  • PowerShellの実行ポリシー設定
  • WSL2との連携設定
  • パスの区切り文字の違いに注意 macOS/Linux:
  • パーミッションの適切な設定
  • $PATHへの追加確認
  • シンボリックリンクの取り扱い
  1. 動作確認の方法
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# バージョン確認
sam --version
aws --version
docker --version
# SAMテンプレートの検証
sam validate
# ローカル環境のテスト
sam local start-api
# バージョン確認 sam --version aws --version docker --version # SAMテンプレートの検証 sam validate # ローカル環境のテスト sam local start-api
   # バージョン確認
   sam --version
   aws --version
   docker --version

   # SAMテンプレートの検証
   sam validate

   # ローカル環境のテスト
   sam local start-api

環境構築時は、特に認証情報の設定と必要な権限の付与に注意が必要です。また、ローカル開発環境でのテストには、Dockerが正常に動作している必要があります。トラブル発生時は、まず各コンポーネントのバージョンと設定を確認することをお勧めします。

AWS SAMによるローカル開発の実践手順

AWS SAMを使用したローカル開発環境の構築から、実際の開発手順まで、実践的な内容を解説します。

プロジェクトの作成と基本構成

  1. 新規プロジェクトの作成
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# プロジェクトの初期化
sam init
# 対話式の設定
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
What package type would you like to use?
1 - Zip (artifact is a zip uploaded to S3)
2 - Image (artifact is an image uploaded to ECR)
Package type: 1
Which runtime would you like to use?
1 - nodejs18.x
2 - python3.9
3 - ruby2.7
Runtime: 2
Project name: my-serverless-app
# プロジェクトの初期化 sam init # 対話式の設定 Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 What package type would you like to use? 1 - Zip (artifact is a zip uploaded to S3) 2 - Image (artifact is an image uploaded to ECR) Package type: 1 Which runtime would you like to use? 1 - nodejs18.x 2 - python3.9 3 - ruby2.7 Runtime: 2 Project name: my-serverless-app
   # プロジェクトの初期化
   sam init

   # 対話式の設定
   Which template source would you like to use?
   1 - AWS Quick Start Templates
   2 - Custom Template Location
   Choice: 1

   What package type would you like to use?
   1 - Zip (artifact is a zip uploaded to S3)
   2 - Image (artifact is an image uploaded to ECR)
   Package type: 1

   Which runtime would you like to use?
   1 - nodejs18.x
   2 - python3.9
   3 - ruby2.7
   Runtime: 2

   Project name: my-serverless-app
  1. プロジェクトの基本構造
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
my-serverless-app/
├── .aws-sam/ # ビルドアーティファクト
├── events/ # テストイベント
│ └── event.json
├── src/ # ソースコード
│ ├── handlers/ # Lambda関数
│ └── layers/ # Lambdaレイヤー
├── tests/ # テストコード
├── samconfig.toml # SAM設定ファイル
└── template.yaml # SAMテンプレート
my-serverless-app/ ├── .aws-sam/ # ビルドアーティファクト ├── events/ # テストイベント │ └── event.json ├── src/ # ソースコード │ ├── handlers/ # Lambda関数 │ └── layers/ # Lambdaレイヤー ├── tests/ # テストコード ├── samconfig.toml # SAM設定ファイル └── template.yaml # SAMテンプレート
   my-serverless-app/
   ├── .aws-sam/          # ビルドアーティファクト
   ├── events/            # テストイベント
   │   └── event.json
   ├── src/              # ソースコード
   │   ├── handlers/     # Lambda関数
   │   └── layers/       # Lambdaレイヤー
   ├── tests/            # テストコード
   ├── samconfig.toml    # SAM設定ファイル
   └── template.yaml     # SAMテンプレート
  1. 開発環境のセットアップ
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 仮想環境の作成(Python使用時)
python -m venv .venv
source .venv/bin/activate # Unix系
.venv\Scripts\activate # Windows
# 依存パッケージのインストール
pip install -r requirements.txt
# 開発用パッケージの追加
pip install pytest pytest-mock boto3
# 仮想環境の作成(Python使用時) python -m venv .venv source .venv/bin/activate # Unix系 .venv\Scripts\activate # Windows # 依存パッケージのインストール pip install -r requirements.txt # 開発用パッケージの追加 pip install pytest pytest-mock boto3
   # 仮想環境の作成(Python使用時)
   python -m venv .venv
   source .venv/bin/activate  # Unix系
   .venv\Scripts\activate     # Windows

   # 依存パッケージのインストール
   pip install -r requirements.txt

   # 開発用パッケージの追加
   pip install pytest pytest-mock boto3

template.yamlの書き方と重要な設定項目

  1. 基本的なテンプレート構造
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAMアプリケーションのサンプル
Globals:
Function:
Timeout: 30
MemorySize: 128
Runtime: python3.9
Environment:
Variables:
STAGE: dev
Parameters:
Stage:
Type: String
Default: dev
AllowedValues:
- dev
- stg
- prod
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/handlers/hello_world/
Handler: app.lambda_handler
Events:
HelloApi:
Type: Api
Properties:
Path: /hello
Method: get
# DynamoDBテーブルの定義例
UsersTable:
Type: AWS::Serverless::SimpleTable
Properties:
PrimaryKey:
Name: userId
Type: String
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: SAMアプリケーションのサンプル Globals: Function: Timeout: 30 MemorySize: 128 Runtime: python3.9 Environment: Variables: STAGE: dev Parameters: Stage: Type: String Default: dev AllowedValues: - dev - stg - prod Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: src/handlers/hello_world/ Handler: app.lambda_handler Events: HelloApi: Type: Api Properties: Path: /hello Method: get # DynamoDBテーブルの定義例 UsersTable: Type: AWS::Serverless::SimpleTable Properties: PrimaryKey: Name: userId Type: String ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5
   AWSTemplateFormatVersion: '2010-09-09'
   Transform: AWS::Serverless-2016-10-31

   Description: SAMアプリケーションのサンプル

   Globals:
     Function:
       Timeout: 30
       MemorySize: 128
       Runtime: python3.9
       Environment:
         Variables:
           STAGE: dev

   Parameters:
     Stage:
       Type: String
       Default: dev
       AllowedValues:
         - dev
         - stg
         - prod

   Resources:
     HelloWorldFunction:
       Type: AWS::Serverless::Function
       Properties:
         CodeUri: src/handlers/hello_world/
         Handler: app.lambda_handler
         Events:
           HelloApi:
             Type: Api
             Properties:
               Path: /hello
               Method: get

     # DynamoDBテーブルの定義例
     UsersTable:
       Type: AWS::Serverless::SimpleTable
       Properties:
         PrimaryKey:
           Name: userId
           Type: String
         ProvisionedThroughput:
           ReadCapacityUnits: 5
           WriteCapacityUnits: 5
  1. 重要な設定項目の解説 設定項目 説明 使用例 CodeUri 関数コードの場所 CodeUri: src/handlers/function/ Handler エントリーポイント Handler: app.lambda_handler Events トリガーの定義 API Gateway, SNS等のイベント設定 Environment 環境変数 ステージ、API키等の設定 Policies IAMポリシー リソースアクセス権限の設定
  2. 共通設定(Globals)の活用
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Globals:
Function:
Timeout: 30
MemorySize: 128
Runtime: python3.9
Tags:
Environment: !Ref Stage
Environment:
Variables:
STAGE: !Ref Stage
LOG_LEVEL: INFO
Globals: Function: Timeout: 30 MemorySize: 128 Runtime: python3.9 Tags: Environment: !Ref Stage Environment: Variables: STAGE: !Ref Stage LOG_LEVEL: INFO
   Globals:
     Function:
       Timeout: 30
       MemorySize: 128
       Runtime: python3.9
       Tags:
         Environment: !Ref Stage
       Environment:
         Variables:
           STAGE: !Ref Stage
           LOG_LEVEL: INFO

Lambda関数のローカルテスト方法

  1. ローカルでの関数呼び出し
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 関数の直接呼び出し
sam local invoke HelloWorldFunction --event events/event.json
# APIのローカル起動
sam local start-api
# APIのテスト
curl http://localhost:3000/hello
# 関数の直接呼び出し sam local invoke HelloWorldFunction --event events/event.json # APIのローカル起動 sam local start-api # APIのテスト curl http://localhost:3000/hello
   # 関数の直接呼び出し
   sam local invoke HelloWorldFunction --event events/event.json

   # APIのローカル起動
   sam local start-api

   # APIのテスト
   curl http://localhost:3000/hello
  1. テストイベントの作成(events/event.json)
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"httpMethod": "GET",
"path": "/hello",
"queryStringParameters": {
"name": "SAM"
},
"headers": {
"Accept": "application/json"
}
}
{ "httpMethod": "GET", "path": "/hello", "queryStringParameters": { "name": "SAM" }, "headers": { "Accept": "application/json" } }
   {
     "httpMethod": "GET",
     "path": "/hello",
     "queryStringParameters": {
       "name": "SAM"
     },
     "headers": {
       "Accept": "application/json"
     }
   }
  1. デバッグの設定(VS Code使用時)
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"version": "0.2.0",
"configurations": [
{
"type": "aws-sam",
"request": "direct-invoke",
"name": "Debug SAM Local",
"invokeTarget": {
"target": "template",
"templatePath": "template.yaml",
"logicalId": "HelloWorldFunction"
},
"lambda": {
"payload": {
"json": {
"httpMethod": "GET",
"path": "/hello"
}
}
}
}
]
}
{ "version": "0.2.0", "configurations": [ { "type": "aws-sam", "request": "direct-invoke", "name": "Debug SAM Local", "invokeTarget": { "target": "template", "templatePath": "template.yaml", "logicalId": "HelloWorldFunction" }, "lambda": { "payload": { "json": { "httpMethod": "GET", "path": "/hello" } } } } ] }
   {
     "version": "0.2.0",
     "configurations": [
       {
         "type": "aws-sam",
         "request": "direct-invoke",
         "name": "Debug SAM Local",
         "invokeTarget": {
           "target": "template",
           "templatePath": "template.yaml",
           "logicalId": "HelloWorldFunction"
         },
         "lambda": {
           "payload": {
             "json": {
               "httpMethod": "GET",
               "path": "/hello"
             }
           }
         }
       }
     ]
   }
  1. ユニットテストの実装例(tests/unit/test_handler.py)
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import json
import pytest
from src.handlers.hello_world import app
def test_lambda_handler():
event = {
"httpMethod": "GET",
"queryStringParameters": {"name": "SAM"}
}
response = app.lambda_handler(event, None)
assert response["statusCode"] == 200
body = json.loads(response["body"])
assert "message" in body
assert "Hello SAM" in body["message"]
import json import pytest from src.handlers.hello_world import app def test_lambda_handler(): event = { "httpMethod": "GET", "queryStringParameters": {"name": "SAM"} } response = app.lambda_handler(event, None) assert response["statusCode"] == 200 body = json.loads(response["body"]) assert "message" in body assert "Hello SAM" in body["message"]
   import json
   import pytest
   from src.handlers.hello_world import app

   def test_lambda_handler():
       event = {
           "httpMethod": "GET",
           "queryStringParameters": {"name": "SAM"}
       }

       response = app.lambda_handler(event, None)

       assert response["statusCode"] == 200
       body = json.loads(response["body"])
       assert "message" in body
       assert "Hello SAM" in body["message"]

ローカル開発環境でのテストを効率的に行うことで、デプロイ前のバグを早期に発見し、開発サイクルを短縮することができます。特に、sam localコマンドを活用することで、AWS環境を使用することなくローカルでの動作確認が可能になります。

本番環境へのデプロイ手順と運用管理

AWS SAMを使用した本番環境へのデプロイ手順と、効果的な運用管理の方法について解説します。

デプロイメントパイプラインの構築方法

  1. AWS CodePipelineを使用したCI/CD構築
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# template.yaml内にパイプライン定義を追加
Resources:
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
ArtifactStore:
Type: S3
Location: !Ref ArtifactBucket
Stages:
- Name: Source
Actions:
- Name: Source
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeCommit
Version: '1'
Configuration:
RepositoryName: !Ref RepositoryName
BranchName: main
OutputArtifacts:
- Name: SourceCode
- Name: Build
Actions:
- Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: '1'
Configuration:
ProjectName: !Ref BuildProject
InputArtifacts:
- Name: SourceCode
OutputArtifacts:
- Name: BuildOutput
# template.yaml内にパイプライン定義を追加 Resources: Pipeline: Type: AWS::CodePipeline::Pipeline Properties: ArtifactStore: Type: S3 Location: !Ref ArtifactBucket Stages: - Name: Source Actions: - Name: Source ActionTypeId: Category: Source Owner: AWS Provider: CodeCommit Version: '1' Configuration: RepositoryName: !Ref RepositoryName BranchName: main OutputArtifacts: - Name: SourceCode - Name: Build Actions: - Name: Build ActionTypeId: Category: Build Owner: AWS Provider: CodeBuild Version: '1' Configuration: ProjectName: !Ref BuildProject InputArtifacts: - Name: SourceCode OutputArtifacts: - Name: BuildOutput
   # template.yaml内にパイプライン定義を追加
   Resources:
     Pipeline:
       Type: AWS::CodePipeline::Pipeline
       Properties:
         ArtifactStore:
           Type: S3
           Location: !Ref ArtifactBucket
         Stages:
           - Name: Source
             Actions:
               - Name: Source
                 ActionTypeId:
                   Category: Source
                   Owner: AWS
                   Provider: CodeCommit
                   Version: '1'
                 Configuration:
                   RepositoryName: !Ref RepositoryName
                   BranchName: main
                 OutputArtifacts:
                   - Name: SourceCode
           - Name: Build
             Actions:
               - Name: Build
                 ActionTypeId:
                   Category: Build
                   Owner: AWS
                   Provider: CodeBuild
                   Version: '1'
                 Configuration:
                   ProjectName: !Ref BuildProject
                 InputArtifacts:
                   - Name: SourceCode
                 OutputArtifacts:
                   - Name: BuildOutput
  1. デプロイメント設定ファイル(samconfig.toml)
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
version = 0.1
version = 0.1
   version = 0.1
[default] [default.deploy] [default.deploy.parameters]

stack_name = “my-serverless-app” s3_bucket = “my-deployment-bucket” s3_prefix = “my-serverless-app” region = “ap-northeast-1” confirm_changeset = true capabilities = “CAPABILITY_IAM” parameter_overrides = “Stage=prod”

[prod] [prod.deploy.parameters] stack_name = “my-serverless-app-prod” parameter_overrides = “Stage=prod”

  1. デプロイコマンドの実行
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# ビルド
sam build
# テスト環境へのデプロイ
sam deploy --config-env dev
# 本番環境へのデプロイ
sam deploy --config-env prod
# ビルド sam build # テスト環境へのデプロイ sam deploy --config-env dev # 本番環境へのデプロイ sam deploy --config-env prod
   # ビルド
   sam build

   # テスト環境へのデプロイ
   sam deploy --config-env dev

   # 本番環境へのデプロイ
   sam deploy --config-env prod

ステージング環境の作成とテスト

  1. 環境別の設定管理 環境 用途 特徴 dev 開発 機能開発、ユニットテスト stg 検証 統合テスト、性能テスト prod 本番 実運用環境
  2. 環境変数の管理
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 環境別のパラメータストアの使用
aws ssm put-parameter \
--name "/myapp/prod/database-url" \
--value "prod-db-url" \
--type SecureString
# template.yamlでの参照
Parameters:
DatabaseUrl:
Type: AWS::SSM::Parameter::Value<String>
Default: /myapp/${Stage}/database-url
# 環境別のパラメータストアの使用 aws ssm put-parameter \ --name "/myapp/prod/database-url" \ --value "prod-db-url" \ --type SecureString # template.yamlでの参照 Parameters: DatabaseUrl: Type: AWS::SSM::Parameter::Value<String> Default: /myapp/${Stage}/database-url
   # 環境別のパラメータストアの使用
   aws ssm put-parameter \
       --name "/myapp/prod/database-url" \
       --value "prod-db-url" \
       --type SecureString

   # template.yamlでの参照
   Parameters:
     DatabaseUrl:
       Type: AWS::SSM::Parameter::Value<String>
       Default: /myapp/${Stage}/database-url
  1. 統合テストの実施
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# tests/integration/test_api.py
import requests
import pytest
@pytest.mark.integration
def test_api_endpoint():
base_url = "https://api.example.com" # ステージング環境のURL
response = requests.get(f"{base_url}/hello")
assert response.status_code == 200
data = response.json()
assert "message" in data
# tests/integration/test_api.py import requests import pytest @pytest.mark.integration def test_api_endpoint(): base_url = "https://api.example.com" # ステージング環境のURL response = requests.get(f"{base_url}/hello") assert response.status_code == 200 data = response.json() assert "message" in data
   # tests/integration/test_api.py
   import requests
   import pytest

   @pytest.mark.integration
   def test_api_endpoint():
       base_url = "https://api.example.com"  # ステージング環境のURL
       response = requests.get(f"{base_url}/hello")
       assert response.status_code == 200
       data = response.json()
       assert "message" in data

本番環境での監視設定とアラート

  1. CloudWatchメトリクスの設定
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
Events:
HelloApi:
Type: Api
AutoPublishAlias: live
DeploymentPreference:
Type: Linear10PercentEvery10Minutes
Alarms:
- ErrorAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Lambda function error rate > 0
MetricName: Errors
Threshold: 0
Period: 300
EvaluationPeriods: 1
ComparisonOperator: GreaterThanThreshold
Namespace: AWS/Lambda
Statistic: Sum
Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: Events: HelloApi: Type: Api AutoPublishAlias: live DeploymentPreference: Type: Linear10PercentEvery10Minutes Alarms: - ErrorAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Lambda function error rate > 0 MetricName: Errors Threshold: 0 Period: 300 EvaluationPeriods: 1 ComparisonOperator: GreaterThanThreshold Namespace: AWS/Lambda Statistic: Sum
   Resources:
     HelloWorldFunction:
       Type: AWS::Serverless::Function
       Properties:
         Events:
           HelloApi:
             Type: Api
         AutoPublishAlias: live
         DeploymentPreference:
           Type: Linear10PercentEvery10Minutes
         Alarms:
           - ErrorAlarm:
               Type: AWS::CloudWatch::Alarm
               Properties:
                 AlarmDescription: Lambda function error rate > 0
                 MetricName: Errors
                 Threshold: 0
                 Period: 300
                 EvaluationPeriods: 1
                 ComparisonOperator: GreaterThanThreshold
                 Namespace: AWS/Lambda
                 Statistic: Sum
  1. 主要な監視項目 メトリクス 説明 推奨閾値 Duration 関数実行時間 p95 < 1000ms Errors エラー数 0 Throttles スロットル数 0 ConcurrentExecutions 同時実行数 < 設定値の80% IteratorAge イベント処理の遅延 < 1分
  2. アラート通知の設定
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
AlertTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: !Sub ${AWS::StackName}-alerts
Subscription:
- Protocol: email
Endpoint: alert@example.com
HighErrorAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmActions:
- !Ref AlertTopic
AlarmDescription: High error rate detected
MetricName: Errors
Namespace: AWS/Lambda
Statistic: Sum
Period: 300
EvaluationPeriods: 1
Threshold: 1
ComparisonOperator: GreaterThanThreshold
Resources: AlertTopic: Type: AWS::SNS::Topic Properties: TopicName: !Sub ${AWS::StackName}-alerts Subscription: - Protocol: email Endpoint: alert@example.com HighErrorAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref AlertTopic AlarmDescription: High error rate detected MetricName: Errors Namespace: AWS/Lambda Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 ComparisonOperator: GreaterThanThreshold
   Resources:
     AlertTopic:
       Type: AWS::SNS::Topic
       Properties:
         TopicName: !Sub ${AWS::StackName}-alerts
         Subscription:
           - Protocol: email
             Endpoint: alert@example.com

     HighErrorAlarm:
       Type: AWS::CloudWatch::Alarm
       Properties:
         AlarmActions:
           - !Ref AlertTopic
         AlarmDescription: High error rate detected
         MetricName: Errors
         Namespace: AWS/Lambda
         Statistic: Sum
         Period: 300
         EvaluationPeriods: 1
         Threshold: 1
         ComparisonOperator: GreaterThanThreshold

本番環境への展開は慎重に行う必要があります。段階的なデプロイメント戦略を採用し、適切な監視とアラート設定を行うことで、安定した運用を実現できます。特に、CloudWatchを活用した監視体制の構築は、問題の早期発見と迅速な対応に不可欠です。

AWS SAMのベストプラクティスと実践的なTips

実務でAWS SAMを活用する際の重要なベストプラクティスと、本番環境での実践的なTipsを解説します。

セキュリティ強化のための設定方法

  1. 最小権限の原則の適用
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: app.lambda_handler
Runtime: python3.9
Policies:
# 必要最小限の権限を定義
- Statement:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
Resource: !GetAtt MyTable.Arn
Condition:
StringEquals:
aws:RequestedRegion: !Ref AWS::Region
Resources: MyFunction: Type: AWS::Serverless::Function Properties: Handler: app.lambda_handler Runtime: python3.9 Policies: # 必要最小限の権限を定義 - Statement: - Effect: Allow Action: - dynamodb:GetItem - dynamodb:PutItem Resource: !GetAtt MyTable.Arn Condition: StringEquals: aws:RequestedRegion: !Ref AWS::Region
   Resources:
     MyFunction:
       Type: AWS::Serverless::Function
       Properties:
         Handler: app.lambda_handler
         Runtime: python3.9
         Policies:
           # 必要最小限の権限を定義
           - Statement:
             - Effect: Allow
               Action:
                 - dynamodb:GetItem
                 - dynamodb:PutItem
               Resource: !GetAtt MyTable.Arn
               Condition:
                 StringEquals:
                   aws:RequestedRegion: !Ref AWS::Region
  1. 機密情報の安全な管理
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
SecureFunction:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
# 直接値を書かず、Systems Managerパラメータストアを使用
API_KEY: '{{resolve:ssm-secure:/myapp/api-key:1}}'
DB_PASSWORD: '{{resolve:secretsmanager:MyDBSecret:SecretString:password}}'
Resources: SecureFunction: Type: AWS::Serverless::Function Properties: Environment: Variables: # 直接値を書かず、Systems Managerパラメータストアを使用 API_KEY: '{{resolve:ssm-secure:/myapp/api-key:1}}' DB_PASSWORD: '{{resolve:secretsmanager:MyDBSecret:SecretString:password}}'
   Resources:
     SecureFunction:
       Type: AWS::Serverless::Function
       Properties:
         Environment:
           Variables:
             # 直接値を書かず、Systems Managerパラメータストアを使用
             API_KEY: '{{resolve:ssm-secure:/myapp/api-key:1}}'
             DB_PASSWORD: '{{resolve:secretsmanager:MyDBSecret:SecretString:password}}'
  1. セキュリティグループとVPCの設定
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
VPCFunction:
Type: AWS::Serverless::Function
Properties:
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
Policies:
- VPCAccessPolicy: {}
Resources: VPCFunction: Type: AWS::Serverless::Function Properties: VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroup SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 Policies: - VPCAccessPolicy: {}
   Resources:
     VPCFunction:
       Type: AWS::Serverless::Function
       Properties:
         VpcConfig:
           SecurityGroupIds:
             - !Ref LambdaSecurityGroup
           SubnetIds:
             - !Ref PrivateSubnet1
             - !Ref PrivateSubnet2
         Policies:
           - VPCAccessPolicy: {}

コスト最適化のためのアーキテクチャ設計

  1. Lambda関数の最適化
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Globals:
Function:
# メモリサイズの最適化
MemorySize: 256
# タイムアウトの適切な設定
Timeout: 6
# 環境変数のキャッシュ
Environment:
Variables:
POWERTOOLS_SERVICE_NAME: myapp
POWERTOOLS_METRICS_NAMESPACE: myapp
# レイヤーの活用
Layers:
- !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:19
Globals: Function: # メモリサイズの最適化 MemorySize: 256 # タイムアウトの適切な設定 Timeout: 6 # 環境変数のキャッシュ Environment: Variables: POWERTOOLS_SERVICE_NAME: myapp POWERTOOLS_METRICS_NAMESPACE: myapp # レイヤーの活用 Layers: - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:19
   Globals:
     Function:
       # メモリサイズの最適化
       MemorySize: 256
       # タイムアウトの適切な設定
       Timeout: 6
       # 環境変数のキャッシュ
       Environment:
         Variables:
           POWERTOOLS_SERVICE_NAME: myapp
           POWERTOOLS_METRICS_NAMESPACE: myapp
       # レイヤーの活用
       Layers:
         - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:19
  1. リソースの効率的な利用
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
# DynamoDBのオートスケーリング設定
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
BillingMode: PAY_PER_REQUEST
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
SSESpecification:
SSEEnabled: true
# S3のライフサイクルルール設定
StorageBucket:
Type: AWS::S3::Bucket
Properties:
LifecycleConfiguration:
Rules:
- Id: TransitionToIA
Status: Enabled
Transitions:
- TransitionInDays: 30
StorageClass: STANDARD_IA
Resources: # DynamoDBのオートスケーリング設定 UsersTable: Type: AWS::DynamoDB::Table Properties: BillingMode: PAY_PER_REQUEST StreamSpecification: StreamViewType: NEW_AND_OLD_IMAGES SSESpecification: SSEEnabled: true # S3のライフサイクルルール設定 StorageBucket: Type: AWS::S3::Bucket Properties: LifecycleConfiguration: Rules: - Id: TransitionToIA Status: Enabled Transitions: - TransitionInDays: 30 StorageClass: STANDARD_IA
   Resources:
     # DynamoDBのオートスケーリング設定
     UsersTable:
       Type: AWS::DynamoDB::Table
       Properties:
         BillingMode: PAY_PER_REQUEST
         StreamSpecification:
           StreamViewType: NEW_AND_OLD_IMAGES
         SSESpecification:
           SSEEnabled: true

     # S3のライフサイクルルール設定
     StorageBucket:
       Type: AWS::S3::Bucket
       Properties:
         LifecycleConfiguration:
           Rules:
             - Id: TransitionToIA
               Status: Enabled
               Transitions:
                 - TransitionInDays: 30
                   StorageClass: STANDARD_IA
  1. コスト監視の設定
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
CostAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Daily estimated charges > $10
Namespace: AWS/Billing
MetricName: EstimatedCharges
Statistic: Maximum
Period: 21600 # 6時間
EvaluationPeriods: 1
Threshold: 10
ComparisonOperator: GreaterThanThreshold
Resources: CostAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmDescription: Daily estimated charges > $10 Namespace: AWS/Billing MetricName: EstimatedCharges Statistic: Maximum Period: 21600 # 6時間 EvaluationPeriods: 1 Threshold: 10 ComparisonOperator: GreaterThanThreshold
   Resources:
     CostAlarm:
       Type: AWS::CloudWatch::Alarm
       Properties:
         AlarmDescription: Daily estimated charges > $10
         Namespace: AWS/Billing
         MetricName: EstimatedCharges
         Statistic: Maximum
         Period: 21600  # 6時間
         EvaluationPeriods: 1
         Threshold: 10
         ComparisonOperator: GreaterThanThreshold

大規模開発での注意点と対策

  1. モジュール化とコード管理
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 共通のパラメータを定義(parameters.yaml)
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- stg
- prod
# 共通のポリシーを定義(policies.yaml)
Policies:
CommonLambdaPolicy:
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
# メインテンプレート(template.yaml)
Transform: AWS::Serverless-2016-10-31
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./src/api
Policies:
- !Include policies.yaml#CommonLambdaPolicy
# 共通のパラメータを定義(parameters.yaml) Parameters: Environment: Type: String Default: dev AllowedValues: - dev - stg - prod # 共通のポリシーを定義(policies.yaml) Policies: CommonLambdaPolicy: Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: '*' # メインテンプレート(template.yaml) Transform: AWS::Serverless-2016-10-31 Resources: ApiFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./src/api Policies: - !Include policies.yaml#CommonLambdaPolicy
   # 共通のパラメータを定義(parameters.yaml)
   Parameters:
     Environment:
       Type: String
       Default: dev
       AllowedValues:
         - dev
         - stg
         - prod

   # 共通のポリシーを定義(policies.yaml)
   Policies:
     CommonLambdaPolicy:
       Statement:
         - Effect: Allow
           Action:
             - logs:CreateLogGroup
             - logs:CreateLogStream
             - logs:PutLogEvents
           Resource: '*'

   # メインテンプレート(template.yaml)
   Transform: AWS::Serverless-2016-10-31
   Resources:
     ApiFunction:
       Type: AWS::Serverless::Function
       Properties:
         CodeUri: ./src/api
         Policies:
           - !Include policies.yaml#CommonLambdaPolicy
  1. デプロイメント戦略
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
AutoPublishAlias: live
DeploymentPreference:
Type: Linear10PercentEvery10Minutes
Hooks:
PreTraffic: !Ref PreTrafficHook
PostTraffic: !Ref PostTrafficHook
Alarms:
- !Ref FunctionErrorAlarm
Resources: ApiFunction: Type: AWS::Serverless::Function Properties: AutoPublishAlias: live DeploymentPreference: Type: Linear10PercentEvery10Minutes Hooks: PreTraffic: !Ref PreTrafficHook PostTraffic: !Ref PostTrafficHook Alarms: - !Ref FunctionErrorAlarm
   Resources:
     ApiFunction:
       Type: AWS::Serverless::Function
       Properties:
         AutoPublishAlias: live
         DeploymentPreference:
           Type: Linear10PercentEvery10Minutes
           Hooks:
             PreTraffic: !Ref PreTrafficHook
             PostTraffic: !Ref PostTrafficHook
           Alarms:
             - !Ref FunctionErrorAlarm
  1. チーム開発のためのベストプラクティス カテゴリ ベストプラクティス 実装方法 コード管理 モノレポ構成 src/配下に機能別ディレクトリ テスト 自動テスト GitHub Actions/CodeBuild レビュー PRテンプレート .github/pull_request_template.md ドキュメント 自動生成 AWS SAM CLI generate-docs
  2. トラブルシューティングのためのロギング設定
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# app.py
import logging
from aws_lambda_powertools import Logger, Tracer, Metrics
logger = Logger()
tracer = Tracer()
metrics = Metrics()
@logger.inject_lambda_context
@tracer.capture_lambda_handler
def lambda_handler(event, context):
try:
# ビジネスロジック
logger.info("Processing request", extra={
"event": event
})
metrics.add_metric(name="SuccessfulRequests", unit="Count", value=1)
return {
"statusCode": 200,
"body": "Success"
}
except Exception as e:
logger.exception("Error processing request")
metrics.add_metric(name="FailedRequests", unit="Count", value=1)
raise
# app.py import logging from aws_lambda_powertools import Logger, Tracer, Metrics logger = Logger() tracer = Tracer() metrics = Metrics() @logger.inject_lambda_context @tracer.capture_lambda_handler def lambda_handler(event, context): try: # ビジネスロジック logger.info("Processing request", extra={ "event": event }) metrics.add_metric(name="SuccessfulRequests", unit="Count", value=1) return { "statusCode": 200, "body": "Success" } except Exception as e: logger.exception("Error processing request") metrics.add_metric(name="FailedRequests", unit="Count", value=1) raise
   # app.py
   import logging
   from aws_lambda_powertools import Logger, Tracer, Metrics

   logger = Logger()
   tracer = Tracer()
   metrics = Metrics()

   @logger.inject_lambda_context
   @tracer.capture_lambda_handler
   def lambda_handler(event, context):
       try:
           # ビジネスロジック
           logger.info("Processing request", extra={
               "event": event
           })
           metrics.add_metric(name="SuccessfulRequests", unit="Count", value=1)
           return {
               "statusCode": 200,
               "body": "Success"
           }
       except Exception as e:
           logger.exception("Error processing request")
           metrics.add_metric(name="FailedRequests", unit="Count", value=1)
           raise

AWS SAMを使用した大規模開発では、セキュリティ、コスト、運用性のバランスを取ることが重要です。適切なモジュール化とCI/CDパイプラインの構築、そして包括的なモニタリング体制の確立により、効率的な開発と運用が可能になります。