一覧に戻る
Serverless

コスト最適化サーバーレスアーキテクチャ

API Gateway、Lambda、DynamoDB、S3を使用し、ARM64アーキテクチャやライフサイクルポリシーなどを適用してコストを最小化したサーバーレス構成です。

構成要素 (AWS Services):

API GatewayLambdaDynamoDBS3CloudWatch

構築される主要リソース (12種):

S3 Bucket1
DynamoDB Table1
IAM Role1
Lambda Function1
Logs LogGroup1
ApiGateway RestApi1
ApiGateway Resource1
ApiGateway Method1
ApiGateway Deployment1
ApiGateway Stage1
Lambda Permission1
CloudWatch Alarm1

アーキテクチャ図 (Architecture Diagram)

クリックで拡大表示
コスト最適化サーバーレスアーキテクチャ アーキテクチャ図

AWS CLI でのデプロイ例

AWS CLIを使用してCloudFormationスタックをデプロイする場合は、以下のコマンドを実行します。

aws cloudformation deploy \
  --template-file cost-optimized-serverless.yaml \
  --stack-name cost-optimized-serverless-stack \
  --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM
cost-optimized-serverless.yaml
DL
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Cost-optimized serverless architecture with AWS best practices'

Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - prod
    Description: Environment name

Resources:
  # S3 Bucket for static content/data storage
  DataBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration:
        Rules:
          - Id: TransitionToIA
            Status: Enabled
            Transitions:
              - TransitionInDays: 30
                StorageClass: STANDARD_IA
              - TransitionInDays: 90
                StorageClass: INTELLIGENT_TIERING
      VersioningConfiguration:
        Status: Enabled

  # DynamoDB Table with on-demand billing
  DataTable:
    Type: AWS::DynamoDB::Table
    Properties:
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: true
      SSESpecification:
        SSEEnabled: true
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES

  # Lambda Execution Role
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: DynamoDBAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - dynamodb:GetItem
                  - dynamodb:PutItem
                  - dynamodb:Query
                  - dynamodb:Scan
                  - dynamodb:UpdateItem
                Resource: !GetAtt DataTable.Arn
        - PolicyName: S3Access
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:PutObject
                Resource: !Sub '${DataBucket.Arn}/*'

  # Lambda Function with ARM architecture for cost savings
  ApiFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.13
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Architectures:
        - arm64
      MemorySize: 128
      Timeout: 30
      Environment:
        Variables:
          TABLE_NAME: !Ref DataTable
          BUCKET_NAME: !Ref DataBucket
      Code:
        ZipFile: |
          import json
          import os
          import boto3
          
          dynamodb = boto3.resource('dynamodb')
          table = dynamodb.Table(os.environ['TABLE_NAME'])
          
          def handler(event, context):
              return {
                  'statusCode': 200,
                  'body': json.dumps({'message': 'Hello from Lambda!'})
              }

  # Lambda Log Group with retention
  ApiLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/aws/lambda/${ApiFunction}'
      RetentionInDays: 7

  # API Gateway REST API
  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: !Sub '${AWS::StackName}-api'
      Description: Cost-optimized REST API
      EndpointConfiguration:
        Types:
          - REGIONAL

  # API Gateway Resource
  ApiResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      RestApiId: !Ref RestApi
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: data

  # API Gateway Method
  ApiMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      RestApiId: !Ref RestApi
      ResourceId: !Ref ApiResource
      HttpMethod: GET
      AuthorizationType: NONE
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiFunction.Arn}/invocations'

  # API Gateway Deployment
  ApiDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: ApiMethod
    Properties:
      RestApiId: !Ref RestApi

  # API Gateway Stage
  ApiStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      RestApiId: !Ref RestApi
      DeploymentId: !Ref ApiDeployment
      StageName: !Ref Environment
      TracingEnabled: false
      MethodSettings:
        - ResourcePath: '/*'
          HttpMethod: '*'
          LoggingLevel: ERROR
          DataTraceEnabled: false
          MetricsEnabled: true
          ThrottlingBurstLimit: 100
          ThrottlingRateLimit: 50

  # Lambda Permission for API Gateway
  ApiGatewayInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref ApiFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*'

  # CloudWatch Alarm for Lambda errors
  LambdaErrorAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: Alert when Lambda function errors exceed threshold
      MetricName: Errors
      Namespace: AWS/Lambda
      Statistic: Sum
      Period: 300
      EvaluationPeriods: 1
      Threshold: 5
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: FunctionName
          Value: !Ref ApiFunction

Outputs:
  ApiEndpoint:
    Description: API Gateway endpoint URL
    Value: !Sub 'https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/${Environment}/data'
    Export:
      Name: !Sub '${AWS::StackName}-ApiEndpoint'

  BucketName:
    Description: S3 Bucket name
    Value: !Ref DataBucket
    Export:
      Name: !Sub '${AWS::StackName}-BucketName'

  TableName:
    Description: DynamoDB Table name
    Value: !Ref DataTable
    Export:
      Name: !Sub '${AWS::StackName}-TableName'

  LambdaFunctionArn:
    Description: Lambda Function ARN
    Value: !GetAtt ApiFunction.Arn
    Export:
      Name: !Sub '${AWS::StackName}-LambdaArn'