使用 Amazon Copilot 在一小时内为连接微服务构建高效的 CI/CD 管道

本文将介绍如何使用 Amazon Copilot 为连接微服务构建 CI/CD 管道。这应该会加快使用 Amazon ECS 在亚马逊云科技云上部署和托管基于容器的服务的过程。
发布时间:2023 年 4 月 26 日
DevOps
容器
Copilot
服务发现
CI-CD
ECS
Fargate
教程
亚马逊云科技

随着应用程序现代化的兴起,将单体应用程序分解为微服务成为了一个重大话题。本质上,这个过程首先会将单体应用程序分解为独立运行的功能单元,从而让使用容器等工具创建虚拟化应用程序环境变得更容易。与此同时,还会引出另一个问题:对于所有微服务,是选择使用一个(统一的)代码仓库,还是为每个微服务维护各自的代码存储库。

每项微服务保持独立的代码存储库有以下几点优势:

  • 加快软件的发布速度
  • 能够组建小团队专注于单个服务的开发和交付
  • 让团队能够维护较小的代码库,降低复杂性
  • 能够使用更小的代码库实现更快的构建和部署过程
  • 能够自由地独立地编写代码,使每个服务都能独立于其他服务(使用不同的编程语言、库、方法等)

为每个微服务都创建单独的存储库有利于团队进行自主的开发和发布周期管理。即便如此,当微服务相互关联时,接下来的问题就是如何轻松地创建所需的基础设施。与大多数问题一样,这需要权衡,毕竟问题的复杂性不会奇迹般地消失。此时,原本单个应用程序系统中多个部件所带来的复杂性通过拆分成单独的服务而降低了,并将复杂性转移至基础设施和协调服务上。好在随着微服务架构的日趋成熟,在过去十年里,用于管理这些的工具和方法得到了显著改善。

本教程将向您展示如何利用 Amazon Copilot CLI - 通过 Amazon Copilot 让您在一小时内快速为连接微服务构建高效的 CI/CD 管道。Amazon Copilot CLI 是一款工具,可供开发人员在 Amazon App RunnerAmazon ECSAmazon Fargate 上构建、发布和运维适用于生产环境的容器化应用程序。关于 Copilot 及其核心概念的详细信息,请参阅 Copilot 官方文档

Olawale Olaleye
亚马逊云科技使用经验
200 - 中级
完成所需时间
60 分钟
所需费用
支持亚马逊云科技免费套餐
前提条件

注册 / 登录 亚马逊云科技账户

示例代码

本教程中使用的示例代码来自 GitHub

上次更新时间
2023 年 4 月 26 日

架构

上面的架构图显示了一个三层应用程序,其中应用程序负载均衡器(ALB)将流量转发到 frontend(前端)ECS 服务。前端 ECS 服务向浏览器提供网页内容,并充当路由器,进而与执行业务逻辑的 backend(后端)ECS 服务进行通信。后端 ECS 服务继而使用 DynamoDB 表来插入/更新/删除数据。在这种情况下,前端和后端都是单独的微服务、使用各自的 CI/CD 管道和 Git 存储库进行维护。前端利用服务发现创建的易于使用的 DNS 域名与后端进行通信。Amazon ECS 上的服务发现功能在发生扩容和缩容事件期间管理 DNS 记录。虽然这些应用程序功能上互相依存并可以单独访问,但上述基础架构让我们可以将每个微服务作为独立单元部署。

在下一节中,您将使用 Amazon Copilot 构建和部署上述架构。您将使用示例 Todo(待办) 应用程序。该应用采用 ReactJs 构建用户界面,并由前端服务托管。Todo 服务能够帮助您规划工作和生活,所有数据将存储在 DynamoDB 表中以供后续访问。您还可以利用 Todo 服务添加更多待办事项,也可以删除不需要的待办事项。前端服务还使用 Nginx 代理服务器处理从负载均衡器接收的请求,进而充当后端服务的路由器。后端服务执行管理 DynamoDB 表中存储的数据的实际业务逻辑。与后端服务关联的服务发现会维护 Route53 私有托管区域中的 DNS 记录。这对于维护前端服务的正确 DNS 记录来说至关重要,能方便使用易于记忆的 URL 访问后端服务,因为后端服务的内部 IP 地址可能会因扩缩事件的发生而变化。前端和后端都部署在同一 VPC 内,并放置在私有子网内。应用程序负载均衡器放置在公有子网内。此功能运行所需的所有基础设施都可以使用 Amazon Copilot 创建。

前提条件

