使用 Amazon CodeCatalyst 在 Amazon ECS 上部署容器 Web 应用程序

学习使用 ECS 和 CodeCatalyst 构建和部署基于容器的 Web 应用程序。
发布时间:2023 年 4 月 24 日
ECS
CDK
CodeCatalyst
CI-CD
教程
亚马逊云科技

Amazon ECS 是一种全托管容器编排服务,可帮助您轻松部署、管理和扩展容器化应用程序。它与亚马逊云科技平台的其余部分集成,通过 Amazon ECS Anywhere,为在云中以及现在在基础设施上运行容器工作负载提供了安全且易于使用的解决方案。

Amazon CodeCatalyst 是一种集成式 DevOps 服务,可利用该服务通过持续集成和持续交付(CI/CD)工具规划、代码协作、构建、测试和部署应用程序。应用程序生命周期的所有这些阶段和方面都包含在一个工具中,因此可以快速而自信地交付软件。

在本指南中,您将学习如何使用 Amazon CodeCatalyst 在 Amazon Elastic Container Service (Amazon ECS) 上部署容器化应用程序。

学习内容

除了了解 Amazon ECS 及其各种组件之外,您还将:

  • 创建使用 Amazon ECS 运行容器的基础设施
  • 使用 Amazon CodeCatalyst 将容器化应用程序部署到 Amazon ECS
Olawale Olaleye
亚马逊云科技使用经验
200 - 中级
完成所需时间
15-20 分钟
所需费用
低于 0.02 美元(如果在一小时内完成)。
前提条件

[*]在过去 24 小时内新创建的账户可能无法使用本教程所需的服务。

示例代码

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

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

前提条件

在开始之前,请了解以下信息:

  • 亚马逊云科技账户(如果您还没有,可以创建一个并在此处设置您的环境)。
  • 已安装 CDK:访问 Amazon CDK 入门指南,了解更多信息。
  • 已下载示例项目代码以提取 SampleApp。
  • Docker 已安装并正在运行。
  • CodeCatalyst 账户和空间设置,并为您分配了空间管理员角色(如果您还没有 CodeCatalyst 设置,可以按照 Amazon CodeCatalyst 设置指南进行设置)。

了解 ECS

本部分的重点是介绍 Amazon ECS 的概念。我们将介绍 Amazon ECS 的各个组件(集群、任务定义、服务)、编排的含义,以及如何选择使用的计算类型来运行容器。如果您已经熟悉 Amazon ECS,可以直接跳到创建基础设施部分。

什么是 Amazon ECS?

Amazon ECS 是一种全托管容器编排服务,可帮助您轻松部署、管理和扩展容器化应用程序。它与亚马逊云科技平台的其余部分集成,通过 Amazon ECS Anywhere,为在云中以及现在在基础设施上运行容器工作负载提供了安全且易于使用的解决方案。编排器管理容器的生命周期:部署容器,确保容器正常运行,替换不正常的节点以及处理新部署。

ECS 包含哪些组件?

Amazon ECS 集群是一个逻辑分组,包含部署到一个集群的所有容器。集群本身不会产生费用,只有用于运行容器的计算和其他基础设施才产生费用。

要启动容器,需要提供任务定义,其中包含容器镜像位置、CPU 和内存量、日志记录配置等属性。仅提供任务定义仍无法启动容器;只是提供了运行容器所需的所有配置。要启动容器,还需要定义服务

在服务中,定义需要的容器副本数量(或者如果需要在每个实例上运行容器,则定义进程守护程序,该进程守护程序需要在每个主机上运行,且 ECS 将处理它的编排)。要将您的服务公开到互联网,需要设置应用程序负载均衡器,以将请求转发到您的服务。最后,Amazon ECS 可以配置为跨多个可用区 (AZ) 部署,同时根据可用的 AZ 数量自动均衡部署,并在负载均衡器中更新每个部署的详细信息,以允许向其路由流量。

下图展示了基础设施的结构:

ECS 基础设施

计算容量规划和选项

