LoginSignup
14
2

More than 1 year has passed since last update.

AWS Copilot で Phoenix Framework の本番環境を構築する データベース編

Last updated at Posted at 2022-06-08

はじめに

AWS Copilot で Phoenix Framework の本番環境を構築するシリーズです

実装したサンプルはこちらに格納しています

ストレージの追加

前回の時点では、クラスタリングはできていますが、
チャットした内容は保存されていません

本番運用するシステムならば、データ保存(永続化)は必要でしょう

AWS Copilot では、ストレージをサービスに追加することにより、データ保存が可能になります

copilot storage init でストレージを対話形式で追加できます

Only found one workload, defaulting to: lb-svc

  What type of storage would you like to associate with lb-svc?  [Use arrows to move, type to filter, ? for more help]
  > DynamoDB            (NoSQL)
    S3                  (Objects)
    Aurora Serverless   (SQL)

選択肢は DynamoDBS3Aurora Serverless です

今回はチャットなので、 DynamoDB を使ってみましょう

...
Storage type: DynamoDB

  What would you like to name this DynamoDB Table? [? for help] 

次にテーブル名を入力します

messages と入力した場合、出来上がるテーブル名は
react-chat-test-lb-svc-messages になります

つまり <アプリケーション名>-<環境名>-<サービス名>-<入力したテーブル名> です

続いてパーティションキーやソートキーを入力していきます

最終的に以下のように表示されます

Recommended follow-up actions:
  - Update lb-svc's code to leverage the injected environment variable MESSAGES_NAME.
    For example, in JavaScript you can write:
    ```
    const storageName = process.env.MESSAGES_NAME
    ```
  - Run `copilot deploy --name lb-svc` to deploy your storage resources.

そして、 copilot/lb-svc/addons/messages.yml が以下の内容で作成されます

Parameters:
  App:
    Type: String
    Description: Your application's name.
  Env:
    Type: String
    Description: The environment name your service, job, or workflow is being deployed to.
  Name:
    Type: String
    Description: The name of the service, job, or workflow being deployed.
Resources:
  messages:
    Metadata:
      'aws:copilot:description': 'An Amazon DynamoDB table for messages'
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: !Sub ${App}-${Env}-${Name}-messages_x
      AttributeDefinitions:
        - AttributeName: channel_name
          AttributeType: "S"
        - AttributeName: message_id
          AttributeType: "S"
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: channel_name
          KeyType: HASH
        - AttributeName: message_id
          KeyType: RANGE

  messagesAccessPolicy:
    Metadata:
      'aws:copilot:description': 'An IAM ManagedPolicy for your service to access the messages db'
    Type: AWS::IAM::ManagedPolicy
    Properties:
      Description: !Sub
        - Grants CRUD access to the Dynamo DB table ${Table}
        - { Table: !Ref messages }
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: DDBActions
            Effect: Allow
            Action:
              - dynamodb:BatchGet*
              - dynamodb:DescribeStream
              - dynamodb:DescribeTable
              - dynamodb:Get*
              - dynamodb:Query
              - dynamodb:Scan
              - dynamodb:BatchWrite*
              - dynamodb:Create*
              - dynamodb:Delete*
              - dynamodb:Update*
              - dynamodb:PutItem
            Resource: !Sub ${ messages.Arn}
          - Sid: DDBLSIActions
            Action:
              - dynamodb:Query
              - dynamodb:Scan
            Effect: Allow
            Resource: !Sub ${ messages.Arn}/index/*

Outputs:
  messagesName:
    Description: "The name of this DynamoDB."
    Value: !Ref messages
  messagesAccessPolicy:
    Description: "The IAM::ManagedPolicy to attach to the task role."
    Value: !Ref messagesAccessPolicy

addon として CloudFormation のテンプレートが作られるわけですね

この状態でまたデプロイします

copilot svc deploy \
  --name lb-svc \
  --env test

デプロイが完了した後、 AWS のコンソールを見ると確かに DynamoDB にテーブルが作成されています

スクリーンショット 2022-06-03 15.03.08.png

また、 ECS のタスクに環境変数も追加されています

スクリーンショット 2022-06-03 15.06.00.png

コンテナ内からはこの環境変数を使ってテーブルを指定すれば良いわけですね

ちなみに、テーブルのキーを変更した場合、そのままデプロイすると以下のようなエラーになります

...
    - An Amazon DynamoDB table for messages                                            [update complete]           [0.0s]
      CloudFormation cannot update a stack when a custom-named resource requ                                       
      ires replacing. Rename react-chat-test-lb-svc-messages and update the                                        
      stack again.                                                                                                 
...

キーを変える場合、 addons/messages.yml 内のテーブル名を変更する必要があります

テーブル名を変えたくない場合、一度名前を変更してデプロイした後、
テーブル名を元に戻して再度デプロイすることになります

Elixir でのテーブル名設定

DynamoDB へのアクセス方法紹介の記事ではないので、ポイントだけ書きます

まず、 react_chat/config/config.exs にテーブル名取得用の設定を追加します

config :react_chat, ReactChatWeb.RoomChannel, table_name: System.get_env("MESSAGES_NAME")

また、環境変数 MESSAGES_NAME は実行時のコンテナに設定されます

config.exsprod.exs はビルド時の環境変数を使うため、
実行時の環境変数を使う場合は runtime.exs に設定を書いておく必要があります

したがって、 react_chat/config/runtime.exs にも設定を追加する必要があります

if config_env() == :prod do
  ...
  # 次の行を追加
  config :react_chat, ReactChatWeb.RoomChannel, table_name: System.get_env("MESSAGES_NAME")
end

まとめ

AWS Copilot で簡単に DynamoDB のテーブルを追加することができました

デフォルトで作ったら DynamoDB が BillingMode: PAY_PER_REQUEST になっていたので、
コスト最適にするならここもいじる必要があります

RDB を使いたい場合は Aurora Serverless を選択することになると思いますが、こちらはまだ未検証です

本番利用したときどれだけの性能、コストになるのか、、、

リアルタイム処理では DynamoDB を使って、
バッチ処理結果を Aurora Serverless に入れるような感じにすればコスト最適にできそう

14
2
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
14
2