🤖

AWS入門 - Copilot 使ってみる

2021/11/19に公開

AWSを使う必要が出てきたので、色々と試してみる。
ここでは、Copilot を試す。

AWS Copilot

https://aws.github.io/copilot-cli/

もともとは Amazon ECS CLI というものがあったらしく、
それの後継にあたるのが AWS Copilot らしい。

ECS CLI の方は名前の通り、ECSに関する操作をCLI化したものである。
Copilot の方は、ECSを含めたアプリケーションとして必要なリソース群を、簡単に構築できるようにしたものである。
なので、後継とは言いつつも、それぞれ全くの別物である。

Copilot には、アプリケーション環境を簡単に構築できるようにする、独自の概念がある。
まずはそれらを確認していく。

Application

CopilotにおけるApplicationとは、
本番・検証・開発といった複数環境を全て含んでいる大きな概念となっている。

Applicationの中に複数のEnvironmentがあり、
Environmentの中に複数のServiceがある。

Environment

Environmentが、Prod・Stg・Devみたいなやつ。
よく環境と呼ばれるもの。
また、同一のEnvironment内に配置したServiceは、
同一のネットワーク・ECSクラスターなどを利用する形になるらしい。

Service

Serviceが、Frontend・Backend・Batchみたいなやつ。
MicroServicesのServiceがイメージとしては近い感じがする。

Serviceには決められたタイプがあり、タイプに応じて構築されるシステムの構成が決まる。
Service Typeは今の所、次の4つである。

  • Request-Driven Web Service (App Runner)
  • Load Balanced Web Service (Internet to ECS on Fargate)
  • Backend Service (ECS on Fargate)
  • Worker Service (Events to SQS to ECS on Fargate)

Job

単発実行するECSタスクに相当するもの。
Serviceと同じく、Jobにもタイプがあると思われる。
ただし、今の所は1つだけ。

  • Scheduled Job (Scheduled event to State Machine to Fargate)

Pipeline

ソースコードを元にサービスをデプロイするもの。
イメージのビルド・ECRへプッシュ・デプロイといった一連の流れ。

おそらくApplication内にPipelineは1つだけである。

まとめるとこんな感じ。
低コストでマイクロサービス化されたシステムを簡単に構築できそうである。

Copilotを使ってみる

とりあえず、単一のEnvironment・単一のServiceを含んだ、Applicationを作ってみたいと思う。
まずは、適当にディレクトを作成し、Dockerfileを置く。

Dockerfile
FROM nginx:latest

copilot initでサービスを作成し、"test" Environmentへとデプロイする。

$ copilot init
Welcome to the Copilot CLI! We're going to walk you through some questions
to help you get set up with a containerized application on AWS. An application is a collection of
containerized services that operate together.

Application name: app-1118
Workload type: Request-Driven Web Service
Service name: service-request-driven
Dockerfile: ./Dockerfile
parse EXPOSE: no EXPOSE statements in Dockerfile ./Dockerfile
Port: 80
Ok great, we'll set up a Request-Driven Web Service named service-request-driven in application app-1118 listening on port 80.

✔ Created the infrastructure to manage services and jobs under application app-1118..

✔ The directory copilot will hold service manifests for application app-1118.

✔ Wrote the manifest for service service-request-driven at copilot/service-request-driven/manifest.yml
Your manifest contains configurations like your container size and port (:80).

✔ Created ECR repositories for service service-request-driven..

All right, you're all set for local development.
Deploy: Yes

✔ Linked account xxxxxxxxxxxx and region ap-northeast-1 to application app-1118..

✔ Proposing infrastructure changes for the app-1118-test environment.
- Creating the infrastructure for the app-1118-test environment.         [create complete]  [101.4s]
  - An IAM Role for AWS CloudFormation to manage resources               [create complete]  [34.2s]
  - An ECS cluster to group your services                                [create complete]  [9.0s]
  - Enable long ARN formats for the authenticated AWS principal          [create complete]  [0.6s]
  - An IAM Role to describe resources in your environment                [create complete]  [32.2s]
  - A security group to allow your containers to talk to each other      [create complete]  [6.1s]
  - An Internet Gateway to connect to the public internet                [create complete]  [18.6s]
  - Private subnet 1 for resources with no internet access               [create complete]  [19.6s]
  - Private subnet 2 for resources with no internet access               [create complete]  [19.6s]
  - Public subnet 1 for resources that can access the internet           [create complete]  [19.6s]
  - Public subnet 2 for resources that can access the internet           [create complete]  [19.6s]
  - A Virtual Private Cloud to control networking of your AWS resources  [create complete]  [15.9s]