Amazon ECS 可以在 EC2 主机(虚拟机)上调度服务运行,也可以使用 Amazon Fargate(一种用于容器的无服务器计算引擎)。运行容器时,需要考虑容量规划。例如,如果您的集群中有两个可用主机,每个主机都有 512MB 的内存,则集群将显示总共 1024MB 的可用内存,但您无法启动需要 512MB 以上内存的新容器,因为没有单个主机有足够的内存。可以通过使用容量提供程序自动扩展集群来缓解这种情况。

或者,也可以使用 Fargate,它允许指定每个容器的 CPU 和内存需求,然后启动所需的计算,为您运行容器。Fargate 和 EC2 主机之间的主要区别在于,使用 Fargate 时,不需要在主机上设置、管理或维护操作系统,也不需要进行容量规划,因为它将启动所需的确切容量。

创建基础设施

在本部分中,您将创建 Amazon CDK 应用程序并在其中部署示例容器,该应用程序将创建设置 Amazon ECS 集群所需的所有基础设施。

创建 CDK 应用程序

首先,确保安装了 CDK。如果尚未安装,请按照 Amazon CDK 入门指南进行操作。

 cdk --version

现在,我们将使用 TypeScript 作为首选语言,创建基础的框架 CDK 应用程序。在终端中运行以下命令:

mkdir cdk-ecs-infra
 cd cdk-ecs-infra
 cdk init app --language typescript

这将输出如下内容:

 Applying project template app for typescript
 # Welcome to your CDK TypeScript project
 
 This is a blank project for CDK development with TypeScript.
 
 The `cdk.json` file tells the CDK Toolkit how to execute your app.
 
 ## Useful commands
 
 * `npm run build` compile typescript to js
 * `npm run watch` watch for changes and compile
 * `npm run test` perform the jest unit tests
 * `cdk deploy` deploy this stack to your default AWS account/region
 * `cdk diff` compare deployed stack with current state
 * `cdk synth` emits the synthesized CloudFormation template
 
 Initializing a new git repository...
 hint: Using 'master' as the name for the initial branch. This default branch name
 hint: is subject to change. To configure the initial branch name to use in all
 hint: of your new repositories, which will suppress this warning, call:
 hint: 
 hint: git config --global init.defaultBranch <name>
 hint: 
 hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
 hint: 'development'. The just-created branch can be renamed via this command:
 hint: 
 hint: git branch -m <name>
 Executing npm install...
 npm WARN deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
 ✅ All done!

为资源堆栈创建代码

转到文件 lib/cdk-ecs-infra-stack.ts。将在该文件中为要创建的资源堆栈编写代码。

资源堆栈是一组云基础设施资源(在您的特定情况下,全都是亚马逊云科技资源),这些资源将预配到特定的账户。在其中预配这些资源的账户/区域可以在堆栈中进行配置(如 Amazon CDK 入门指南中所述)。

在此资源堆栈中,您将创建以下资源:

  • IAM role(IAM 角色):此角色将分配给容器,以便容器能够调用其他亚马逊云科技服务。
  • ECS 任务定义:启动容器时要使用的特定参数。
  • 用于 Fargate 负载均衡服务的 ECS 模式:此模式简化了创建集群、负载均衡器和服务所需的所有组件的复杂度,并将所有组件配置为协同工作。

创建 ECS 集群

在定义任何资源之前,我们都需要导入所需的库。我们将使用 aws-ec2、aws-ecs、aws-ecr 和 aws-cdk-lib/aws-ecs-patterns 库。要添加这些库,请编辑 lib/cdk-ecs-infra-stack.ts 文件,在该文件顶部添加依赖关系:

import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecr from "aws-cdk-lib/aws-ecr";
import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns";

这些部分提供了对部署 Web 应用程序所需的所有组件的访问权限。第一步是添加以下代码,查找您账户中的现有默认 VPC:

// Look up the default VPC
 const vpc = ec2.Vpc.fromLookup(this, "VPC", {
 isDefault: true
 });

接下来,需要定义要使用的容器以及应对其进行配置的方式。可以通过创建任务定义以提供容器端口、所需的 CPU 和内存量以及要使用的容器镜像来实现。在本指南中,我们将使用公开可用的 Nginx 镜像构建 Nginx 容器,并由 CDK 为我们管理容器的构建、上传和部署。我们还将创建 IAM 角色以附加到任务定义并创建 ECR 存储库,供在下一部分部署应用程序中部署示例应用程序时使用。