您需要满足一些前提条件才能进行本文所描述的操作。确保您已配置以下项目以进行本文所描述的操作:

  1. 有效的亚马逊云科技账户
  2. Amazon Copilot 已安装
  3. Amazon CLI 已安装配置,以便与您的账户进行交互
  4. Git 客户端 已安装
  5. Docker 在您的工作站上已安装运行

初始设置

在本节中,您将进行初始设置以作为开始使用 Copilot 的基本前提,即拉取示例应用程序代码,并在您的终端上初始化应用程序和环境。我们将从示例应用程序开始(其中所有代码都位于统一存储库中),随后我们会将其前端和后端服务作为独立的单元进行部署,并通过 CI/CD 流程把代码分别迁移至它们的专有存储库。如果您尚未设置 Copilot CLI,请确保您已安装。

1.下载示例应用程序的副本

将示例应用程序下载到本地工作站并将目录更改为代码位置:

git clone git@github.com:build-on-aws/automate-container-microservices-aws-copilot.git
cd automate-container-microservices-aws-copilot/code

代码目录结构应如下所示(如果感兴趣,这是使用 tree -d 生成的 ):

.
├── backend
│ └── manifests
│ ├── backend
│ │ └── addons
│ ├── environments
│ │ └── development
│ └── pipelines
│ └── todobackend-main
└── frontend
 ├── manifests
 │ ├── environments
 │ │ └── development
 │ ├── frontend
 │ └── pipelines
 │ └── todofrontend-main
 └── webapp
 ├── public
 └── src
 ├── components
 └── modules

2.导航至后端文件夹

确保您位于终端上的 backend 文件夹内。如果不在,请运行以下命令更改当前所处目录:

cd backend/

文件夹结构应如下所示:

.
├── Dockerfile
├── app.py
└── requirements.txt

3.使用 Copilot 初始化应用程序

使用 Copilot 的第一步是使用现有代码初始化新的应用程序。运行以下命令以使用 Copilot 初始化后端:

copilot app init todo

执行上述命令后,您看到的结果应该类似于以下内容:

✔ Proposing infrastructure changes for stack todo-infrastructure-roles
- Creating the infrastructure for stack todo-infrastructure-roles [create complete] [39.0s]
 - A StackSet admin role assumed by CloudFormation to manage regional stacks [create complete] [16.0s]
 - An IAM role assumed by the admin role to create ECR repositories, KMS keys, and S3 buckets [create complete] [17.2s]
✔ The directory copilot will hold service manifests for application todo.

Recommended follow-up action:
 - Run `copilot init` to add a new service or job to your application.

当运行 copilot app init 时,Copilot 使用 Amazon CloudFormation 创建 IAM 角色来管理服务和作业。Copilot 还会将 /copilot/applications/todo 参数注册到 Systems Manager Parameter Store 中。例如,如果运行 copilot app ls,Copilot 会检查 Parameter Store 并通知您该亚马逊云科技区域中存在的所有应用程序。

您可以看到新创建的 copilot 目录。该目录会保存清单文件。

4.创建开发环境

现在我们已经初始化了一个应用程序,我们需要对其进行部署。Copilot 支持定义多个环境,我们要创建一个名为 development 的环境。运行 copilot env init 命令来创建开发环境。按照交互式终端提示操作并提供输入。您会看到几个问题,需要您提供以下答案:

  • 您的环境的名称是什么?输入 development。
  • 您要使用哪些凭证来创建开发环境?Choose the profile for your development account(选择您开发账户的配置文件)然后按回车键。
  • 是否在新环境中使用默认配置?选择 Yes, use default. 然后按回车键。

这条命令会在 copilot/environments/development/manifest.yml 中生成一个 yaml 文件。这个清单文件包含 Copilot 设置的环境的配置。

在创建环境时,Copilot 会在 Amazon Systems Manager Parameter Store 中注册该环境的参数,并创建一个 IAM 角色来管理 Copilot 为所有基础设施创建的 Amazon CloudFormation 堆栈。您可以在终端上看到进度。环境创建完成后,您将在屏幕上看到以下输出结果:

Environment name: development
Credential source: [profile default]
Default environment configuration? Yes, use default.
✔ Wrote the manifest for environment development at copilot/environments/development/manifest.yml
- Update regional resources with stack set "todo-infrastructure" [succeeded] [0.0s]
- Update regional resources with stack set "todo-infrastructure" [succeeded] [125.6s]
 - Update resources in region "us-west-2" [create complete] [127.7s]
 - KMS key to encrypt pipeline artifacts between stages [create complete] [120.6s]
 - S3 Bucket to store local artifacts [create complete] [3.0s]
✔ Proposing infrastructure changes for the todo-development environment.
- Creating the infrastructure for the todo-development environment. [create complete] [41.5s]
 - An IAM Role for AWS CloudFormation to manage resources [create complete] [15.7s]
 - An IAM Role to describe resources in your environment [create complete] [16.3s]
