継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

『AWS Coplilot CLI』の v0.2.0 でサポートされたストレージリソースのデプロイを実践する

タダです.

AWS Coplilot CLI」がv0.2.0になった時に追加されたcopilot storage initコマンドがあります.このコマンドで S3 もしくは DynamoDB を ECS のアプリケーションと関連づけられ,デプロイする時も一緒に展開されます.今回はストレージリソースを追加するコマンドでどんなことができるのかを観つつ,実際に AWS 上にリソースを作成してみます.

github.com

copilot storage init でリソースを足してみる

copilot storage initで S3 と DynamoDB をリソースを足してデプロイして動作を確認してみます.

S3 をストレージリソースに指定する場合

copilot storage initcopilot-sandbox-bucketという S3 バケットを作り,front-endというサービスに関連づけるようにコマンドを実行しました.すると,front-endサービスのディレクトリ配下にaddonsディレクトリが追加されました.

» copilot storage init -n copilot-sandbox-bucket -t S3 -s front-end
✔ Wrote CloudFormation template for S3 Bucket copilot-sandbox-bucket at front-end/addons/copilot-sandbox-bucket.yml
The Cloudformation template is a nested stack which fully describes your resource,
the IAM policy necessary for an ECS task to access that resource, and outputs
which are injected as environment variables into the Copilot service this addon is associated with.

Recommended follow-up actions:
- Update your service code to leverage the injected environment variable `COPILOTSANDBOXBUCKET_NAME`
- Run `copilot svc deploy --name front-end` to deploy your storage resources to your environments.

ツリーで出すと以下のディレクトリ構造です.

» tree                                
.
└── front-end
    ├── addons
    │   └── copilot-sandbox-bucket.yml
    └── manifest.yml

2 directories, 2 files

addons ディレクトリにできた CloudFormation の中身