要创建任务定义和 IAM 角色,请添加以下代码:

const repository = new ecr.Repository(this, 'My-Repository',{
 repositoryName: 'my-respository-cdkecsinfrastack'
 });

 const taskIamRole = new cdk.aws_iam.Role(this, "AppRole", {
 roleName: "AppRole",
 assumedBy: new cdk.aws_iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
 });
 
 taskIamRole.addManagedPolicy(
 cdk.aws_iam.ManagedPolicy.fromAwsManagedPolicyName(
 "service-role/AmazonECSTaskExecutionRolePolicy"
 ));

 const taskDefinition = new ecs.FargateTaskDefinition(this, 'Task', {
 taskRole: taskIamRole,
 family : 'CdkEcsInfraStackTaskDef',
 });

 taskDefinition.addContainer('MyContainer', {
 image: ecs.ContainerImage.fromRegistry('nginx:latest'),
 portMappings: [{ containerPort: 80 }],
 memoryReservationMiB: 256,
 cpu: 256,
 });

在上面的代码中,您会看到通过使用 FargateTaskDefintion 和 ContainerImage.fromRegistry 指定了要部署到 Fargate 的任务定义类型。CDK 将使用 DockerHub 中的 Nginx 容器镜像。

接下来,需要设置 Amazon ECS 集群、定义服务、创建负载均衡器、将其配置为连接到服务,并设置所需的安全组规则。ECS 中的服务用于通过指定所需的副本数量、部署策略和其他配置来启动任务定义。对于本例,我们将仅启动容器的一个副本。安全组充当实例的虚拟防火墙,以控制入站和出站流量,但您不需要对其进行配置,因为将使用的 ECS 模式会自动进行配置。

将以下代码添加到项目中任务定义的下方:

new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyApp", {
 vpc: vpc,
 taskDefinition: taskDefinition,
 desiredCount: 1,
 serviceName: 'MyWebApp',
 assignPublicIp: true,
 publicLoadBalancer: true,
 healthCheckGracePeriod: cdk.Duration.seconds(5),
 }); 

您将传入之前查找的 VPC 对象以指定在何处创建所有资源,以及定义要部署哪个容器镜像的任务定义。desiredCount 指示所需的副本数量,serviceName 指定要调用的服务,publicLoadBalancer 设置为 true,以便可以通过互联网访问。在本例中,将 assignPublicIp 设置为 true 这一行非常重要,因为我们将使用没有私有子网的默认 VPC。虽然最佳实践是推荐在私有子网中启动服务,但这个问题不在本指南的涵盖范围内。

最后,我们需要输出 Web 应用程序的 URL,以及 ECS 集群的 ARN(我们将在稍后设置 CodeCatalyst 工作流以部署更改时使用)。将以下内容添加到 ecs_pattern.ApplicationLoadBalancedFargateService 块的末尾:

// Output the URL of the site
 new cdk.CfnOutput(this, "MyApp URL", {
 value: "http://" + ecs_app.loadBalancer.loadBalancerDnsName
 });
 
 // Output the ARN of the ECS Cluster
 new cdk.CfnOutput(this, "ECS cluster ARN", {
 value: ecs_app.cluster.clusterArn
 });

现在可以部署 Web 应用程序了,但首先需要在要部署的账户上设置 CDK。

编辑 bin/cdk-ecs-infra.ts 文件,取消第 14 行的注释:

env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },

这将使用在 Amazon CLI 中配置的账户 ID 和区域。在使用 CDK 之前,需要先将其引导,这将为 CDK 创建所需的基础设施,以管理您账户中的基础设施。若要引导 CDK,请运行 cdk bootstrap。您应当会看到类似于以下内容的输出:

cdk bootstrap
 
 #output
 ⏳ Bootstrapping environment aws://0123456789012/<region>...
 ✅ Environment aws://0123456789012/<region> bootstrapped

这将为 CDK 创建所需的基础设施,以管理您账户中的基础设施。如果您不熟悉设置 CDK 应用程序,建议您阅读 Amazon CDK 入门指南

引导完成后,将运行 cdk deploy 以部署容器、集群和所需的所有其他基础设施。请注意,要构建容器化应用程序,必须运行 Docker。您应该会看到类似以下内容的输出:

CDK 部署输出

CDK 将在创建基础设施之前显示提示,因为要创建的基础设施会更改安全配置,在本例中,将创建 IAM 角色和安全组。按 y,然后按 Enter 进行部署。CDK 现在将设置您定义的所有基础设施,这需要几分钟才能完成。

运行时,您将看到如下更新:

CDK 部署输出

完成后,您将看到如下输出,其中包含指向公共 URL 的链接,以便访问您的服务:

CDK 部署输出

在所选择的浏览器中打开 MyServiceAppURL 链接以验证 Nginx 部署。

CDK 部署 Nginx

完整示例代码

import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns";
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class CdkEcsInfraStack extends cdk.Stack {
 constructor(scope: Construct, id: string, props?: cdk.StackProps) {
 super(scope, id, props);

 // Look up the default VPC
 const vpc = ec2.Vpc.fromLookup(this, "VPC", {
 isDefault: true
 });

 const repository = new ecr.Repository(this, 'My-Repository',{
 repositoryName: 'my-respository-cdkecsinfrastack'
 });

 const taskIamRole = new cdk.aws_iam.Role(this, "AppRole", {
 roleName: "AppRole",
 assumedBy: new cdk.aws_iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
 });

 taskIamRole.addManagedPolicy(
 cdk.aws_iam.ManagedPolicy.fromAwsManagedPolicyName(
 "service-role/AmazonECSTaskExecutionRolePolicy"
 ));

 const taskDefinition = new ecs.FargateTaskDefinition(this, 'Task', {
 taskRole: taskIamRole,
 family : 'CdkEcsInfraStackTaskDef',
 });

 taskDefinition.addContainer('MyContainer', {
 image: ecs.ContainerImage.fromRegistry('nginx:latest'),
 portMappings: [{ containerPort: 80 }],
 memoryReservationMiB: 256,
 cpu: 256,
 });

 new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyApp", {
 vpc: vpc,
 taskDefinition: taskDefinition,
 desiredCount: 1,
 serviceName: 'MyWebApp',
 assignPublicIp: true,
 publicLoadBalancer: true,
 });

 // Output the URL of the site
 new cdk.CfnOutput(this, "MyApp URL", {
 value: "http://" + ecs_app.loadBalancer.loadBalancerDnsName
 });
 
 // Output the ARN of the ECS Cluster
 new cdk.CfnOutput(this, "ECS cluster ARN", {
 value: ecs_app.cluster.clusterArn
 });
 }
}

此示例 CDK 项目可以在 GitHub 存储库中的 cdk-ecs-infra 目录下获取。

部署应用程序

在本部分中,您将创建一个 Amazon CodeCatalyst 项目、一个代码存储库和一个工作流,以将容器化示例应用程序部署到在创建基础设施部分中创建的 Amazon ECS 集群中。

创建 CodeCatalyst CodeCatalystPreviewDevelopmentAdministrator 角色

您需要 IAM 角色才能创建构建和部署应用程序的工作流。您可以创建一个名为 CodeCatalystPreviewDevelopmentAdministrator 的角色,而无需创建两个角色。CodeCatalystPreviewDevelopmentAdministrator 角色具有广泛的权限,这可能会带来安全风险,因此我们建议您仅在安全问题不那么重要的教程和场景中使用该角色。

您可以通过以下方式创建角色:前往您空间的摘要页面,然后点击 Settings(设置)选项卡并转到 Amazon Account(亚马逊云科技账户)页面。打开 Manage roles from Amazon Management Console(从亚马逊云科技管理控制台管理角色)页面,然后创建 CodeCatalystPreviewDevelopmentAdministrator 角色。

CodeCatalyst 控制台,其中显示了点击为 CodeCatalyst 添加 IAM 角色的位置

在 Add IAM Role(添加 IAM 角色)页面中,点击创建新的 CodeCatalystPreviewDevelopmentAdministrator 角色。

IAM 控制台,详细说明了如何创建 CodeCatalyst IAM 角色

该角色将采用以下形式创建:codeCatalystPreviewDevelopmentAdministrator,并附加一个唯一标识符。

创建 CodeCatalyst 项目

要创建 CodeCatalyst 项目,您需要先配置 CodeCatalyst 账户和空间。如果您还没有配置 CodeCatalyst,可以按照 Amazon CodeCatalyst 设置指南进行操作。