✔ Provisioned bootstrap resources for environment development in region us-west-2 under application todo.
Recommended follow-up actions:
 - Update your manifest copilot/environments/development/manifest.yml to change the defaults.
 - Run `copilot env deploy --name development` to deploy your environment.

运行 copilot env ls 命令来查看开发环境是否已经创建。应该会看到以下输出结果:

$ copilot env ls
development

5.在开发环境中创建所需的基础设施

现在我们已经初始化了 Copilot 应用程序并创建好了环境,该是时候创建运行容器化应用程序所需的基础设施了。运行 copilot env deploy 命令,如果您之前使用过 Copilot 并且已在初始化命令指定的账户中创建了一些应用程序,那么运行这条命令只会提示您输入。如果只创建了一个环境,Copilot 就会默认使用该环境。现在,Copilot 将继续创建 VPC、公共子网、私有子网、用于服务发现的 Route53 私有托管域、自定义路由表、用于容器相互通信的安全组以及用于对 ECS 服务进行分组的 ECS 集群。环境创建完成后,您将看到以下输出结果:

Only found one environment, defaulting to: development
✔ Proposing infrastructure changes for the todo-development environment.
- Creating the infrastructure for the todo-development environment. [update complete] [73.1s]
 - An ECS cluster to group your services [create complete] [7.5s]
 - A security group to allow your containers to talk to each other [create complete] [0.0s]
 - An Internet Gateway to connect to the public internet [create complete] [17.1s]
 - Private subnet 1 for resources with no internet access [create complete] [3.4s]
 - Private subnet 2 for resources with no internet access [create complete] [3.3s]
 - A custom route table that directs network traffic for the public subnets [create complete] [10.9s]
 - Public subnet 1 for resources that can access the internet [create complete] [3.3s]
 - Public subnet 2 for resources that can access the internet [create complete] [0.0s]
 - A private DNS namespace for discovering services within the environment [create complete] [42.6s]
 - A Virtual Private Cloud to control networking of your AWS resources [create complete] [11.0s]

现在我们已经准备好部署我们的第一个服务了。下面,我们将部署基础设施和应用程序。我们会先部署后端,再部署前端。

创建后端服务

我们现在可以开始部署后端了。为了实际示范如何拆分单体应用程序,我们将部署 Mono-repo 中 backend 文件夹里的现有代码,创建所需的 DynamoDB 表,然后将其移至新的存储库。在代码提交到新的存储库后,我创建一个 CI/CD 管道,该管道将自动构建和部署我们将来对代码所做的任何更改。

1.初始化后端服务

在这一步,您将创建一个 ECS 服务来托管 ECS 任务中的后端应用程序。如架构图所示,后端服务同样也需要一个 DynamoDB 表作为数据库。您也将在此步骤中通过 Copilot 创建来创建这个 DynamoDB 表。

运行 copilot svc init 命令来创建定义后端服务的清单文件。

您会看到几个问题,需要您提供以下答案:

  • 您的服务架构最符合哪种服务类型?选择 Backend(后端) Service(服务)然后按回车键。
  • 您想将此服务命名为?输入 backend(后端)。
  • 您想将哪个 Dockerfile 用于后端?选择 ./Dockerfile 然后按回车键。

该命令会创建一个 ECR 存储库来保存后端服务的 Docker 镜像,并创建一个 copilot/backend 目录来保存清单文件。后端服务创建完成后,您将看到以下输出结果:

$ copilot svc init
Note: It's best to run this command in the root of your workspace.
Service type: Backend Service
Service name: backend
Dockerfile: ./Dockerfile
✔ Wrote the manifest for service backend at copilot/backend/manifest.yml
Your manifest contains configurations like your container size and port (:10000).

- Update regional resources with stack set "todo-infrastructure" [succeeded] [11.8s]
 - Update resources in region "us-west-2" [update complete] [6.3s]
 - ECR container image repository for "backend" [create complete] [2.2s]
Recommended follow-up actions:
 - Update your manifest copilot/backend/manifest.yml to change the defaults.
 - Run `copilot svc deploy --name backend --env test` to deploy your service to a test environment.

这样只会为容器镜像创建 ECR 存储库,并不会构建镜像或部署镜像。copilot svc init 命令在 copilot/backend/manifest.yml 文件中创建了一个清单文件。为了确保我们可以监视容器是否正常运行,我们需要添加运行状况检查。运行状况检查是一个定期访问的端点,用于报告应用程序是否正常运行。它可以运行一系列内部检查,或者仅以 HTTP“OK”(HTTP 响应 200)作为响应。要添加运行状况检查,请修改 copilot/backend/manifest.yml 并添加 port 下的 image 选项下显示的 healthcheck 选项:

image:
 build: backend/Dockerfile
 # Port exposed through your container to route traffic to it.
 port: 10000
 healthcheck:
 command: ["CMD-SHELL", "curl -f http://localhost:10000/ishealthy || exit 1"]
 interval: 10s
 retries: 2
 timeout: 6s 
 start_period: 10s

如果您想了解运行状况检查是如何在后端实现的,可以看一下 app.py 中添加的 路由

@app.route('/ishealthy')
def receive_health_check():
 return "Health check succeed\n"

2.创建 DynamoDB 表

在这一步,您将使用 Copilot 创建后端服务所需的 DynamoDB 表。后端服务使用 DynamoDB 表来保存待办事项。您可以通过 copilot storage init 命令将存储资源添加到服务中。

运行 copilot storage init 命令创建供后端服务使用的 DynamoDB 表。

您会看到几个问题,需要您提供以下答案:

  • 您希望将哪种类型的存储与后端关联?选择 DynamoDB 然后按回车键。
  • 您想将此 DynamoDB 表命名为?输入 todotable(待办事项表)。
  • 您是否希望该存储与后端服务同步创建和删除?选择 Yes, the storage should be created and deleted at the same time as backend(是,该存储应与后端同时创建和删除)
  • 您想将此 DynamoDB 的分区键命名为?输入 TodoId
  • 该分区键是什么数据类型?选择 Number(数值)然后按回车键
  • 您是否想为此表添加排序键?输入 n

通过运行 copilot storage init 命令,Copilot 会创建 一个 copilot/backend/addons 目录和并会在该目录中创建todotable.yml 一个 Amazon CloudFormation 模板:。Copilot 会使用此模板创建其他资源。Amazon CloudFormation 模板创建后,您应该会看到以下输出结果:

$ copilot storage init
Storage type: DynamoDB
Only found one workload, defaulting to: backend
Storage resource name: todotable
Lifecycle: Yes, the storage should be created and deleted at the same time as backend
Partition key: TodoId
Partition key datatype: Number
Sort key? No
✔ Wrote CloudFormation template at copilot/backend/addons/todotable.yml

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

上述设置还会在 ECS 任务定义中创建一个名为 TODOTABLE_NAME 的环境变量。如果查看 app.ts 文件,应用程序已经可以通过以下代码行 使用该环境变量

table_name = os.getenv('TODOTABLE_NAME')

3.部署后端服务

运行 copilot svc deploy 命令自动将后端服务部署至开发环境。您尚未构建 Docker 镜像,因此构建容器镜像将需要一些时间。您可以在终端上看到进度。

部署完成后,您应该会看到以下输出结果:

✔ Proposing infrastructure changes for stack todo-development-backend
- Creating the infrastructure for stack todo-development-backend [create complete] [325.6s]
 - An Addons CloudFormation Stack for your additional AWS resources [create complete] [42.5s]
 - An IAM ManagedPolicy for your service to access the todotable db [create complete] [18.6s]
 - An Amazon DynamoDB table for todotable [create complete] [11.4s]
 - Service discovery for your services to communicate within the VPC [create complete] [0.0s]
 - Update your environment's shared resources [create complete] [0.0s]
 - An IAM role to update your environment stack [create complete] [20.4s]
 - An IAM Role for the Fargate agent to make AWS API calls on your behalf [create complete] [20.4s]
 - A CloudWatch log group to hold your service logs [create complete] [0.0s]
 - An ECS service to run and maintain your tasks in the environment cluster [create complete] [245.3s]
 Deployments 
 Revision Rollout Desired Running Failed Pending 
 PRIMARY 1 [completed] 1 1 0 0 
 - An ECS task definition to group your containers and run them on ECS [create complete] [3.2s]
 - An IAM role to control permissions for the containers in your tasks [create complete] [18.5s]
✔ Deployed service backend.
Recommended follow-up action:
 - You can access your service at backend:10000 with service connect.

部署完成后,运行 copilot svc status 查看服务状态。如果状态为 ACTIVE,则表示容器正常运行。

Found only one deployed service backend in environment development
Task Summary

 Running ██████████ 1/1 desired tasks are running

Tasks

 ID Status Revision Started At
 -- ------ -------- ----------
 121b23ed RUNNING 1 12 minutes ago

