AWS Copilot 深入淺出 教學

yysu
19 min readMay 1, 2021

在前一篇文章裡,我們大致瞭解了AWS Copilot的核心概念以及目的,在這一章中我們將更深入每一個模組,來了解每一個部分的意義是什麼,有哪些指令可以使用。

若你還不了解 AWS Copilot 是在做什麼,建議你先參考我的前一篇文章 AWS Copilot 介紹 實際上手 教學

Deep Dive into 各個組件

Applications

是 environments、services、pipelines 的集合。舉例來說,我們想要建一個投票的應用,該應用程式需要收集選票並彙總結果。

這個投票有兩項 services,要建立這個應用程式,我們可以運行兩次 copilot init 兩次,第一次運行 copilot init 時,會詢問我們該服務屬於哪個應用程式,我們可以將應用程式稱為 vote,將我們的第一個服務稱為 Collector。 再次運行 init 時,系統會詢問我們是否要將新 service 添加到現有的 Vote 應用中,並將新 service 命名為 Aggregator。

https://aws.github.io/copilot-cli/docs/concepts/applications/

這邊要稱讚 Copilot 一點,建立好的應用程式配置(哪些服務和環境屬於該配置)會存儲在您的AWS帳號中(利用SSM Parameter store,並且每個被創建出來的資源都會被加上 Tag : copilot-app,方便辨認),因此同帳號中的其他IAM user/role 也可以在同個應用程式上進行開發。

AWS SSM Parameter 中可以查看建立好的應用程式配置

儘管 Copilot 基礎設施的大部分是基於environment和service的,但也有一些應用程序範圍的資源,包括:

  • ECR 儲存庫
  • KMS Key、S3 Bucket 可用來作 CodePipeline 內 cross region和 cross account 部署

我們也可以透過 copilot app 來操作應用程式。

Environments

您的應用程式可以具有多個環境,並且每個環境都將具有自己的網絡和共享資源基礎結構。雖然 Copilot 在開始時創建了一個測試環境,但通常會創建一個新的單獨的Production環境。 這個生產環境將完全獨立於測試環境,並具有自己的網絡設施和服務,同時具有測試環境和生產環境,您可以將更改部署到測試環境,進行驗證,然後將其推廣到生產環境。

舉例來說,我們有一個名為 MyApp 的應用程式,其中包含兩項服務,即API和Backend,這兩個服務已部署到測試和生產兩個環境中,在測試環境中,兩個服務都只運行一個容器,而Production環境中的服務有多個運行的容器,服務可以根據所部署的環境使用不同的配置。

https://aws.github.io/copilot-cli/docs/concepts/environments/

如何創建新的環境?

可以運行下列指令, Copilot 會詢問環境的名稱,以及您想用來啟動該環境的配置文件。

$ copilot env init 

執行指令後,可以觀察到 Copilot 創建了新環境的所有資源。創建資源後,環境將連動應用程式的帳號。這樣即使沒有訪問該環境帳號的權限,應用程式帳號中的參與者也可以管理環境。如果需要,此連動過程還會創建並配置新的區域的 ECR 存儲庫。

Copilot environment 創建的基礎設施資源,包括:

  • VPC & Networking
  • Load Balancer and DNS (如果 service type 是Load Balanced,也可選擇給與 Route53 上 domain name,Copilot 會搞定一切…)

操作環境指令

$ copilot env ls
$ copilot env show

Services

Copilot 讓你在 AWS 上運行容器就像輸入 copilot init 一樣容易,Copilot將構建您的映像,將其推送到Amazon ECR,並設置所有基礎設施以 scalable 和安全的方式運行您的服務。

如何創建新的服務?

$ copilot svc init

這邊可以注意到目前支持的服務類型有下面幾種:

  • Load Balanced Web Service (可以接收 Internet 流量)
Load Balanced Web Service
  • Backend Service (不想讓 Internet 訪問)
Backend Service

Mainfest 與設置

在我們運行 copilot init 後,Copilot 會在 copilot 目錄中創建了一個名為manifest.yml 的文件,該文件包含服務的常用配置選項,雖然確切的選項取決於您正在運行的服務類型,但常見的選項包括分配給您的服務的資源 (如記憶體 & CPU),運行狀況檢查和環境變數。

也可以看一下先前部署的 front-end 的負載均衡Web服務的清單。

