9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

この記事は CodeChrysalis Advent Calendar 2019 の記事です。

はじめに

Serverless Framework はYAMLでサーバサイドの環境構築ができる、Infrastructure As Code の真骨頂です。確かにAWS等のコンソールでもポチポチクリックしながら環境構築はできますが、

  1. 変更の管理ができない
  2. 画面でポチポチクリックするのが本当に面倒(Lazy...)

なのでServerless Framework の CLI でコマンド一発で全てが構築されるのはとても気持ちが良い。今回はその中でもAWSのDynamoDBをどのように構築するかを紹介します。

まずはYAML

早速YAMLを紹介します。

service: cc-database

custom:
  stage: ${opt:stage, self:provider.stage}

  ccGSIForStudentId: ${self:custom.stage}-dynamodbCcGSIForStudentId
  ccTableName: ${self:custom.stage}-dynamodbCc

  tableThroughputs:
    prod: 5
    default: 1
  tableThroughput: ${self:custom.tableThroughputs.${self:custom.stage}, self:custom.tableThroughputs.default}

provider:
  name: aws
  stage: dev
  profile: cc-admin
  region: ap-northeast-1

resources:
  Resources:
    CcDynamoDbTable:
      Type: AWS::DynamoDB::Table
      DeletionPolicy: Retain
      Properties:
        TableName: ${self:custom.catalogsTableName}
        AttributeDefinitions:
          - AttributeName: cohortId
            AttributeType: S
          - AttributeName: studentId
            AttributeType: S
        KeySchema:
          - AttributeName: cohortId
            KeyType: HASH
          - AttributeName: studentId
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: ${self:custom.tableThroughput}
          WriteCapacityUnits: ${self:custom.tableThroughput}
        GlobalSecondaryIndexes:
          - IndexName: ${self:custom.ccGSIForStudentId}
            KeySchema:
              - AttributeName: studentId
                KeyType: HASH
            Projection:
              ProjectionType: ALL
            ProvisionedThroughput:
              ReadCapacityUnits: ${self:custom.tableThroughput}
              WriteCapacityUnits: ${self:custom.tableThroughput}

  Outputs:
    CcDynamoDbTableArn:
      Value:
        Fn::GetAtt:
          - CcDynamoDbTable
          - Arn
      Export:
        Name: ${self:custom.stage}-CcDynamoDbTableArn

要素を解説

必ず必要な要素

service, provider, resources は定義が必ず必要です。

service

そのサービスの名前を定義します。
ここでサービスはモノリスサービスかマイクロサービスにするのかを決める必要があります。一つのYAMLにサーバサイドのすべての要素を入れてモノリスサービスにしても良いし、それぞれをサービスに分けてマイクロサービスにしても良いし、それは設計次第です。どちらが良いかはこのドキュメントのテーマではないので深追いしません。

この説明ではこのサービスはデータベースだけ(つまりマイクロサービス)として、cc-databaseとしました。

provider

ここではどのクラウドサービスを利用するかを定義します。今回はAWSなので以下のとおり。

  name: aws
  stage: dev
  profile: cc-admin
  region: ap-northeast-1

stageはデフォルトの環境を定義しておき、逆に言えば明確に指定しないとproduction環境にデプロイしないようにしています。

profileはserverless-frameworkでデプロイするときのユーザーをあらかじめIAMで作成しておき、ここで指定します。regionは比較的親しみのあるワードだと思いますが、お使いになるリージョンを指定します。

resources

ここで実際にデプロイしたいサービスの内容を記述します。もしAWSを利用する場合はSyntaxはCloudFormationに準じます。

Type: AWS::DynamoDB::Table

これでどのプロダクトをデプロイするかを指定します。今回はDynamoDBを指定しました。

DeletionPolicy: Retain

Serverless Framework からデータベースを変更したり削除したりしてもデータを残す指定をしています。開発時点では Delete でも良いかもしれませんが、本番サービスに入ってからデータを消してしまうと大惨事です。保持する設定をしています。

Properties:

ここで実際に作成するテーブル、ローカルインデックス、グローバルセカンダリインデックスを指定します。

TableName: ${self:custom.catalogsTableName}

テーブル名を定義しています。customについては後ほど解説します。

AttributeDefinitions:
  - AttributeName: cohortId
    AttributeType: S
  - AttributeName: studentId
    AttributeType: S

キーとして使う要素をAttributeDefinitionsですべて洗い出す必要があります。要素の名前とそのデータ型を指定します。またテーブルだけではなくインデックスで使う要素についてもここで洗い出す必要があります。

KeySchema:
  - AttributeName: cohortId
    KeyType: HASH
  - AttributeName: studentId
    KeyType: RANGE

ここではテーブルのキーを指定します。パーティーションキーをcohortId、ソートキーをstudentIdにしています。

ProvisionedThroughput:
  ReadCapacityUnits: ${self:custom.tableThroughput}
  WriteCapacityUnits: ${self:custom.tableThroughput}

ここでスループットを指定します。読み込みと書き込みでそれぞれ指定する必要があります。オートスケールにしたくないのでこの状態にしています。

GlobalSecondaryIndexes:
  - IndexName: ${self:custom.ccGSIForStudentId}
    KeySchema:
      - AttributeName: studentId
KeyType: HASH
    Projection:
      ProjectionType: ALL
    ProvisionedThroughput:
      ReadCapacityUnits: ${self:custom.tableThroughput}
      WriteCapacityUnits: ${self:custom.tableThroughput}

こちらはグローバルセカンダリインデックスの設定です。ほぼテーブルと同じですが、Projectionだけインデックス特有で、どのカラムをインデックスに持たせるかの設定です。今はALLにしているのですべてを射影しますが、一部のカラムだけで良ければ変更します。

Outputs:
  CcDynamoDbTableArn:
    Value:
		Fn::GetAtt:
			- CcDynamoDbTable
			- Arn
		Export:
			Name: ${self:custom.stage}-CcDynamoDbTableArn

もし他のマイクロサービスからDynamoDBのArnを読み取りたい場合はここでOutputsを指定しておくと、"Fn::ImportValue"で他のマイクロサービスを指定するYAMLに書くことで読み込めます。例えばLambdaがDynamoDBにアクセスするための設定で必要です。

custom

ここは変数のようなもので、定義は必須ではないが、定義しておくと便利なものを記述します。

custom:
  stage: ${opt:stage, self:provider.stage}

  ccGSIForStudentId: ${self:custom.stage}-dynamodbCcGSIForStudentId
  ccTableName: ${self:custom.stage}-dynamodbCc

  tableThroughputs:
    prod: 5
    default: 1
  tableThroughput: ${self:custom.tableThroughputs.${self:custom.stage}, self:custom.tableThroughputs.default}

たとえばここで

stage: ${opt:stage, self:provider.stage}

はCLIを実行するときの引数にSTAGEが引き渡されたらそれを使用するし、そうでなければproviderに指定されているSTAGE、すなわちdevを使用する設定としています。

テーブル名、グローバルセカンダリインデックスの名前、スループットの値を変数化しておき、この内部のYAMLや外部のYAMLから読み込むようにしています。

補足ですが、外部のYAMLから当該YAMLを読み込むためには

${file(./database/serverless.yml):custom.ccTableName}

を使うことで読み込めます。例えばこれはテーブル名を読み込んでいます。

さいごに

Code Chrysalisは東京を拠点にした12週間の短期集中型ソフトウェアエンジニア養成学校です。ソフトウェアエンジニアになるための12週間特別集中コース:イマーシブやプログラミング初心者向けの講座もありますので、ぜひ見てみてください。

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?