addonsの中にできた CloudFormation テンプレートもみてみましょう.S3 とバケットポリシー と IAM ポリシーが作られるようになっています.S3 バケット名はアプリケーション名-環境名-サービス名-copilot-sandbox-bucketに作られるよう定義されているので,今回はアプリケーション名をs3-test-app.サービス名をfront-end,環境名はtestにしているので,s3-test-app-test-front-end-copilot-sandbox-bucketというバケットが作られるはずです.

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:
  copilotsandboxbucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      AccessControl: Private
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: AES256
      BucketName: !Sub '${App}-${Env}-${Name}-copilot-sandbox-bucket'
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true

  copilotsandboxbucketBucketPolicy:
    Type: AWS::S3::BucketPolicy
    DeletionPolicy: Retain
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: ForceHTTPS
            Effect: Deny
            Principal: '*'
            Action: 's3:*'
            Resource: 
              - !Sub ${ copilotsandboxbucket.Arn}/*
              - !Sub ${ copilotsandboxbucket.Arn}
            Condition: 
              Bool:
                "aws:SecureTransport": false
      Bucket: !Ref copilotsandboxbucket

  copilotsandboxbucketAccessPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      Description: !Sub
        - Grants CRUD access to the S3 bucket ${Bucket}
        - { Bucket: !Ref copilotsandboxbucket }
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: S3ObjectActions
            Effect: Allow
            Action:
              - s3:GetObject
              - s3:PutObject
              - s3:PutObjectACL
              - s3:PutObjectTagging
              - s3:DeleteObject
              - s3:RestoreObject
            Resource: !Sub ${ copilotsandboxbucket.Arn}/*
          - Sid: S3ListAction
            Effect: Allow
            Action: s3:ListBucket
            Resource: !Sub ${ copilotsandboxbucket.Arn}

Outputs:
  copilotsandboxbucketName:
    Description: "The name of a user-defined bucket."
    Value: !Ref copilotsandboxbucket
  copilotsandboxbucketAccessPolicy:
    Description: "The IAM::ManagedPolicy to attach to the task role"
    Value: !Ref copilotsandboxbucketAccessPolicy

デプロイの実践

ECS と一緒に S3 が作成されるかを見るために試しにデプロイします.front-endサービスでtestステージとしてデプロイします.

» copilot svc deploy -n front-end -e test
Sending build context to Docker daemon  97.28kB
Step 1/3 : FROM nginx
 ---> 2622e6cca7eb
Step 2/3 : EXPOSE 80
 ---> Using cache
 ---> 26762c0d19ed
Step 3/3 : COPY index.html /usr/share/nginx/html
 ---> Using cache
 ---> 418ae089702d
Successfully built 418ae089702d
Successfully tagged XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/s3-test-app/front-end:594bd85
Login Succeeded
The push refers to repository [XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/s3-test-app/front-end]
f2ed02c7c10a: Pushed 
f978b9ed3f26: Pushed 
9040af41bb66: Pushed 
7c7d7f446182: Pushed 
d4cf327d8ef5: Pushed 
13cb14c2acd3: Pushed 
594bd85: digest: sha256:234bf1c50d5b5b0f27abaec5be3e2b33cf1f81f0caa3f3a5c015cb0610e79004 size: 1570


✔ Deployed front-end, you can access it at http://s3-te-Publi-1LSK6S09DLXSM-500018808.ap-northeast-1.elb.amazonaws.com.

ECS クラスターと一緒にs3-test-app-test-front-end-copilot-sandbox-bucketが作成されていました. f:id:sadayoshi_tada:20200803131803p:plain f:id:sadayoshi_tada:20200803131813p:plain

削除する時の注意点として S3 バケットは削除されません.CloudFormation テンプレート(本記事でいう copilot-sandbox-bucket.yml )で DeletionPolicy: Retain が定義されているためです.開発中に何度も作って潰してを繰り返すこともあると思うのでその時はDeletionPolicy:Deleteを設定することを検討しましょう. docs.aws.amazon.com

DynamoDB をストレージリソースに指定する場合

copilot storage initcopilot-sandbox-tableという DynamoDB のテーブルを作り,Email というパーティションキーと UserId というソートキーを設定して,front-endというサービスに関連づけるようにコマンドを実行しました.S3 の時と同様に,front-endサービスのディレクトリ配下にaddonsディレクトリが追加されました.

 » copilot storage init -n copilot-sandbox-table -t DynamoDB -s front-end --partition-key Email:S --sort-key UserId:N --no-lsi
✔ Wrote CloudFormation template for DynamoDB Table copilot-sandbox-table at copilot/front-end/addons/copilot-sandbox-table.yml
The Cloudformation template is a nested stack which fully describes your resource,
the IAM policy necessary for an ECS task to access that resource, and outputs
which are injected as environment variables into the Copilot service this addon
is associated with.

Recommended follow-up actions:
- Update your service code to leverage the injected environment variable `COPILOTSANDBOXTABLE_NAME`
- Run `copilot svc deploy --name front-end` to deploy your storage resources to your environments.

ツリーで出すと以下のディレクトリ構造です.

» tree                                
.
└── front-end
    ├── addons
    │   └── copilot-sandbox-table.yml
    └── manifest.yml

2 directories, 2 files

addons ディレクトリにできた CloudFormation の中身

addonsの中にできた CloudFormation テンプレートもみてみましょう.ざっとみると,DynamoDB と IAM ポリシーが作られるようになっています.DynamoDB のテーブル名はアプリケーション名-環境名-サービス名-copilot-sandbox-tableに作られるよう定義されているので,今回はアプリケーション名をdynamo-test-app.サービス名をfront-end,環境名はtestにしているので,dynamo-test-app-test-front-end-copilot-sandbox-bucketというバケットが作られるはずです.

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:
  copilotsandboxtable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    Properties:
      TableName: !Sub ${App}-${Env}-${Name}-copilot-sandbox-table
      AttributeDefinitions:
        - AttributeName: Email
          AttributeType: "S"
        - AttributeName: UserId
          AttributeType: "N"
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: Email
          KeyType: HASH
        - AttributeName: UserId
          KeyType: RANGE

  copilotsandboxtableAccessPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      Description: !Sub
        - Grants CRUD access to the Dynamo DB table ${Table}
        - { Table: !Ref copilotsandboxtable }
      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 ${ copilotsandboxtable.Arn}
          - Sid: DDBLSIActions
            Action:
              - dynamodb:Query
              - dynamodb:Scan
            Effect: Allow
            Resource: !Sub ${ copilotsandboxtable.Arn}/Index/*

Outputs:
  copilotsandboxtableName:
    Description: "The name of this DynamoDB."
    Value: !Ref copilotsandboxtable
  copilotsandboxtableAccessPolicy:
    Description: "The IAM::ManagedPolicy to attach to the task role."
    Value: !Ref copilotsandboxtableAccessPolicy

デプロイの実践

DynamoDB のリソースが作られるかを確認するためにデプロイします.front-endサービスでtestステージとしてデプロイします.

» copilot svc deploy -n front-end -e test
Sending build context to Docker daemon  97.28kB
Step 1/3 : FROM nginx
 ---> 2622e6cca7eb
Step 2/3 : EXPOSE 80
 ---> Using cache
 ---> 26762c0d19ed
Step 3/3 : COPY index.html /usr/share/nginx/html
 ---> Using cache
 ---> 418ae089702d
Successfully built 418ae089702d
Successfully tagged XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/dynamo-test-app/front-end:594bd85
Login Succeeded
The push refers to repository [XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/dynamo-test-app/front-end]
f2ed02c7c10a: Pushed 
f978b9ed3f26: Pushed 
9040af41bb66: Pushed 
7c7d7f446182: Pushed 
d4cf327d8ef5: Pushed 
13cb14c2acd3: Pushed 
594bd85: digest: sha256:234bf1c50d5b5b0f27abaec5be3e2b33cf1f81f0caa3f3a5c015cb0610e79004 size: 1570


✔ Deployed front-end, you can access it at http://dynam-Publi-1J6Y56CHUQZF1-2062355131.ap-northeast-1.elb.amazonaws.com.

ECS クラスターと一緒にdynamo-test-app-test-front-end-copilot-sandbox-tableが作成されていました. f:id:sadayoshi_tada:20200803120639p:plain f:id:sadayoshi_tada:20200803121612p:plain

まとめ

ver0.2.0で追加されたcopilot storage initコマンドでできることと実際にリソースの作成を試してみました.サービスで指定した ECS リソース以外にも S3 や DynamoDB を利用したアーキテクチャを採用したい時にこのコマンドが役立つと思います.次はcopilot pipeline のコマンドについて記事を書きたいと思います.

関連記事

sadayoshi-tada.hatenablog.com

sadayoshi-tada.hatenablog.com

sadayoshi-tada.hatenablog.com