name: front-end
type: Load Balanced Web Service
# Distribute traffic to your service.
http:
# Requests to this path will be forwarded to your service.
# To match all requests you can use the "/" path.
path: '/'
# You can specify a custom health check path. The default is "/".
# healthcheck: '/'
# Configuration for your containers and service.
image:
# Docker build arguments. For additional overrides: https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/#image-build
build: Dockerfile
# Port exposed through your container to route traffic to it.
port: 80
cpu: 256 # Number of CPU units for the task.
memory: 512 # Amount of memory in MiB used by the task.
count: 1 # Number of tasks that should be running in your service.
exec: true # Enable running commands in your container.
# Optional fields for more advanced use-cases.
#
#variables: # Pass environment variables as key value pairs.
# LOG_LEVEL: info
#secrets: # Pass secrets from AWS Systems Manager (SSM) Parameter Store.
# GITHUB_TOKEN: GITHUB_TOKEN # The key is the name of the environment variable, the value is the name of the SSM parameter.
# You can override any of the values defined above by environment.
#environments:
# test:
# count: 2 # Number of tasks to run for the "test" environment.

想了解如何配置這個mainfest,可以參考https://aws.github.io/copilot-cli/docs/manifest/overview

如何在環境上部署服務 ?

$ copilot deploy # 如果您有多個環境,系統將提示您選擇要部署到的環境

運行這個命令將會:

  1. 在本地製作 Docker Image
  2. 推送到 ECR 存儲庫
  3. 將 Mainfest.yml 文件轉換為 CloudFormation
  4. 將任何其他基礎架構打包到CloudFormation中
  5. 將更新的服務和資源部署到CloudFormation
部署服務到創建好的 Staging 環境
$ copilot svc show

將顯示服務的summary。此輸出包括每個環境的服務配置,服務的所有端點以及傳遞到服務中的環境變數。 您還可以加 --resources flag,以查看與您的服務關聯的所有AWS資源。

如何查看服務的狀態?

$ copilot svc status

如何查看服務日誌?

$ copilot svc logs

Jobs

是由事件觸發的 ECS 任務。 目前 Copilot 只支持 “Scheduled Jobs”,這些任務可以按固定的時間或通過rate()定期觸發。

如何創建工作?

$ copilot job init

或是也可以建立 scheduled job manifest 文件,並用 copilot deploy 部署,其中包含由計劃事件觸發的任務的最常見配置。 例如,您可以配置何時觸發作業、容器大小、任務timeout 以及在失敗時重試多少次。

調度的 Job 由 ECS Task Definition, Task Role, Task Execution Role、用於重試故障的 Step Function State Machine 以及CloudWatch Event Rule 組成。

Pipelines

Copilot 希望使部署流程的設置盡可能容易,在本部分中,我們將討論使用Copilot 設置 CodePipeline,當您推送到GitHub,Bitbucket或AWS CodeCommit存儲庫時,自動部署到您的環境並運行自動化測試時,該管道會自動構建您的服務程式。

這邊 Copilot 文件[1]有解釋,為什麼會需要 Pipeline來發布應用?

We won’t get too philosophical about releasing software, but what’s the point of having a release pipeline? With copilot deploy you can deploy your service directly from your computer to ECS, so why add a middleman? That's a great question. For some apps, manually using deploy is enough, but as your release process gets more complicated (as you add more environments or add automated testing, for example) you want to offload the boring work of repeatedly orchestrating that process to a service. With two services, each having two environments (test and production, say), running integration tests after you deploy to your test environment becomes surprisingly cumbersome to do by hand.

Using an automated release tool like CodePipeline helps make your release manageable. Even if your release isn’t particularly complicated, knowing that you can just git push to deploy your change always feels a little magical 🌈.

[中文]

對於某些應用程式,使用 $ copilot deploy 手動進行就足夠了,但是隨著發布過程變得更加複雜(例如,隨著添加更多環境或添加自動化測試),您希望減輕將該過程中重複編排到服務中的無聊工作。 有了兩個服務,每個服務都有兩個環境(例如測試和生產),在部署到測試環境後運行集成測試變得非常麻煩。

使用 CodePipeline等自動發布工具有助於使發布易於管理。即使您的發行版本不是特別複雜,但是知道您可以通過 git push 部署來自動更改,感覺有些神奇。

Pipeline 架構

Copilot 可以通過一些命令為您設置CodePipeline,管道將具有以下基本結構:

  1. Source Stage : 推送到 GitHub、Bitbucket 或 CodeCommit存儲庫 branch時,將觸發管道執行。
  2. Build Stage : 從存儲庫主機中提取 Source code 後,將構建服務的容器映像並將其發佈到每個環境的 ECR 存儲庫中。
  3. Deploy Stage : 構建程式碼後,可以通過測試或手動批准後將其部署到任何或所有環境中。

使用 Copilot 設置 CodePipeline 後,只需將其推送到 GitHub,Bitbucket或CodeCommit 存儲庫,CodePipeline就會編排部署。

創建 Pipeline 三步驟

  1. 準備管道架構
  2. Commit 並推送 copilot/ 目錄中生成的文件。
  3. 創建實際的CodePipeline。

從工作區根目錄執行以下三個步驟:

$ copilot pipeline init 
$ git add copilot/pipeline.yml copilot/buildspec.yml copilot/.workspace && git commit -m "Adding pipeline artifacts" && git push
$ copilot pipeline update

