API Gateway、Lambda、DynamoDB、S3を使用し、ARM64アーキテクチャやライフサイクルポリシーなどを適用してコストを最小化したサーバーレス構成です。
AWS CLIを使用してCloudFormationスタックをデプロイする場合は、以下のコマンドを実行します。
aws cloudformation create-stack \ --stack-name cost-optimized-serverless-stack \ --template-body file://cost-optimized-serverless.yaml \ --capabilities CAPABILITY_IAM
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.12
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'