✔ Created environment test in region ap-northeast-1 under application app-1118.
Environment test is already on the latest version v1.6.1, skip upgrade.
Building your container image: docker build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-1118/service-request-driven --platform linux/amd64 /Users/xxxxxxxxxxxx/test-copilot -f /Users/xxxxxxxxxxxx/test-copilot/Dockerfile
[+] Building 3.0s (6/6) FINISHED
 => [internal] load build definition from Dockerfile                                                                                            0.0s
 => => transferring dockerfile: 59B                                                                                                             0.0s
 => [internal] load .dockerignore                                                                                                               0.0s
 => => transferring context: 2B                                                                                                                 0.0s
 => [internal] load metadata for docker.io/library/nginx:latest                                                                                 2.9s
 => [auth] library/nginx:pull token for registry-1.docker.io                                                                                    0.0s
 => CACHED [1/1] FROM docker.io/library/nginx:latest@sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e                    0.0s
 => => resolve docker.io/library/nginx:latest@sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e                           0.0s
 => exporting to image                                                                                                                          0.0s
 => => exporting layers                                                                                                                         0.0s
 => => writing image sha256:8418e0447b6addd3e821dacecac241952f2a9757452d6566b6e8b95d4a58f99c                                                    0.0s
 => => naming to xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-1118/service-request-driven                                              0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Login Succeeded
Using default tag: latest
The push refers to repository [xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-1118/service-request-driven]
8525cde30b22: Pushed
1e8ad06c81b6: Pushed
49eeddd2150f: Pushed
ff4c72779430: Pushed
37380c5830fe: Pushed
e1bbcf243d0e: Pushed
latest: digest: sha256:e2b2db2f958dab5a66d0c4ab3b237056d30628b0f2d841eb53f4cf5cae818a1c size: 1570
✔ Proposing infrastructure changes for stack app-1118-test-service-request-driven
- Creating the infrastructure for stack app-1118-test-service-request-driven      [create complete]  [253.1s]
  - An IAM Role for App Runner to use on your behalf to pull your image from ECR  [create complete]  [29.2s]
  - An IAM role to control permissions for the containers in your service         [create complete]  [29.8s]
  - An App Runner service to run and manage your containers                       [create complete]  [213.4s]
✔ Deployed service service-request-driven.
Recommended follow-up action:
    You can access your service at https://vnfmi8pe36.ap-northeast-1.awsapprunner.com over the internet.

色々とログが出ているが、裏側ではCloudFormationのStackを作成することで各リソースを作成している気がする。
なので、Stackを見れば何が作成されたのかが確認できそうである。
(CloudFormationの知識がないと、後々詰みそうな予感がする)

"infrastructure"と呼ばれているものに関連した部分では、次のようなものが作成されている。
ECRリポジトリだけService固有のもので、それ以外はApplicationとして必要なものっぽい。

  • IAMロール
  • ECRリポジトリ(app-1118/service-request-driven)
  • KMSキー
  • S3バケット

その後に"test"Environmentが作成されている。
VPC・Subnet・SecurityGroup・ECSクラスターなど一式が作成されている。
説明にあったとおり、同じEnvironment内であれば、同じネットワーク・ECSクラスターを使う形になるっぽい。(AppRunnerの場合は別)

最後に、Serviceが作成されている。
今回は、Request-Driven Web Serviceタイプを選択したので、App Runnerのサービスが作成されている。
他のタイプを選択した場合は、ECSサービスやCodePipelineなどが作成されるのだろう。

で、作成されたAppRunnerにアクセスすると、Welcome to nginx!が表示された。

まだ使っていない部分が沢山あるので、間違っていそうではあるが、全体像はこんな感じだろう。
基本的にはStackを作成することで、リソースを管理する。
そして、Copilitの役割としては、Stackをいい感じに隠蔽しながら環境を整える。

Copilot CLI

いくつかコマンドを試してみる。

参照系

$ copilot app show
About

  Name              app-1118
  Version           v1.0.2
  URI

Environments

  Name              AccountID           Region
  ----              ---------           ------
  test              xxxxxxxxxxxx        ap-northeast-1

Services

  Name                    Type
  ----                    ----
  service-request-driven  Request-Driven Web Service

Pipelines

  Name
  ----

$ copilot env ls
test

$ copilot env show --name test
About

  Name              test
  Production        false
  Region            ap-northeast-1
  Account ID        xxxxxxxxxxxx

Services

  Name                    Type
  ----                    ----
  service-request-driven  Request-Driven Web Service

Tags

  Key                  Value
  ---                  -----
  copilot-application  app-1118
  copilot-environment  test

$ copilot pipeline ls

