DynamoDBを使ったサーバレスアプリをSAMで構築する
AWS DVAの出題範囲の1つでもある、デプロイに関する内容です。
AWS SAM(Serverless Application Model)を使ったサーバレスアプリの作成方法を確認します。
以下のページで、SAMを使って、LambdaとAPI Gatewayを組み合わせて、サーバレスアプリの構築方法をご紹介しました。
今回はこの続編ということで、新たにDynamoDBを組み込んだサーバレスアプリを構築します。
構築する環境
基本的には、以前の構成と同様です。
API Gatewayをエンドポイント、バックエンドでLambdaとして作成します。
LambdaからDynamoDBへアクセスし、データの読み書きを実行します。
ユーザからアクセスがあった場合、その日時データを保存します。その後、保存されている全日時データをスキャンし、結果を返します。
SAMテンプレートファイル
以下の構成をSAMで作成します。
以下のURLに、SAMテンプレートとLambda関数用スクリプトファイルを配置しています。
https://github.com/awstut-an-r/awstut-dva/tree/main/01/001
ポイント解説
SAMの基本的な事項については、以下のページをご確認ください。
DynamoDBの基本については、以下のページをご確認ください。
本ページでは、上記で触れられてない点について取り上げます。
LambdaからDynamoDBにアクセスするための権限
Lambda関数およびAPI Gatewayの定義は、先述のページと同様です。
ただ今回はLambdaからDynamoDBにアクセスするため、IAMロールを作成し、必要な権限を付与します。
Resources:
HelloWorldFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: HelloWorldFunctionPolicies
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- dynamodb:List*
- dynamodb:DescribeReservedCapacity*
- dynamodb:DescribeLimits
- dynamodb:DescribeTimeToLive
Resource: "*"
- Effect: Allow
Action:
#- dynamodb:BatchGet*
#- dynamodb:DescribeStream
#- dynamodb:DescribeTable
#- dynamodb:Get*
#- dynamodb:Query
- dynamodb:Scan
#- dynamodb:BatchWrite*
#- dynamodb:CreateTable
#- dynamodb:Delete*
#- dynamodb:Update*
#- dynamodb:PutItem
Resource: !GetAtt Table.Arn
Code language: YAML (yaml)
今回はAWS公式のAmazon DynamoDB: 特定のテーブルへのアクセスを許可するを参考にIAMロールを定義しました。
SAMでDynamoDBを定義する
SAMには、専用の記法が用意されています。
今回はSAMの記法に則って、現在日時を保存するためのDynamoDBテーブルを定義します。
Resources:
Table:
Type: AWS::Serverless::SimpleTable
Properties:
PrimaryKey:
Name: dt
Type: String
#ProvisionedThroughput:
TableName: !Sub ${Prefix}-Table
Code language: YAML (yaml)
通常のCloudFormationでは、DynamoDBを作成する場合、Typeプロパティに「AWS::DynamoDB::Table」を指定しますが、SAMの記法に従うと「AWS::Serverless::SimpleTable」となります。
PrimaryKeyプロパティでパーティションキーを指定します。今回は「dt」という文字列タイプの属性をパーティションキーとするように指定します。
今回はProvisionedThroughputプロパティを設定しません。設定しないということは、オンデマンドモードを選択するという意味になります。
ProvisionedThroughput
スループットプロビジョニング情報の読み取りと書き込み。
AWS::Serverless::SimpleTable
ProvisionedThroughput を指定しなかった場合、BillingMode は PAY_PER_REQUEST として指定されます。
なおオンデマンドモードは、事前のキャパシティプロビジョニングが不要で、トラフィック量に応じた支払いが可能なモデルです。
DynamoDB on-demandはシンプルなpay-per-request課金モデルを提供しreadリクエストとwriteリクエストを使った分に応じて支払うだけになります。これによりシンプルなコスト計算とパフォーマンス管理を実現します。
Amazon DynamoDB On-Demand – 事前のキャパシティプランニングが不要のリクエスト課金が可能になりました。
参考までに、通常のCloudFormationの記法で、同様のテーブルを作成する場合のコードを記載します。
Resources:
SampleTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: dt
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: dt
KeyType: HASH
TableName: !Sub ${Prefix}-SampleTable
Code language: YAML (yaml)
PythonからDynamoDBにアクセスする
PythonスクリプトからDynamoDBへアクセスし、アイテムを読み書きする方法を確認します。
import json
import boto3
import datetime
import json
TABLE_NAME = 'dva-01-001-Table'
REGION_NAME = 'ap-northeast-1'
def lambda_handler(event, context):
now = datetime.datetime.now()
now_str = now.strftime('%Y-%m-%d %H:%M:%S')
dynamodb_config = {
'region_name': REGION_NAME
}
dynamodb = boto3.resource('dynamodb', **dynamodb_config)
table = dynamodb.Table(TABLE_NAME)
table.put_item(Item={
'dt': now_str
})
result = table.scan()
return {
"statusCode": 200,
"body": json.dumps(
{"AccessDatetime": result},
indent=2
)
}
Code language: Python (python)
ポイントを取り上げます。
datetimeオブジェクトを作成し、現在日時を取得します。取得後、フォーマットを指定して文字列として取得します。
boto3.resourceでBynamoDBにアクセスするためのクライアントオブジェクトを作成します。
同オブジェクトを使用し、テーブル名を指定して、テーブルオブジェクトを作成します。
テーブルオブジェクトのput_itemメソッドで項目を保存できます。今回は属性名をdtとし、先ほど取得した現在日時データを保存します。
保存済みの全項目を取得する場合は、同オブジェクトのscanメソッドを使用します。
最後にHTTPのステータスコードとともに、scanメソッドで取得したデータを返します。
SAMアプリをビルド・デプロイ
samコマンドを使用して、アプリをビルドし、デプロイします。
以下のページをご確認ください。
今回生成された主要リソースの情報は以下の通りです。
- API Gateway:HelloWorldApi
- Lambda関数:HelloWorldFunction
- DynamoDB:dva-01-001-SimpleTable
AWS Management Consoleからも、リソースの作成状況を確認します。
まずCloudFormationで作成されたスタックを確認します。
SAMアプリをデプロイすることによって、自動的にCloudFormationスタックが作成されました。
これはSAMがCloudFormationの変形であるためです。
Resourcesタブを見ると、実際に作成されたリソースを確認することができます。
作成されたリソースの詳細を確認します。
Lambda、DynamoDB、API Gatewayが作成されました。特にAPI Gatewayに関しては、エンドポイントのURLが確認できます。
SAMアプリにアクセス
準備が整いましたので、アプリにアクセスします。
応答がありました。API Gatewayを介して、Lambda関数が呼び出され、同関数内からDynamoDBにアクセスしています。
現在日時情報が1件書き込まれた後、scanが実行されていることがわかります。
何度かアクセスしてみます。
アクセスする度に、アイテム数が増えていくことがわかります。
最後にAWS Management ConsoleからDynamoDBを確認してみます。
こちらからも保存されているアイテムが表示されました。
先ほどと同様に3件分が確認できます。
まとめ
SAMを使用して、Lambda、API Gateway、そしてDynamoDBで構成されるWebアプリの作成方法を確認しました。