はじめに
やること
DynamoDBのテーブルをCloudFormationで作成します。
つまり、DynamoDBをコード化してデプロイします。
以前、CloudFront→API Gateway→Lambda→DynamoDBの簡単なアプリを作ってみたのですが、IaC(Infrastructure as Code)を学ぶにあたり、これらをコード化しようと考えました。
独自ドメイン→CloudFront→S3のHTMLフォームを表示。API Gateway経由でDynamoDBにデータ登録
まずはDynamoDBを行います。(CloudFront、API Gateway、Lambdaも後日コード化すると思います)
コードはYAMLで記述しますが、コードの各プロパティの説明も行います。
こんな方々向け
以下のような方々の参考になれば幸いです。
- DynamoDBのことはよくわからないが、とりあえずDynamoDBをコード化してデプロイしたい
- CloudFormationを使ったことがないが、とりあえずCloudFormationでコードを書いてみたい
前提
DynamoDBの構造
デプロイするDynamoDBの構造は以下のようになっています。
項目 | 設定値 |
---|---|
テーブル名 | デプロイ時に設定する |
テーブルの項目 | Email(String型) Name(String型) Gender(String型) Inquiry(String型) |
パーティションキー | |
ソートキー | Name |
テーブルのキャパシティ | RCU:3 WCU:3 |
グローバルセカンダリインデックス① | インデックス名:GSI-Name パーティションキー:Name ソートキー:Inquiry 射影される属性:Email RCU:1 WCU:1 |
グローバルセカンダリインデックス② | インデックス名:GSI-Gender パーティションキー:Gender ソートキー:Inquiry 射影される属性:Email RCU:1 WCU:1 |
YAMLコード
DynamoDBをデプロイするためのコードは下記になります。
「DynamoDB.yml」というファイル名で保存しました。
---
AWSTemplateFormatVersion: 2010-09-09
Description: "Code for DynamoDB"
Parameters:
TableName:
Type: String
Description: "Name of DynamoDB Table"
Resources:
DynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: "Email"
AttributeType: "S"
- AttributeName: "Name"
AttributeType: "S"
- AttributeName: "Gender"
AttributeType: "S"
- AttributeName: "Inquiry"
AttributeType: "S"
KeySchema:
- AttributeName: "Email"
KeyType: "HASH"
- AttributeName: "Name"
KeyType: "RANGE"
ProvisionedThroughput:
ReadCapacityUnits: "3"
WriteCapacityUnits: "3"
GlobalSecondaryIndexes:
- IndexName: "GSI-Name"
KeySchema:
- AttributeName: "Name"
KeyType: "HASH"
- AttributeName: "Inquiry"
KeyType: "RANGE"
Projection:
NonKeyAttributes:
- "Email"
ProjectionType: "INCLUDE"
ProvisionedThroughput:
ReadCapacityUnits: "1"
WriteCapacityUnits: "1"
- IndexName: "GSI-Gender"
KeySchema:
- AttributeName: "Gender"
KeyType: "HASH"
- AttributeName: "Inquiry"
KeyType: "RANGE"
Projection:
NonKeyAttributes:
- "Email"
ProjectionType: "INCLUDE"
ProvisionedThroughput:
ReadCapacityUnits: "1"
WriteCapacityUnits: "1"
TableName: !Ref TableName
やってみる
デプロイ
AWSコンソールからCloudFormationダッシュボードに移動して、「スタック」から「スタックの作成」をクリックします。
「テンプレートの準備完了」を選択、「テンプレートファイルのアップロード」を選択、「ファイルの選択」ボタンを押してコードファイル(ここでは「DynamoDB.yml」)を選択して、「次へ」をクリックします。
「スタックの名前」にはCloudFormationのスタック名を入力します。スタックとはCloudFormationの概念で、デプロイするリソースの集まりのようなものです。ひとつのスタックに複数のリソースのデプロイを記述することもできます。ここでは、DynamoDBのみのデプロイを記述したスタックとなります。
パラメータは、yamlコードで「Parameters」セクションを記述しているので、ここで「テーブルの名前はどうするか?」と聞かれています(後述)。テーブル名を入力して「次へ」をクリックします。
「スタックオプションの設定」画面では今回は特に何も追加せず、「次へ」をクリックします。
最後に「レビュー」画面が表示されるので、内容を確認して「スタックの作成」をクリックします。
スタックの進行ステータスが「CREATE_COMPLETE」になれば成功です。
コード解説
では、コードの中のどの部分が、CloudFormationやDynamoDBのパラメータと紐付いているのか、一つひとつ解説していきます。
AWSTemplateFormatVersion
「形式バージョン」になり、2022年5月20日執筆時点で、「2010-09-09」のみが有効な値となっています。固定値です。
その下の「Description」は説明となり、CloudFormationのスタックの「説明」欄に記述されるものとなります。
Parameters
「Parameters」セクションは、CloudFormationでデプロイ時に指定するパラメータを定義する場所です。
CloudFormationでデプロイを実行するとき、下記の「スタックの詳細を指定」ウィンドウで「パラメータ」の入力箇所が出てきましたが、こちらの設定値になります。(下図参照)
“Parameters”のすぐ下に記述した”TableName”の箇所は、任意の文字列を書くことができ、CloudFormationデプロイ時の画面に表示されます。(下図参照)
「Type」には値の型(文字列型や数値型など)を指定し、今回はString型としました。
Descriptionにはパラメータの説明を記述し、こちらもCloudFormationの画面に表示されます。(下図参照)
Resources
「Resources」セクションの直下に”DynamoDBTable”と記載していますが、こちらはCloudFormationの論理IDとなります。自分で任意の文字列を指定できます。
Properties
論理ID(ここでは「”DynamoDBTable」)の中で指定している「Properties」には、作成するDynamoDBの設定値を記述します。
「AttributeDefinitions」はDynamoDBテーブルの「項目」のことです。「AttributeType」は項目の型で、ここでは“S”(String型)を指定しています。その他に、“N”がNumber型で、“B”がBinary型になります。
「KeySchema」ではパーティションキーとソートキーを定義します。ここでは、”Email”という項目をパーティションキーにして、”Name”という項目をソートキーにしています。コード上で“HASH”と記述するとパーティションキーとなり、“RANGE”と記述するとソートキーとなります。
「ProvisionedThroughput」では、プロビジョンされた読み込みと書き込みのキャパシティーユニットを記述します。コード上で「ProvisionedThroughput」は2箇所記述していますが、コードの上の方がテープルのキャパシティーユニットで、コードの下の方がインデックスのキャパシティーユニットになります。(下図はテーブルのキャパシティーユニットの設定箇所)
コードの続きを見ていきます。
「GlobalSecondaryIndexes」ではグローバルセカンダリインデックスの設定を記述します。
ここでは2つのグローバルセカンダリインデックスを定義していて、”GSI-Name”と”GSI-Gender”になります。「IndexName」の箇所で記述します。
それぞれのグローバルセカンダリインデックスについて、パーティションキーとソートキーを記述する箇所が、「KeySchema」の中になります。「AttributeName」でキーの名前を記述し、「KeyType」でキーのタイプを記述します。キーのタイプは“HASH”でパーティションキーとなり、“RANGE”でソートキーとなります。
「Projection」の中では「射影される属性」を記述します。「NonKeyAttributes」に射影される属性の項目を記述して、「ProjectionType」には“KEYS_ONLY”か“INCLUDE”か“ALL”を指定します。ここでは”INCLUDE”を指定しています。
「ProvisionedThrouput」ではプロビジョンされた読み込みと書き込みのスループットを記述しますが、こちらはグローバルセカンダリインデックスのものとなります。
最後に「TableName」の欄を見ていきます。
「TableName」はその名のとおり、DynamoDBのテーブル名になります。
ここでは「!Ref」(参照)を使用して、「Parameters」セクションで記述した値をテーブル名に使用するようにしています。つまり、CloudFormationでデプロイ時に入力した値が、テーブル名に設定されるようにしています。
補足
今回の検証で遭遇したエラーとトラブルシュートを記載します。
ソートキーを2つ指定してしまった
(省略)
'keySchema' failed to satisfy constraint: Member must have length less than or equal to 2 (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException;
(省略)
こちらは、DynamoDBテーブルに2個以上のソートキーを指定しようとして発生しました。(DynamoDBの理解が浅く。。)
DynamoDBテーブルのパターンとしては、「パーティションキーがひとつ」の場合と「パーティションキーとソートキー」の場合があります。
つまり、パーティションキーとソートキーの個数の合計が2以上になることはないので、上のようなエラーが発生しました。
テーブルの項目をKeySchemaに記載しなかった
One or more parameter values were invalid: Some AttributeDefinitions are not used. AttributeDefinitions: [Gender, Email, Inquiry, Name], keys used: [Email, Inquiry, Name] (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException;
(省略)
AttributeDefinitionsプロパティで記述したものを、KeySchemaプロパティで記述しなかったときに発生しました。
「KeySchemaプロパティの属性は、AttributeDefinitionsプロパティでも指定する必要がある」とAWSドキュメントに書いてありました。
コメント