$ copilot pipeline show
Only found one application, defaulting to: app-1118
No pipeline manifest in workspace for application app-1118, looking for deployed pipelines
No pipelines found for application app-1118.
$ copilot svc ls
Name                    Type
----                    ----
service-request-driven  Request-Driven Web Service

$ copilot svc show
Only found one service, defaulting to: service-request-driven
About

  Application       app-1118
  Name              service-request-driven
  Type              Request-Driven Web Service

Configurations

  Environment       CPU (vCPU)          Memory (MiB)        Port
  -----------       ----------          ------------        ----
  test              1                   2048                80

Routes

  Environment       URL
  -----------       ---
  test              https://vnfmi8pe36.ap-northeast-1.awsapprunner.com

Variables

  Name                      Environment         Value
  ----                      -----------         -----
  COPILOT_APPLICATION_NAME  test                app-1118
  COPILOT_ENVIRONMENT_NAME    "                 test
  COPILOT_SERVICE_NAME        "                 service-request-driven

デプロイ

指定のEnvironment・Serviceに対応するStackが更新され、リソースが更新される。
やはり、CloudFormationの知識がないと積むかもしれない。

$ copilot deploy
Only found one workload, defaulting to: service-request-driven
Only found one environment, defaulting to: test
Environment test is already on the latest version v1.6.1, skip upgrade.
Building your container image: docker build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-1118/service-request-driven --platform linux/amd64 /Users/xxxxxxxxxxxx/test-copilot -f /Users/xxxxxxxxxxxx/test-copilot/Dockerfile
[+] Building 3.2s (7/7) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                           0.0s
 => => transferring dockerfile: 91B                                                                                                                                                                                                                            0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                                              0.0s
 => => transferring context: 2B                                                                                                                                                                                                                                0.0s
 => [internal] load metadata for docker.io/library/nginx:latest                                                                                                                                                                                                3.1s
 => [internal] load build context                                                                                                                                                                                                                              0.0s
 => => transferring context: 357B                                                                                                                                                                                                                              0.0s
 => CACHED [1/2] FROM docker.io/library/nginx:latest@sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e                                                                                                                                   0.0s
 => => resolve docker.io/library/nginx:latest@sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e                                                                                                                                          0.0s
 => [2/2] COPY html /usr/share/nginx/html                                                                                                                                                                                                                      0.0s
 => exporting to image                                                                                                                                                                                                                                         0.0s
 => => exporting layers                                                                                                                                                                                                                                        0.0s
 => => writing image sha256:771fc70773bfcc7eebb955ba13f134e2e8c16ebb019815054d4ecb5ee0ad5aa9                                                                                                                                                                   0.0s
 => => naming to xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-1118/service-request-driven                                                                                                                                                             0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Login Succeeded
Using default tag: latest
The push refers to repository [xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-1118/service-request-driven]
5f4cfe345fc4: Pushed
8525cde30b22: Layer already exists
1e8ad06c81b6: Layer already exists
49eeddd2150f: Layer already exists
ff4c72779430: Layer already exists
37380c5830fe: Layer already exists
e1bbcf243d0e: Layer already exists
latest: digest: sha256:c207d3fe04b93e109b051886cdcec451f7f779e43ef13af16e82fde87c387ff8 size: 1777
✔ Proposing infrastructure changes for stack app-1118-test-service-request-driven
- Updating the infrastructure for stack app-1118-test-service-request-driven  [update complete]  [243.9s]
  - An App Runner service to run and manage your containers                   [update complete]  [234.0s]
✔ Deployed service service-request-driven.
Recommended follow-up action:
    You can access your service at https://vnfmi8pe36.ap-northeast-1.awsapprunner.com over the internet.

Application削除

AppRunnerサービスが停止され、各種Stackが削除された。
よって、関連するリソースも全て削除された。

$ copilot app delete
Sure? Yes
✔ Deleted service service-request-driven from environment test..
✔ Deleted resources of service service-request-driven from application app-1118..

✔ Deleted service service-request-driven from application app-1118.
✔ Deleted environment test from application app-1118..
✔ Cleaned up deployment resources..
✔ Deleted application resources..
✔ Deleted application configuration..
✔ Deleted local .workspace file.

まとめ

沢山あるので、まだほんの一部だがAppRunnerと同じく、抽象度が高くて良い感じ。
ただし、AppRunnerとは違って、使用する各リソースはコンソール画面から見える形になるので、そこらへんの運用コストは発生してしまう。

CloudFormationへの依存度が高そうなのが気になる点ではあるが、他の機能も続けて試してみたいと思う。

Copilotシリーズ

https://zenn.dev/umatoma/articles/ae776079a66f99
https://zenn.dev/umatoma/articles/8c25136a9fca46
https://zenn.dev/umatoma/articles/8e302614ba93c6

Discussion