【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のインストール
   # 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のインストール
   # 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. 認証情報の設定
   # AWS CLIの設定
   aws configure

   # 以下の情報を入力
   AWS Access Key ID: [アクセスキーID]
   AWS Secret Access Key: [シークレットアクセスキー]
   Default region name: [リージョン名(例:ap-northeast-1)]
   Default output format: json
  1. プロファイルの設定(複数環境の場合)
   # 開発環境用プロファイル
   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. 動作確認の方法
   # バージョン確認
   sam --version
   aws --version
   docker --version

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

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

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

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

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

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

  1. 新規プロジェクトの作成
   # プロジェクトの初期化
   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. プロジェクトの基本構造
   my-serverless-app/
   ├── .aws-sam/          # ビルドアーティファクト
   ├── events/            # テストイベント
   │   └── event.json
   ├── src/              # ソースコード
   │   ├── handlers/     # Lambda関数
   │   └── layers/       # Lambdaレイヤー
   ├── tests/            # テストコード
   ├── samconfig.toml    # SAM設定ファイル
   └── template.yaml     # SAMテンプレート
  1. 開発環境のセットアップ
   # 仮想環境の作成(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. 基本的なテンプレート構造
   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)の活用
   Globals:
     Function:
       Timeout: 30
       MemorySize: 128
       Runtime: python3.9
       Tags:
         Environment: !Ref Stage
       Environment:
         Variables:
           STAGE: !Ref Stage
           LOG_LEVEL: INFO

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

  1. ローカルでの関数呼び出し
   # 関数の直接呼び出し
   sam local invoke HelloWorldFunction --event events/event.json

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

   # APIのテスト
   curl http://localhost:3000/hello
  1. テストイベントの作成(events/event.json)
   {
     "httpMethod": "GET",
     "path": "/hello",
     "queryStringParameters": {
       "name": "SAM"
     },
     "headers": {
       "Accept": "application/json"
     }
   }
  1. デバッグの設定(VS Code使用時)
   {
     "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)
   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構築
   # 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)
   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. デプロイコマンドの実行
   # ビルド
   sam build

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

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

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

  1. 環境別の設定管理 環境 用途 特徴 dev 開発 機能開発、ユニットテスト stg 検証 統合テスト、性能テスト prod 本番 実運用環境
  2. 環境変数の管理
   # 環境別のパラメータストアの使用
   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. 統合テストの実施
   # 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メトリクスの設定
   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. アラート通知の設定
   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. 最小権限の原則の適用
   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. 機密情報の安全な管理
   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の設定
   Resources:
     VPCFunction:
       Type: AWS::Serverless::Function
       Properties:
         VpcConfig:
           SecurityGroupIds:
             - !Ref LambdaSecurityGroup
           SubnetIds:
             - !Ref PrivateSubnet1
             - !Ref PrivateSubnet2
         Policies:
           - VPCAccessPolicy: {}

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

  1. Lambda関数の最適化
   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. リソースの効率的な利用
   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. コスト監視の設定
   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. モジュール化とコード管理
   # 共通のパラメータを定義(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. デプロイメント戦略
   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. トラブルシューティングのためのロギング設定
   # 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パイプラインの構築、そして包括的なモニタリング体制の確立により、効率的な開発と運用が可能になります。