下面將分別理解每個步驟中的重點:

  1. Configuring your Pipeline

管道配置是在本地 workspace 創建的。如果 workspace 只有一個服務,那麼只會為該服務觸發管道。但是如果 workspace 中有多個服務,則管道將在 workspace 中構建所有服務,因此要開始建立管道,請進入服務的 workspace 並運行:

$ copilot pipeline init

這個指令還不會創建管道,但會創建一些文件,這些文件將在創建管道時使用。

  • Release order::系統將提示您選擇要部署的環境,根據希望它們在管道中部署的順序選擇它們(部署一次在一個環境中發生)。例如:您可能想先部署到測試環境,然後再部署到產品環境。
  • Tracking repository:選擇了要部署到的環境後,系統將提示您選擇要跟踪 CodePipeline 的存儲庫。當推送到該存儲庫時,它將觸發管道執行。

2. Updating the Pipeline manifest (optional)

運行 $ copilot pipeline init 之後,將在copilot/目錄中創建兩個文件:pipeline.yml 和buildspec.yml。

pipeline.yml

# This YAML file defines the relationship and deployment ordering of your environments.# The name of the pipeline
name: pipeline-demo-aws-copilot-sample-service
# The version of the schema used in this template
version: 1
# This section defines the source artifacts.
source:
# The name of the provider that is used to store the source artifacts.
provider: GitHub
# Additional properties that further specifies the exact location
# the artifacts should be sourced from. For example, the GitHub provider
# has the following properties: repository, branch.
properties:
branch: main
repository: https://github.com/aws-samples/aws-copilot-sample-service
# The deployment section defines the order the pipeline will deploy
# to your environments.
stages:
- # The name of the environment to deploy to.
name: test
# Optional: flag for manual approval action before deployment.
# requires_approval: true
# Optional: use test commands to validate this stage of your build.
# test_commands: [echo 'running tests', make test]
- # The name of the environment to deploy to.
name: staging
# Optional: flag for manual approval action before deployment.
# requires_approval: true
# Optional: use test commands to validate this stage of your build.
# test_commands: [echo 'running tests', make test]

該文件包含3個主要部分:name,即您的CodePipeline的名稱 source,其詳細說明要跟踪的存儲庫和 branch,以及 stages,其列出了您希望將此管道部署到的環境。您可以隨時進行更新,但是之後必須運行 $ copilot pipeline update。

Step 3: Updating the Buildspec (optional)

pipeline init命令還在copilot/目錄中生成了一個 buildspec.yml 文件。 其中包含有關構建和發布服務的說明。 如果要運行除docker build之外的任何其他命令(例如單元測試或 style checks),請將其添加到buildspec的構建階段。

運行此 buildspec 時,它將拉下運行 pipeline init 時使用的Copilot版本,以確保向後兼容。

Step 4: Pushing New Files to your Repository

將 pipeline.yml,buildspec.yml和 .workspace 添加到存儲庫中,copilot/ 目錄中的這些文件是管道 build 階段成功運行所必需的。

Step 5: Creating your Pipeline

運行:

$ copilot pipeline update

這將解析您的 pipeline.yml,在與您的應用相同帳號和區域中創建一個CodePipeline,並開始執行管道。

https://aws.github.io/copilot-cli/docs/concepts/pipelines/

如何添加測試於Pipeline中?

要添加在部署階段之後運行的測試,例如 integration test 或 End-to-End test,請在 test_commands 部分中包括這些命令。 如果所有測試都成功,則您的更改將升級到下一個階段。

加入 test_commands 會生成帶有aws/codebuild/amazonlinux2-x86_64-standard:3.0 映像的 CodeBuild 項目,因此,可以使用Amazon Linux 2中的大多數命令(包括make)。Copilot 的測試命令 CodeBuild 項目支持Docker,因此也可以使用 docker build 命令。在下面的示範中,管道將運行make test 命令(在您的source code目錄中),並且僅在該命令成功退出時才將更改提升到prod階段。

name: pipeline-ecs-kudos-kohidave-demo-api-frontend
version: 1
source:
provider: GitHub
properties:
branch: main
repository: https://github.com/kohidave/demo-api-frontend
stages:
-
name: test
# A change will only deploy to the production stage if the
# make test and echo commands exit successfully.
test_commands:
— make test
— echo "woo! Tests passed"
-
name: prod

References :

[1] https://aws.github.io/copilot-cli/docs/concepts/pipelines/

如果有什麼漏掉或是我誤會的地方,也歡迎你留言來補充、糾正我,能夠互相學是一件很棒的事,如果你覺得這篇文章對你有幫助,也希望你可以不吝於幫我點個讚,點50個讚也可以,謝謝你的觀看🙂

--

--

yysu

AWS Certified All-5 | CKA & CKAD | Ex - Cloud Engineer @ AWS