Copilot 还为后端服务设置了服务发现。服务发现使用 Amazon Cloud Map API 操作来管理 Amazon ECS 服务的 HTTP 和 DNS 命名空间,让其他服务能够向您的服务发送请求。COPILOT_SERVICE_DISCOVERY_ENDPOINT 是 Copilot CLI 在创建服务时为您设置的特殊环境变量。其格式为 {env name}.{app name}.local,/api 请求会传递至 http://backend.development.todo.local:10000/。端点 backend.development.todo.local 会解析为私有 IP 地址,并会在您的 VPC 内通过私有路由连接至后端服务。配置前端服务时,您将使用 COPILOT_SERVICE_DISCOVERY_ENDPOINT 环境变量通过服务发现来访问后端服务。有关服务发现的更多信息,请参阅此处

4.创建后端的 CI/CD 管道

我们现在要开始将后端服务的代码移至专有存储库。首先,我们将代码移动到一个新的空目录。第一步,切换回原来克隆的 automate-container-microservices-aws-copilot 目录所在的根目录,然后运行:

mkdir todobackend
mv automate-container-microservices-aws-copilot/code/backend/* todobackend/

todobackend 文件夹现在应包含以下内容:

.
├── Dockerfile
├── app.py
├── copilot
│ ├─ backend
│ │ ├─ addons
│ │ │ └── todotable.yml
│ │ └── manifest.yml
│ └── environments
│ └── development
│ └── manifest.yml
├─ manifests
│ ├─ backend
│ │ ├─ addons
│ │ │ └── todotable.yml
│ │ └── manifest.yml
│ └── environments
│ └── development
│ └── manifest.yml
└── requirements.txt

我们现在准备将这个新目录初始化为 Git 存储库,创建托管 Git 存储库,并将本地 Git 存储库设置为使用新的远程存储库。我们将使用 Amazon CodeCommit 存储库来对这个方法进行说明。使用以下命令切换到后端源目录,创建新的 CodeCommit 存储库,将本地目录初始化为 Git 存储库,然后将其设置为使用远程 CodeCommit 存储库:

cd todobackend
aws codecommit create-repository --repository-name todobackend --repository-description "My todoapp repository"
git init
git switch -c main
git remote add origin https://git-codecommit.$(aws configure get region).amazonaws.com/v1/repos/todobackend

接下来,运行 copilot pipeline init 生成管道清单。这将在清单文件中创建管道的配置,但并未完成对管道的设置。您会注意到 URL 中的 $(aws configure get region),这将获取您的 Amazon CLI 设置使用的区域,以确保我们创建的 CodeCommit 存储库所在的区域与基础设施其余部分所在的区域相同。您还将在自己输入的命令和要求输入的位置之间看到一条错误消息,其中包含以下内容:

Only one git remote detected. Your pipeline will follow 'https://git-codecommit.us-west-2.amazonaws.com/v1/repos/todobackend'.
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
Your pipeline will follow branch 'main'.

这是因为 Git 仍然在使用 master 作为分支名,我们用 git switch -c main 命令将其更改为使用 main 作为分支名,但尚未提交任何内容。Copilot 会默认使用 main,因为这是当前选定的分支,因此您可以忽略此错误。我们继续按照提示创建 CI/CD 管道。您会看到几个问题,需要您提供以下答案:

  • 您想将此管道命名为?输入 todobackend-main 并按回车键。
  • 这是什么类型的持续交付管道?选择 Workloads(工作负载)并按回车键。
  • 您想将哪种环境添加到您的管道中?选择 development(开发)并按回车键。
  • 您想将哪种环境添加到您的管道中?选择 No additional environments(无其他环境)并按回车键。(如果您从未使用过 Copilot,则不会显示此选项,并会默认添加 development 环境)

然后应该会看到以下输出结果:

Pipeline name: todobackend-main
What type of continuous delivery pipeline is this? Workloads
1st stage: development

✔ Wrote the pipeline manifest for todobackend at 'copilot/pipelines/todobackend-main/manifest.yml'
The manifest contains configurations for your pipeline.
Update the file to add stages, change the tracked branch, add test commands or manual approval actions.
✔ Wrote the buildspec for the pipeline's build stage at 'copilot/pipelines/todobackend-main/buildspec.yml'
The buildspec contains the commands to push your container images, and generate CloudFormation templates.
Update the "build" phase to unit test your services before pushing the images.

Required follow-up actions:
- Commit and push the copilot/ directory to your repository.
- Run `copilot pipeline deploy` to create your pipeline.

我们现在准备创建管道,运行 copilot pipeline deploy 进行来创建。此命令使用作为远程 Git 存储库添加的 CodeCommit 存储库作为 CodePipeline 的源阶段。命令成功后,您应该在终端上看到输出结果,如下所示:

$ copilot pipeline deploy
Only found one pipeline; defaulting to: todobackend-main
✔ Successfully added pipeline resources to your application: todo
✔ Successfully created a new pipeline: todobackend-main

最后,将本地代码推送到 CodeCommit 存储库:

git add -A
git commit -m 'initial commit'
git push origin main

此时,您可以转到亚马逊云科技账户中的 CodePipeline 控制台来查看管道运行。未来对后端应用程序的任何更改都可以在 Git 存储库中进行,并且将更改推送到远程存储库,应该就会通过 CodePipeline 自动部署您的代码。

创建前端服务

我们现在要创建前端服务。由于我们在上一节配置后端服务时已经设置了 Copilot 应用程序和环境,因此我们不需要再次创建它们,直接利用现有资源即可。我们将用相同的方法,首先创建并部署前端,然后将其移至其存储库,然后创建 CI/CD 管道来部署对该存储库所做的更改。

1.初始化前端服务

要部署前端,首先要再次导航至automate-container-microservices-aws-copilot 中的 code/frontend 目录。文件夹结构应如下所示:

.
├── Dockerfile
├── backend.conf.template
├── nginx.conf
└── webapp
 ├── README.md
 ├── package.json
 ├── public
 │ ├── index.html
 │ ├── manifest.json
 │ └── robots.txt
 ├── src
 │ ├── App.css
 │ ├── App.test.tsx
 │ ├── App.tsx
 │ ├── Types.ts
 │ ├── components
 │ │ ├── TableOperation.tsx
 │ │ ├── TaskInput.tsx
 │ │ ├── TaskItem.tsx
 │ │ ├── TaskList.tsx
 │ │ └── util.ts
 │ ├── index.css
 │ ├── index.tsx
 │ ├── modules
 │ │ └── tasksModule.ts
 │ ├── react-app-env.d.ts
 │ ├── reportWebVitals.ts
 │ ├── rootReducer.ts
 │ ├── setupTests.ts
 │ └── store.ts
 └── tsconfig.json

执行 copilot app init 以初始化前端应用程序。Copilot 会检测我们之前创建的应用程序和环境。您会看到几个问题,需要您提供以下答案:

  • 您是否要使用现有的应用程序?(Y/n) 选择 Y(是)。
  • 您想要向哪个现有应用程序添加新服务或作业?(使用方向键移动光标,键入内容进行筛选,如需更多帮助请按“?”)选择 todo

结果应该如下所示:

Use existing application: Yes
Application name: todo
✔ Proposing infrastructure changes for stack todo-infrastructure-roles
✔ The directory copilot will hold service manifests for application todo.

Recommended follow-up action:
 - Run `copilot init` to add a new service or job to your application.

2.准备初始化并部署前端服务

我们现在准备初始化并部署前端服务。您可能已经注意到,我们跳过了创建环境的步骤,这是有意为之,因为 Copilot 会检测是否存在任何已配置的环境。如果您以前使用过 Copilot,会看到一个列表供您选择。如果这是您第一次使用,它会检测到只有 development 环境,并默认会使用该环境。

要初始化前端服务,运行 copilot svc init 命令来创建定义前端服务的清单文件。您会看到几个问题,需要您提供以下答案:

  • 您的服务架构最符合哪种服务类型?选择 Load Balanced Web Service(负载均衡 Web 服务)并按回车键。
  • 您想将此服务命名为?输入 frontend(前端)。
  • 您想将哪个 Dockerfile 用于后端?选择 .Dockerfile 并按回车键。

与后端服务类似,这会创建一个 ECR 存储库来存储前端服务的 Docker 镜像,并会在 copilot/frontend 中创建清单文件。完成后,您应该会看到类似以下的输出:

Note: It's best to run this command in the root of your workspace.
Service type: Load Balanced Web Service
Service name: frontend
Dockerfile: ./Dockerfile
✔ Wrote the manifest for service frontend at copilot/frontend/manifest.yml
Your manifest contains configurations like your container size and port (:80).

- Update regional resources with stack set "todo-infrastructure" [succeeded] [10.2s]
 - Update resources in region "us-west-2" [update complete] [9.0s]
 - ECR container image repository for "frontend" [create complete] [4.4s]
Recommended follow-up actions:
 - Update your manifest copilot/frontend/manifest.yml to change the defaults.
 - Run `copilot svc deploy --name frontend --env test` to deploy your service to a test environment.

3.部署前端服务

我们现在可以开始部署前端了,我们运行 copilot svc deploy 将其部署至开发环境。我们还没有构建 Docker 镜像,因此需要一些时间来构建。该命令的输出能让您随时了解进度以及出现的任何错误。部署完成后,您应该会看到以下内容:

✔ Proposing infrastructure changes for stack todo-development-frontend
- Creating the infrastructure for stack todo-development-frontend [create complete] [299.3s]
 - Service discovery for your services to communicate within the VPC [create complete] [0.0s]
 - Update your environment's shared resources [update complete] [115.4s]
 - A security group for your load balancer allowing HTTP traffic [create complete] [2.5s]
 - An Application Load Balancer to distribute public traffic to your services [create complete] [88.2s]
 - A load balancer listener to route HTTP traffic [create in progress] [154.6s]
 - An IAM role to update your environment stack [create complete] [18.7s]
 - An IAM Role for the Fargate agent to make AWS API calls on your behalf [create complete] [16.3s]
 - An HTTP listener rule for path `/` that forwards HTTP traffic to your tasks [create complete] [3.3s]
 - A custom resource assigning priority for HTTP listener rules [create complete] [2.6s]
 - A CloudWatch log group to hold your service logs [create complete] [0.0s]
 - An IAM Role to describe load balancer rules for assigning a priority [create complete] [14.7s]
 - An ECS service to run and maintain your tasks in the environment cluster [create complete] [125.2s]
 Deployments 
 Revision Rollout Desired Running Failed Pending 
 PRIMARY 1 [completed] 1 1 0 0 
 - A target group to connect the load balancer to your service on port 80 [create complete] [17.1s]
 - An ECS task definition to group your containers and run them on ECS [create complete] [2.2s]
 - An IAM role to control permissions for the containers in your tasks [create complete] [17.1s]
✔ Deployed service frontend.
Recommended follow-up action:
 - You can access your service at http://todo-Publi-14BEAZOWSOFPS-1809648126.us-west-2.elb.amazonaws.com over the internet.

您现在可以使用浏览器和部署返回的 URL 来访问待办事项应用程序。要查看有关服务的更多详细信息,您可以运行 copilot svc status,然后选择您想要查看状态的服务。要确认容器是否已成功部署,请选择 frontend 服务并查找 RUNNING 状态。您应当会看到类似于以下内容的输出:

Service: frontend
Task Summary

 Running ██████████ 1/1 desired tasks are running
 Health ██████████ 1/1 passes HTTP health checks

Tasks

 ID Status Revision Started At HTTP Health
 -- ------ -------- ---------- -----------
 fc25084a RUNNING 1 2 hours ago HEALTHY

此时,我们已经部署了前端和后端服务,您应该看到服务正在运行,打开浏览器并使用输出 URL。显示内容应如下所示:

如果您想知道前端服务如何了解后端服务,请查看 Nginx 配置文件:backend.conf.template。/api 请求会传递至 backend.${COPILOT_SERVICE_DISCOVERY_ENDPOINT}。COPILOT_SERVICE_DISCOVERY_ENDPOINT 是 Copilot CLI 在创建服务时为您设置的特殊环境变量。其格式为 {env name}.{app name}.local,/api 请求会传递至 http://backend.development.todo.local:10000/。端点 backend.development.todo.local 会解析为私有 IP 地址,并会在您的 VPC 内通过私有路由连接至后端服务。有关服务发现的更多信息,请参阅此处

我们还剩下一项任务,那就是创建 CI/CD 管道以便自动部署前端的任何更新。

4.创建前端的 CI/CD 管道

与后端类似,我们将把前端代码移至其存储库,并再次使用 CodeCommit。请确保您位于包含 automate-container-microservices-aws-copilot 目录的目录中,然后运行以下命令:

mkdir todofrontend
mv automate-container-microservices-aws-copilot/code/frontend/* todofrontend/

todobackend 文件夹现在应包含以下内容:

.
├── Dockerfile
├── backend.conf.template
├── manifests
│ ├── environments
│ │ └── development
│ │ └── manifest.yml
│ └─── frontend
│ └── manifest.yml
├── nginx.conf
└── webapp
 ├── README.md
 ├── package.json
 ├── public
 │ ├── index.html
 │ ├── manifest.json
 │ └── robots.txt
 ├── src
 │ ├── App.css
 │ ├── App.test.tsx
 │ ├── App.tsx
 │ ├── Types.ts
 │ ├── components
 │ │ ├── TableOperation.tsx
 │ │ ├── TaskInput.tsx
 │ │ ├── TaskItem.tsx
 │ │ ├── TaskList.tsx
 │ │ └── util.ts
 │ ├── index.css
 │ ├── index.tsx
 │ ├── modules
 │ │ └── tasksModule.ts
 │ ├── react-app-env.d.ts
 │ ├── reportWebVitals.ts
 │ ├── rootReducer.ts
 │ ├── setupTests.ts
 │ └── store.ts
 └── tsconfig.json

我们现在准备使用以下命令创建新存储库:

cd todofrontend
aws codecommit create-repository --repository-name todofrontend --repository-description "My todoapp frontend repository"
git init
git switch -c main
git remote add origin https://git-codecommit.$(aws configure get region).amazonaws.com/v1/repos/todofrontend

与之前类似,我们用 $(aws configure get region) 来注入 Amazon CLI 设置所使用的区域,让新存储库与基础设施的其余部分相匹配。

我们现在可以通过运行 copilot pipeline init 来生成管道清单。您会看到几个问题,需要您提供以下答案:

  • 您想将此管道命名为?输入 todofrontend-main 并按回车键。
  • 这是什么类型的持续交付管道?选择 Workloads(工作负载)并按回车键。
  • 您想将哪种环境添加到您的管道中?选择 development(开发)并按回车键。
  • 您想将哪种环境添加到您的管道中?选择 No additional environments(无其他环境)并按回车键。只有在您之前使用过 Copilot 并创建过其他环境时才会出现此问题。

您应该会看到以下输出(和之前一样,忽略有关使用哪个分支的错误):

Only one git remote detected. Your pipeline will follow 'https://git-codecommit.us-west-2.amazonaws.com/v1/repos/todofrontend'.
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
Your pipeline will follow branch 'main'.
Pipeline name: todofrontend-main
What type of continuous delivery pipeline is this? Workloads
1st stage: development

✔ Wrote the pipeline manifest for todofrontend at 'copilot/pipelines/todofrontend-main/manifest.yml'
The manifest contains configurations for your pipeline.
Update the file to add stages, change the tracked branch, add test commands or manual approval actions.
✔ Wrote the buildspec for the pipeline's build stage at 'copilot/pipelines/todofrontend-main/buildspec.yml'
The buildspec contains the commands to push your container images, and generate CloudFormation templates.
Update the "build" phase to unit test your services before pushing the images.

Required follow-up actions:
- Commit and push the copilot/ directory to your repository.
- Run `copilot pipeline deploy` to create your pipeline.

接着,运行 copilot pipeline deploy 创建管道。此命令使用作为远程 Git 存储库添加的 CodeCommit 存储库作为 CodePipeline 的源阶段。命令成功后,您应该看到以下输出结果:

Only found one pipeline; defaulting to: todofrontend-main
✔ Successfully added pipeline resources to your application: todo
✔ Successfully created a new pipeline: todofrontend-main

最后,使用以下命令将本地代码推送到 CodeCommit 存储库:

git add -A
git commit -m 'initial commit'
git push origin main
 
注意:一定要推送 Copilot 目录及其所有内容。
 

此时,您可以转到亚马逊云科技账户中的 Amazon CodePipeline 控制台 来查看管道运行。未来对前端应用程序的任何更改都可以在 Git 存储库中进行,并且将更改推送到远程存储库,应该就会通过 CodePipeline 自动部署您的代码。

总结

恭喜您!您刚刚使用 Copilot 部署了两个微服务应用程序!希望您喜欢 Amazon Copilot,它能让部署微服务和用于部署更改的 CI/CD 管道变得十分容易,这些微服务经过了精心设计,并且还应用了亚马逊云科技最佳实践。本教程说明了如何创建两个微服务以及二者如何相互通信,但您可以按照所学内容添加按需添添加更多所需服务。您可以继续使用我们刚刚部署的应用程序,也可以将其删除以避免产生每月的运行成本。

清理资源

要删除本教程中创建的所有资源,请运行以下命令:

  • 在 todofrontend 中运行 copilot app delete 并按 y 和回车键确认。这会删除后端、前端、CI/CD 管道和 development 环境。几分钟后完成后,您应该会看到以下输出结果:
$ copilot app delete
Sure? Yes
✔ Delete stack todo-development-backend
- Update regional resources with stack set "todo-infrastructure" [succeeded] [7.9s]
 - Update resources in region "us-west-2" [update complete] [7.0s]

✔ Deleted service backend from application todo.
✔ Delete stack todo-development-frontend
- Update regional resources with stack set "todo-infrastructure" [succeeded] [6.7s]
 - Update resources in region "us-west-2" [update complete] [3.8s]

✔ Deleted service frontend from application todo.
✔ Retained IAM roles for the "development" environment
✔ Delete environment stack todo-development
✔ Deleted environment "development" from application "todo".
✔ Cleaned up deployment resources.
✔ Deleted pipeline todofrontend-main from application todo.
✔ Deleted pipeline todobackend-main from application todo.
✔ Deleted regional resources for application "todo"
✔ Delete application roles stack todo-infrastructure-roles
✔ Deleted application configuration.
✔ Deleted local .workspace file.
  • 运行以下两条命令来删除所创建的 CodeCommit 存储库:
aws codecommit delete-repository --repository-name todofrontend
aws codecommit delete-repository --repository-name todobackend