亚马逊AWS官方博客
借助 GitHub Actions 将容器应用程序持续交付到 AWS Fargate
11 月 14 日,在 GitHub Universe 2019 大会的第二天主题演讲中,Amazon Web Services 宣布我们已将四个新的 适用于 Amazon ECS 和 ECR 的 GitHub Actions 开源化。 借助这些 GitHub Actions,开发人员和开发运营工程师可以在 GitHub 上的代码存储库中轻松设置持续交付管道,从而将容器工作负载部署到 Amazon Elastic Container Service (Amazon ECS) 和 AWS Fargate.
GitHub 与 Amazon Web Services 合作开发了最初的四个开源 GitHub Actions 以及一个入门工作流,其目的是为了让用户可以简单、安全、快速地部署来自 GitHub 存储库的容器化应用程序。团队、项目和组织不同,其 CI/CD 管道和发布流程也将各异。我们希望 GitHub Marketplace 中的这些开源 Actions 和入门工作流模板,能够成为一个起点,为软件工程师团队提供启发,帮助他们构建自己的组件,并根据他们的容器化应用程序自定义他们的 CI/CD 工作流。
随着客户提出更多的反馈、问题和 pull 请求,我们将继续改进这些开源组件,以更好地满足客户的需求。
在下文中,我们将讨论为何以及如何可以使用容器、ECR、ECS 和 GitHub Actions 来构建 CI/CD 管道,从而部署容器化的持续软件开发工作负载,帮助提高软件开发团队的效率。
为何要使用容器?
作为软件开发者,我们都希望使用尽可能与目标生产系统类似的开发和测试环境。 如果开发环境不能准确反映目标生产环境的配置和规模,在开发人员的笔记本电脑上测试代码时将很难预见按生产规模运行时将会出现的错误,这可能会拖累我们的工作。
Java 的著名设计目标是“一次编写,到处运行”,其实是开发一个统一的代码库,可以不加更改地在从智能手表到大型机在内的任何设备上运行,而非在开发人员的电脑上开发和测试将会在任何目标基础设施中运行的应用程序。它不是为了便携而便携,而是追求规模的便携性:如果我在较小规模的系统中开发和测试应用程序,当我根据真实生产需求扩展和缩减时,它不应出现崩溃。
虚拟机、JVM、SaaS 和容器等创新(在一定程度上)都是为了解决这种规模的便携性挑战而诞生。由于 AWS 等云平台为客户提供了极高的规模弹性,确保规模的便携性对于开发人员而言变得更加重要。
容器是将业务应用程序和相关的库都囊括在一个容器镜像中,这个容器镜像可以根据生产的需要复制到任意数量的实例中。对于应用程序代码而言,每个实例都与在开发人员工作站上开发和测试代码时使用的环境一模一样。规模的便携性降低了代码的脆弱性。
为何要选择 ECR?
大多数的真实应用程序都由若干松散耦合的系统组成,这些系统常被称为服务或微服务,旨在根据生产需求的变化独立扩展(例如,Web 子系统的扩展速率可能需要与消息队列子系统不同)。各种子系统往往是在不同的技术堆栈上独立开发和测试的:Web 子系统可能基于 node.js 堆栈,而消息队列子系统则使用 Java 和 Kafka。在这种情况下,通过不同的容器镜像将它们容器化将更高效、更安全,提供更高性能。容器化后,我们需要扫描漏洞,管理这些容器镜像在容器存储库中的各种版本。在 AWS 中,我们可以使用 Amazon ECR 来作为容器镜像的存储库。
为何选择 Fargate 上的 ECS?
如果您需要通过一个具有多个 EC2 实例的集群来启动、配置、扩展、联网和保护多个容器,那么您将需要使用 Amazon ECS 或 Amazon EKS 等容器编排服务。如果您不想承担集群资源利用率管理等管理开销,只想按您的规格启动、配置、扩展、联网和保护您的容器,那么可以考虑无服务器计算方案:AWS Fargate。
为何要选择持续集成和持续交付?
如何构建将在应用程序的整个持续开发生命周期内部署代码更改的管道? 如何确保各独立开发人员团队每天发布到源代码存储库、形成新镜像的代码更改可以如实启动,不会导致整个应用程序的崩溃? 例如,当某个开发人员在我们的 GithHub 存储库上提出了一个 Pull 请求时,如果能在审查代码前就知道合并此 Pull 请求是否会导致构建崩溃,那将无比完美。
一旦我们确信代码更改将不会导致任何破坏,并且确实会实现需要的改进,我们会想要部署它,无需任何人运行容易出错且枯燥无味的手动命令。
为何选择 GitHub Actions?
如果您的代码存储库位于 GitHub 上,使用 GitHub Actions 将可以非常方便地执行 CI/CD 管道。它提供 Pull(提出 Pull 请求时)和 Push(将提交内容推送到您的存储库)等操作挂钩 (action hook)。这些操作挂钩可以相互连接,从而在出现某个操作 (Action) 时,将会在 GitHub 中运行相应的工作流。一个工作流由多个操作组成。
我们已将 github.com/aws-actions 的下列操作开源化:
- github.com/aws-actions/configure-aws-credentials – 从 GitHub 密钥中检索 AWS 凭证,并使其可供工作流中的剩余操作使用。
- github.com/aws-actions/amazon-ecr-login – 让您可以在 ECR 注册表中记录日志,从而便于您从 ECR 存储库提取镜像以及向这些存储库推送镜像。
- github.com/aws-actions/amazon-ecs-render-task-definition – 将容器镜像的 ID 插入 ECS 的任务定义中。
- github.com/aws-actions/amazon-ecs-deploy-task-definition – 将任务定义和镜像部署到 ECS 服务。
此外我们在 GitHub Marketplace 中还提供了一个入门工作流,您可以根据需要对此工作流进行自定义以及在此基础上构建。
下面我们将逐一介绍这些操作,了解它们的原理!
分步详解
第 1 步:安装和配置 AWS CLI
请遵循设置 AWS CLI 的说明并使用您的身份进行配置。
第 2 步:配置 Amazon ECR
您可以使用与以下类似的命令创建一个 ECR 存储库,其中存储库的名称为 my-ecr-repo
,区域为 us-west-2
:
aws ecr create-repository --repository-name my-ecr-repo --region us-west-2
更多选项请参阅 ECR 入门指南。
第 3 步:创建任务定义文件
为您的项目创建一个目录:
mkdir FargateActionDemo && cd./FargateActionDemo
创建任务定义文件 task-def.json
:下面是一个示例任务定义:
{
"family": "sample-fargate",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "fargate-app",
"image": "httpd:2.4",
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}
],
"essential": true,
"entryPoint": [
"sh",
"-c"
],
"command": [
"/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\""
]
}
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
第 4 步:设置 Fargate 服务
要设置 Fargate 服务,首先需要确保您的 AWS 用户具有需要的权限。您可以使用 Amazon ECS First Run Wizard Permissions 示例 IAM 策略中规定的权限。然后需要确保您的账户中具有一个 ecsTaskExecutionRole
IAM 角色。您按照 Amazon ECS 任务执行 IAM 角色指南的说明来创建该角色。最后需要确保您已经创建了一个 VPC 和安全组。有关更多信息,请参阅教程:为您的集群创建带有公有和私有子网的 VPC。
注册任务定义:
aws ecs register-task-definition --region us-west-2 --cli-input-json file://$HOME/FargateActionDemo/task-def.json
创建 ECS 集群:
aws ecs create-cluster --region us-west-2 --cluster-name default
创建 Fargate 服务:
aws ecs create-service --region us-west-2 --service-name fargate-service
--task-definition sample-fargate:1
--desired-count 2
--launch-type "FARGATE" --network-configuration "awsvpcConfiguration={subnets=[subnet-abcd1234
],securityGroups=[sg-abcd1234
]}"
第 5 步:配置 GitHub 存储库
从浏览器中创建存储库;在此例中,我们将存储库命名为“FargateActionDemo”。
然后提交并将任务定义推送到该存储库中:
git init
git add taskdef.json
git commit -m "first commit"
git remote add origin git@github.com:saptak/FargateActionDemo.git
git push -u origin master
第 6 步:配置密钥
在存储库 Settings 部分的 Secrets 中,使用某个 IAM 用户的凭证(可以从 AWS 控制台获取)配置下面的两个 Secrets:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
第 7 步:添加 GitHub Actions 工作流推送以进行部署
进入存储库的 Actions 选项卡找到入门工作流。
选择 Set up this workflow 以将它添加到存储库。这时此工作流文件将会添加到存储库的 .github/workflows
文件夹。
第 8 步:配置工作流文件
首先将工作流中 aws-region
的值替换为您的存储库所在的区域。在上面的第 2 步中,我们指定 us-west-2
为我们的区域。
aws-region: us-west-2
然后将工作流中 ECR_REPOSITORY
的值替换为您的存储库的名称。在上面的第 2 步中,我们将存储库命名为 my-ecr-repo
。
ECR_REPOSITORY: my-ecr-repo
然后将工作流中 task-definition
的值替换为您的任务定义的文件名。在第 4 步中,我们提交并推送了我们的任务定义文件 task-def.json
。
task-definition: task-def.json
然后将工作流中容器名称的值替换为您在第 4 步任务定义的 containerDefinition
部分指定的容器名称。我们已将容器命名为 fargate-app
。
container-name: fargate-app
将工作流中 service
的值替换为第 4 步中分配的服务名称。
service: fargate-service
最后,将工作流中 cluster
的值替换为第 4 步中分配的集群名称。我们已将集群命名为 default
。
cluster: default
提交所有更改并推送到 GitHub 存储库。
此简单的工作流开始运行后,您可以根据自己的需要编辑工作流文件以进行工作流自定义。
第 9 步:测试部署工作流
要进行测试,请对 task-def.json
文件稍作修改。提交并推送更改。然后切换到存储库的 Actions 选项卡,这时您应会看到此工作流正在运行:
小结
容器是一个十分强大的机制,通过它可以开发能够弹性扩展的应用程序。持续集成和持续交付管道可以在迭代式的容器化应用程序开发生命周期中,将容易出错的容器构建、推送和部署工作自动化。这有利于减少能够避免的因代码更改导致的故障,从而减轻客户和工程师的烦恼。我们很高兴能继续与客户和开源社区携手,在不断成长的容器世界里进一步创新。
欢迎提出问题、提交 Pull 请求并启动我们的 GitHub 存储库,为我们提供反馈。