下面我们在 CodeCatalyst 空间中创建一个项目。在 Create Project(创建项目)页面中,点击 Start from Scratch(从头开始)并提供有效的名称,以创建项目。

创建 CodeCatalyst 项目

创建 CodeCatalyst 存储库

可以创建新的存储库,也可以链接现有的 GitHub 存储库。在本教程中,我们将创建一个源存储库。您可以通过前往在上一步中创建的项目,在项目中创建一个存储库 SampleApp。

创建 CodeCatalyst 存储库

创建 CodeCatalyst 开发环境

现在我们将创建一个开发环境,以帮助我们将示例应用程序添加到存储库中。可以从列表中选择一个首选 IDE。对于本教程,我们建议使用 Amazon Cloud9 或 Visual Studio Code。

创建 CodeCatalyst 开发环境

使用以下值创建开发环境:

创建一个使用主分支克隆 SampleApp 存储库的开发环境。

下一步是从 GitHub 将示例应用程序下载到本地计算机,并将其添加到开发环境中。我们将以 zip 文件的形式下载项目,解压缩,然后使用以下命令将其移至我们的项目文件夹中(目录名中的 adb68cd 部分可能与您的不一样,请确认值,并根据需要替换):

wget -O SampleApp.zip https://github.com/build-on-aws/automate-web-app-amazon-ecs-cdk-codecatalyst/zipball/main/
unzip SampleApp.zip
mv build-on-aws-automate-web-app-amazon-ecs-cdk-codecatalyst-adb68cd/SampleApp/* SampleApp/
rm -rf build-on-aws-automate-web-app-amazon-ecs-cdk-codecatalyst-adb68cd
rm SampleApp.zip

接下来,我们需要更新应用程序的任务定义文件。打开 SampleApp 文件夹中的 task.json,并将 <account ID> 替换为您的账户 ID。

{
 "executionRoleArn": "arn:aws:iam::<account ID>:role/AppRole",
 "containerDefinitions": [
 {
 "name": "MyContainer",
 "image": "$REPOSITORY_URI:$IMAGE_TAG",
 "essential": true,
 "portMappings": [
 {
 "hostPort": 80,
 "protocol": "tcp",
 "containerPort": 80
 }
 ]
 }
 ],
 "requiresCompatibilities": [
 "FARGATE"
 ],
 "networkMode": "awsvpc",
 "cpu": "256",
 "memory": "512",
 "family": "CdkEcsInfraStackTaskDef"
}

您的示例应用程序现在可以上传到 CodeCatalyst 存储库了,您可以将更改提交到存储库。在 SampleApp 目录中,运行以下命令:

git add .
git commit -m "Adding sample app"
git push

创建 CodeCatalyst CI/CD 环境

在这一步中,我们将创建 CI/CD 环境(使用非生产环境),以用于执行工作流。您可以通过以下方式创建 CI/CD 环境:前往项目的 CI/CD 部分,选择 Environments(环境),然后点击 Create Environment(创建环境)按钮。您需要选择一个亚马逊云科技账户关联,才能在选定的亚马逊云科技账户上执行工作流。

创建环境

创建 CodeCatalyst 工作流

接下来,我们将创建一个工作流,将示例应用程序构建到 Docker 镜像中,并将其部署到 ECS 集群。工作流是一种自动过程,用于描述在持续集成和持续交付 (CI/CD) 系统中如何构建、测试和部署代码。使用工作流,可以定义启动工作流的事件或触发器,以及在工作流运行期间要执行的操作。

要设置工作流,可以使用 CodeCatalyst 控制台的可视化编辑器或 YAML 编辑器创建工作流定义文件。下面,我们为 SampleApp 存储库创建一个空的工作流定义:前往项目的 CI/CD 部分,选择 CI/CD 部分中的 Workflows(工作流),然后点击 Create workflow(创建工作流)按钮。

创建 CodeCatalyst 工作流

默认工作流中的触发器会触发将任何内容推送到 main 分支,具有以下内容:

Name: Workflow_752b
SchemaVersion: "1.0"

# Optional - Set automatic triggers.
Triggers:
 - Type: Push
 Branches:
 - main

# Required - Define action configurations.
Actions:

添加构建操作

首先,我们将工作流重命名为 BuildAndDeployToECS,只需将第一行更改为 Name: BuildAndDeployToECS即可。您可以使用 yaml 编辑器或可视化编辑器配置工作流。下面我们定义需要创建的步骤,然后使用 yml 编辑器进行添加。我们需要创建以下步骤:

  1. 在工作流中使用构建操作构建应用程序以生成 Docker 镜像,并定义一组输入变量。
    1. region(区域)用于配置希望在其中部署应用程序的亚马逊云科技区域。提供在其中预配 ECS 集群基础设施的同一区域。
    2. registry 用于配置 Docker ECR 端点,以在后面的构建步骤中使用。
    3. image 是您的 ECR 存储库的名称,在 CDK 项目中创建,如果使用的是提供的默认值,则应该为 my-respository-cdkecsinfrastack。
  2. 为 Docker 镜像设置标签
  3. 将设置了标签的 Docker 镜像推送到我们的 ECR 存储库。
  4. 导出我们刚刚创建的镜像的 ECR URl,将其传递到部署步骤
  5. 将容器镜像部署到 ECS 集群。

将以下内容添加到工作流,将<Account-Id> 替换为您的账户 ID,并替换 <CodeCatalystPreviewDevelopmentAdministrator role>(如果使用的是默认值,则应为 CodeCatalystWorkflowDevelopmentRole-AWS):

Actions:
 Build_application:
 Identifier: aws/build@v1
 Inputs:
 Sources:
 - WorkflowSource
 Variables:
 - Name: region
 Value: us-west-2
 - Name: registry
 Value: <Account-Id>.dkr.ecr.us-west-2.amazonaws.com
 - Name: image
 Value: my-respository-cdkecsinfrastack
 Outputs:
 AutoDiscoverReports:
 Enabled: false
 Variables:
 - IMAGE
 Compute:
 Type: EC2
 Environment:
 Connections:
 - Role: <CodeCatalystPreviewDevelopmentAdministrator role>
 # Add account id within quotes. Eg: "123456789012"
 Name: "<Account-Id>"
 Name: Non-prod
 Configuration:
 Steps:
 - Run: export account=`aws sts get-caller-identity --output text | awk '{ print $1 }'`
 - Run: aws ecr get-login-password --region ${region} | docker login --username AWS --password-stdin ${registry}
 - Run: docker build -t appimage .
 - Run: docker tag appimage ${registry}/${image}:${WorkflowSource.CommitId}
 - Run: docker push --all-tags ${registry}/${image}
 - Run: export IMAGE=${registry}/${image}:${WorkflowSource.CommitId}

要确认所有配置都正确无误,请点击 Validate 按钮,该按钮的上方应增加了一个绿色横幅 The workflow definition is valid.。可以通过点击页面底部的 Warnings: 1,查看任何错误的详细信息,1 表示检测到的错误数量。现在,还可以点击 Visual 按钮,使用可视化编辑器检查工作流。

添加呈现 Amazon ECS 任务定义操作

现在,我们需要添加将容器镜像部署到 ECS 集群的最后步骤。我们将使用呈现 Amazon ECS 任务定义操作,将我们之前创建的 ECS 任务定义文件 (task.json) 中的镜像字段更新为在构建操作中作为 IMAGE 输出导出的 Docker 镜像 URI。每次更改示例应用程序的源代码时,该值就会发生更改,因此我们需要在工作流中添加一个步骤,来处理对 task.json 的更新。

要添加呈现 Amazon ECS 任务定义操作,并将 image 字段配置为在构建操作中导出的 Docker 镜像 URI,请将 container-name 字段配置为在 CDK 项目中创建的容器名称,将 task-definition 字段配置为 task.json(即 SampleApp 存储库中的 task.json 文件)。此任务将在运行时输出更新的任务定义文件。

下面的代码段展示了要添加到工作流的呈现 Amazon ECS 任务定义操作配置,确保保持以下缩进格式,RenderAmazonECStaskdefinition 行应在开头缩进 2 个空格

RenderAmazonECStaskdefinition:
 Identifier: aws/ecs-render-task-definition@v1
 Configuration:
 image: ${Build_application.IMAGE}
 container-name: MyContainer
 task-definition: task.json
 Outputs:
 Artifacts:
 - Name: TaskDefinition
 Files:
 - task-definition*
 DependsOn:
 - Build_application
 Inputs:
 Sources:
 - WorkflowSource

添加部署到 Amazon ECS 操作

这是工作流的最后一步,即添加部署到 Amazon ECS 操作。此操作将注册在呈现 Amazon ECS任务定义操作中创建的任务定义文件。注册后,任务定义将由在 Amazon ECS 集群中运行的 Amazon ECS 服务实例化。将任务定义实例化为服务相当于将应用程序部署到 Amazon ECS。

将在呈现 Amazon ECS任务定义操作中创建的任务定义文件设置为该操作的输入构件。在该操作的配置部分中,将 task-definition 配置为输入构件文件路径,将 cluster 配置为在 CDK 项目中创建的 ECS 集群 ARN。可以从 Amazon Console - Amazon Elastic Container Service - Clusters(亚马逊云科技控制台 - Amazon ECS 控制台 - 集群)找到 ECS 集群 ARN。将 <ECS cluster ARN> 替换为您的 ECS 集群 ARN,这是运行 cdk deploy 后输出的一部分,应类似于 arn:aws:ecs:us-west-2:<account Id>:CdkEcsInfraStack-EcsDefaultClusterMnL3mNNYNVPC9C1EC7A3-UdnuAwVtK2q2。将 service 配置为 ECS 服务的名称,即我们在 CDK 项目中定义的名称。或者,也可以从 Amazon Console - Amazon Elastic Container Service - Clusters(亚马逊云科技控制台 - Amazon ECS 控制台 - 集群)找到 ECS 服务名称。region(区域)用于配置希望在其中部署应用程序的亚马逊云科技区域。提供在其中预配 ECS 集群基础设施的同一区域。在 Environment(环境)下提供环境连接和 CI/CD 环境信息。

要使此操作正常运行,请确保 ECS 集群和 ECS 服务名称与您已经在亚马逊云科技环境中配置的基础设施相匹配。

下面的代码段展示了部署到 Amazon ECS 操作配置,与之前一样,请注意 DeploytoAmazonECS 开头需要缩进 2 个空格:

DeploytoAmazonECS:
 Identifier: aws/ecs-deploy@v1
 Configuration:
 task-definition: /artifacts/DeploytoAmazonECS/TaskDefinition/${RenderAmazonECStaskdefinition.task-definition}
 service: MyWebApp
 cluster: <ECS cluster ARN>
 region: us-west-2
 Compute:
 Type: EC2
 Fleet: Linux.x86-64.Large
 Environment:
 Connections:
 - Role: <CodeCatalystPreviewDevelopmentAdministrator role>
 # Add account id within quotes. Eg: "12345678"
 Name: "<Account Id>"
 Name: Non-Prod
 DependsOn:
 - RenderAmazonECStaskdefinition
 Inputs:
 Artifacts:
 - TaskDefinition
 Sources:
 - WorkflowSource

触发工作流

现在您已经实现了构建和部署工作流自动化。工作流应如下所示(将 <account ID>、<CodeCatalystPreviewDevelopmentAdministrator role> 和 <ECS cluster ARN> 值替换为适当的值):

Name: BuildAndDeployToECS
SchemaVersion: "1.0"

# Optional - Set automatic triggers.
Triggers:
 - Type: Push
 Branches:
 - main

# Required - Define action configurations.
Actions:
 Build_application:
 Identifier: aws/build@v1
 Inputs:
 Sources:
 - WorkflowSource
 Variables:
 - Name: region
 Value: us-west-2
 - Name: registry
 Value: <Account-Id>.dkr.ecr.us-west-2.amazonaws.com
 - Name: image
 Value: my-respository-cdkecsinfrastack
 Outputs:
 AutoDiscoverReports:
 Enabled: false
 Variables:
 - IMAGE
 Compute:
 Type: EC2
 Environment:
 Connections:
 - Role: <CodeCatalystPreviewDevelopmentAdministrator role>
 # Add account id within quotes. Eg: "123456789012"
 Name: "<Account-Id>"
 Name: Non-prod
 Configuration:
 Steps:
 - Run: export account=`aws sts get-caller-identity --output text | awk '{ print $1 }'`
 - Run: aws ecr get-login-password --region ${region} | docker login --username AWS --password-stdin ${registry}
 - Run: docker build -t appimage .
 - Run: docker tag appimage ${registry}/${image}:${WorkflowSource.CommitId}
 - Run: docker push --all-tags ${registry}/${image}
 - Run: export IMAGE=${registry}/${image}:${WorkflowSource.CommitId}
 RenderAmazonECStaskdefinition:
 Identifier: aws/ecs-render-task-definition@v1
 Configuration:
 image: ${Build_application.IMAGE}
 container-name: MyContainer
 task-definition: task.json
 Outputs:
 Artifacts:
 - Name: TaskDefinition
 Files:
 - task-definition*
 DependsOn:
 - Build_application
 Inputs:
 Sources:
 - WorkflowSource
 DeploytoAmazonECS:
 Identifier: aws/ecs-deploy@v1
 Configuration:
 task-definition: /artifacts/DeploytoAmazonECS/TaskDefinition/${RenderAmazonECStaskdefinition.task-definition}
 service: MyWebApp
 cluster: <ECS cluster ARN>
 region: us-west-2
 Compute:
 Type: EC2
 Fleet: Linux.x86-64.Large
 Environment:
 Connections:
 - Role: <CodeCatalystPreviewDevelopmentAdministrator role>
 # Add account id within quotes. Eg: "12345678"
 Name: "<Account Id>"
 Name: Non-Prod
 DependsOn:
 - RenderAmazonECStaskdefinition
 Inputs:
 Artifacts:
 - TaskDefinition
 Sources:
 - WorkflowSource

使用 Commit 按钮将工作流添加到存储库,将以 BuildAndDeployToECS.yaml 形式添加到 .codecatalyst/workflows 目录下。提交后,工作流应该就会自动开始运行。可以点击 Recent runs 下的 Run-xxxxx 链接,查看执行情况。完成后,应显示一个绿色打勾标记,表示各个步骤成功执行:

CodeCatalyst 工作流

SampleApp Web 应用程序已成功部署到 ECS 集群。您可以通过刷新浏览器进行验证,之前浏览器显示的是 Nginx 欢迎页面。

ECS 示例应用程序在浏览器中运行

清理资源

恭喜您!通过使用 CDK 设置基础设施,并创建 CI/CD 管道来使用 CodeCatalyst 构建和部署,您已经将容器化应用程序部署到 ECS。如果您不打算进一步使用此设置,我们建议将其删除以节省成本。在本指南的最后一部分中,您将学习如何删除在本指南中创建的所有不同亚马逊云科技资源。

清理亚马逊云科技环境

现在,您已经完成了本指南,但仍需要清理在此期间创建的资源。如果您的账户仍享有免费套餐,每月的运行费用约为 9.00 美元,或每小时 1.2 美分。要删除您创建的所有基础设施,请使用 cdk destroy 命令,只会删除在本指南中创建的基础设施。

cdk destroy

您应该会收到以下提示。依次按 y 和 enter 后,将开始删除所有基础设施并提供更新。完成后,您将看到以下内容:

Are you sure you want to delete: CdkEcsInfraStack (y/n)? y
CdkEcsInfraStack: destroying...

 ✅ CdkEcsInfraStack: destroyed

在 CDK 项目中创建的 ECR 存储库需要在亚马逊云科技控制台中手动删除,因为 CDK 默认不会删除任何存储数据的资源。

ECR 存储库清理

清理 CodeCatalyst 环境

清理在本教程中创建的资源,以释放 CodeCatalyst 空间中的存储。

手动从 CodeCatalyst 空间中删除以下资源:

  1. 删除 CodeCatalyst 开发环境
  2. 删除 CodeCatalyst 源存储库
  3. 删除 CodeCatalyst 项目

总结

恭喜您!您已经学会了如何使用 CDK 和 CodeCatalyst 将 Web 应用程序部署到 ECS 集群。如果您喜欢本教程,发现了任何问题,或有任何意见反馈,请随时发给我们!

有关更多 DevOps 相关内容,请查看 Amazon 在现实生活中如何进行 DevOps,或其他 DevOps 文章。