作者:郭威
1. 前述
通过本文章,您将了解如何通过 AWS CodePipeline,AWS CodeBuild,AWS CloudFormation 来实现基于 Amazon ECS 的持续集成持续部署方案。
开发人员在 GitHub 中提交的新版本代码,会自动触发代码获取,打包镜像,上传镜像仓库,更新新版本容器服务,注册到负载均衡器等操作。
方案中会涉及使用如下组件:
GitHub:示例使用的源,一个提交到 GitHub 上的 PHP 示例网站。AWS CodePipeline 支持 GitHub, AWS CodeCommit 服务,或者 S3 作为源。此次实例使用的 Demo 软件工程可以从以下链接 Fork:
https://github.com/awslabs/ecs-demo-php-simple-app
Docker:作为发布服务使用的容器。演示方案的 Build 阶段会使用 AWS CodeBuild 托管的 ubuntu/docker 1.12.1 基础镜像。
Amazon EC2:作为 ECS 的容器宿主机集群。
Amazon VPC:服务所在的网络。
Amazon ECS:AWS 托管的容器编排服务。文档链接 http://docs.aws.amazon.com/zh_cn/AmazonECS/latest/developerguide/Welcome.html
Amazon ECR:AWS 托管的容器镜像仓库。文档链接 http://docs.aws.amazon.com/zh_cn/AmazonECR/latest/userguide/what-is-ecr.html
AWS CodePipeline:AWS 托管的持续集成持续交付服务,可以快速可靠的更新应用程序和服务,集成支持 GitHub,Jenkins 等主流开源工具。文档链接 http://docs.aws.amazon.com/zh_cn/codepipeline/latest/userguide/welcome.html
AWS CodeBuild:AWS 托管的构建服务,用于打包代码生成可部署的软件包。文档链接 http://docs.aws.amazon.com/zh_cn/codebuild/latest/userguide/welcome.html
AWS CloudFormation:批量创建和管理 AWS 资源的自动化脚本。文档链接 http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/Welcome.html
2.方案架构
流程如下:
开发者将一个新版本的代码工程提交到 GitHub
Pipeline 的 Source 阶段,检测到指定 GitHub 的 repo 有新版本的更新,从 GitHub 上拉取代码工程,开启已设定好的 CICD Pipeline
Pipeline 的 Build 阶段,AWS CodeBuild 将新版本的代码工程打包为 Docker 镜像
AWS CodeBuild 将打包好的镜像推送到 Amazon ECR
Pipeline 的 Deploy 阶段,AWS CodePipeline 触发 AWS CloudFormation,其定义了 Amazon ECS 的 Task definition 和 service
AWS CloudFormation 创建新版本的 Task definition 关联到新版本的 Docker 镜像,并更新 Service
Amazon ECS 从 Amazon ECR 中取到新版本的 Docker 镜像,并运行来替换旧 Task 以完成服务的更新部署
3. 搭建
搭建部分分为以下几个步骤:基础设施,与 CICD Pipeline 的搭建。
3.1 基础设施部分的搭建
这里需要准备好网络,负载均衡器,S3 以及运行 ECS 所需要的宿主机集群。
3.1.1 网络搭建
创建 VPC,子网,Internet Gateway,路由表。将 Internet Gateway Attach 到 VPC 上,路由表配置 0.0.0.0/0 指向 Internet Gateway,并关联子网。
之后的 EC2 宿主机集群,负载均衡器等都使用在这个网络里。
3.1.2 负载均衡器
创建 ALB 应用负载均衡器,监听 80 端口
选择对应的子网
新建安全组,端口 80,并新建目标组
注册目标此时不选择,ECS 创建服务时会注册集群和对应端口进来。
下一步审核后创建。
3.1.3 ECS 宿主机集群
在 ECS 的界面下,创建集群
实例配置保持默认或根据情况自行选择,示例中保持默认。
联网配置,选择创建好的 VPC,子网,创建 Role 允许宿主机上的 ECS 代理调用 ECS 服务的 API。
创建后画面下面会显示集群信息
集群一览会显示
修改 ECS 宿主机集群的安全组,inbound 源设置为建好的应用负载均衡器的安全组 ID
3.1.4 ECR 镜像仓库创建
创建一个用于 Build 阶段上传存放软件工程 Docker 镜像的镜像仓库
ECS 界面下,创建存储库,创建好后如下
3.1.5 S3 桶创建
创建一个 S3 桶用来存放 Deploy 阶段 CloudFormation 使用的脚本模版,创建桶时选择和以上服务同一 Region,并且打开桶的版本控制。
将 CloudFormation 模版压缩 zip 后上传到桶中。
示例中将模版文件 service.yaml 放在 templates 文件夹后压缩为 templates.zip。
service.yaml 如下,注意缩进
Java
到此基础设施部分的搭建工作结束。
3.2 Pipeline 的搭建
分为 Source,Build 以及 Deploy 三阶段:
Source 阶段设置 GitHub 上的软件工程位置,并设置 Deploy 阶段会使用的 CloudFormation 脚本模版来更新 ECS 服务,
Build 阶段使用 AWS CodeBuild 来打包软件工程到 Docker 镜像并上传到 ECR,
Deploy 阶段使用 Source 阶段引入的 CloudFormation 脚本,找到对应的宿主机集群,负载均衡器,以及上传到 ECR 的 Docker 镜像等对象,更新服务。
AWS CodePipeline 创建后的展示图是这样的,串起了整个 CICD 流程
在 AWS CodePipeline 界面点击创建管道 Pipeline,可以看到画面左侧一个基本流程,从源,到生成 Build,到部署 Deploy,到角色等配置。实际应用中用户可以随实际需要,或随着 CICD 流程的由简入繁在创建后编辑加入新的阶段或操作。
点击下一步。
3.2.1 Source 阶段配置
源提供商下拉菜单选择 GitHub,
点击连接到 GitHub 来授权访问权,来允许 AWS CodePipeline 从 GitHub 上获取软件工程源内容,认证后选择 GitHub 上软件工程所在位置和分支
此次实例使用的 Demo 软件工程可以从以下链接 Fork:
https://github.com/awslabs/ecs-demo-php-simple-app
点击下一步。
3.2.2 Build 阶段配置
AWS CodePipeline 在 Build 阶段支持包括 AWS CodeBuild,Jenkins 在内的引擎,此方案选用 AWS 托管的 CodeBuild 服务
选择新建构建项目
选择 AWS CodeBuild 托管的镜像,支持 Ubuntu 系统,运行时支持包括 Java,Python,Go 语言,Node.js,Docker 在内的众多选择,此次方案使用 Docker。
构建规范这里选择使用 buildspec.yml,里面预定了 AWS CodeBuild 在 Build 生命周期中要执行的动作,如 login 到 ECR,打包 Docker 镜像,给 Docker 镜像打 tag,上传 Docker 镜像到已 login 的 ECR 镜像仓库。
Buildspec.yml 放在 GitHub 软件工程源代码目录中,如果复制粘贴的话注意 yaml 文件的缩进
Java
选择 Role
新建一个 Role,这个 Role 允许 AWS CodeBuild 来调用相关的 AWS 服务,此方案中需要调用包括 S3,ECR,CloudWatch 在内的服务。
*默认创建的 Role 不具备对 ECR 的权限,需要在保存构建项目后,到 IAM 找到新创建的 Role,编辑添加对 ECR 的权限否则后面 Pipeline 执行到 Build 时会报错。
保存构建项目。
点击下一步。
3.2.3 Deploy
AWS CodePipeline 部署阶段支持包括 AWS CloudFormation,AWS CodeDeploy,AWS Elastic Beanstalk 在内的服务提供商,此方案选用 AWS CloudFormation 来部署 ECS 容器服务。
这里暂时选择无部署,等 Pipeline 创建好后,编辑引入 Deploy 的 CloudFormation 模版源,再进行配置。
点击下一步。
3.2.4 角色
配置 AWS CodePipeline 对 AWS 服务的调用权限,包括 S3,AWS CodeBuild,AWS CloudFormation,IAM 等。点击创建角色到 IAM 界面选择相对应的策略创建。
创建好后画面回到 Pipeline,IAM 创建好的 Role 已经显示在里面。
点击下一步。
3.2.5 审核后创建管道。
管道创建好后会自动运行,现有的从 GitHub 软件工程源代码抓取工程,打包 Docker 镜像并推送到 ECR 上。界面上显示如图
3.2.6 添加 Deploy 阶段 CloudFormation 需要的模版源以及配置 Deploy 阶段
点击编辑,点击 Source 阶段右上角的画笔图标
可以看到 AWS CodePipeline 的编辑界面在南北纵向和东西横向都可以添加
在 GitHub 这个 Source 右侧,点击添加操作,选择源,操作名称 Template,选择 S3,输入创建好的 S3 桶的地址
画面往下拉,注意在输出项目这里,输入 Template。
Pipeline 中各阶段的传递需要制定南北向的输入输出,即 Source 阶段 S3 源的输出 Template,在 Deploy 阶段用输入 Template 来衔接。
点击更新。
点击 Build 阶段下面的添加阶段,画面右侧选择部署,选择 AWS CloudFormation
操作模式选择创建或更新堆栈,输入创建的堆栈名称,模版这里输入 Template::templates/service.yaml,也就是对应的输入是 S3 源桶中 templates.zip 里的 service.yaml 文件。功能选择 CAPABILITY_NAMED_IAM。
同样需要创建一个 Role,允许 AWS CloudFormation 调用包括 IAM,ECS,ECR 在内的 AWS 服务。
在 IAM 界面创建好后选择 Role。
高级这里点开
在参数覆盖这里输入 CloudFormation 需要传入的参数,其中的固定参数也可以在 S3 的 service.yaml 中直接定义。
Java
Tag 是 Build 阶段传出的 Docker 镜像 Tag 使用的值,传入 CloudFormation 中用于建立 Task Definition 的 Container 时从 ECR 拉取对应版本的 Docker 镜像。
DesiredCount,即想要在 ECS 的 Service 中建立的 Task 的数量。
Cluster,即建立好的宿主机集群的名称。
TargetGroup,即建立好的宿主机集群的应用负载均衡器的 ARN。
Repository,即建立好的 ECR 的镜像仓库名称。
输入项目这里输入 Build 阶段和 S3 模版源的输出。
点击添加操作。
保存管道更改。
4. 运行以及模拟版本更新
4.1 运行
访问负载均衡器的 DNS 地址来确认目前服务已经运行正常。
4.2 模拟版本更新
4.2.1 修改代码
在开发本地更新代码,示例中在 src/index.php 加入一行文字
<h1 style="color:FF7F00;">Amazon ECS Awesome!</h1>
4.2.2 提交新版本后查看 AWS CodePipeline 各阶段触发
4.2.3 刷新服务来确认新修改的部分已经发布
作者简介
郭威,目前在 AWS 负责推广针对初创企业的最佳云计算架构实践。具有 8 年软件设计研发,存储,容器与云计算方案经验。曾任某跨国外企高级研发经理与售前经理,在广电视频行业,金融行业等方面有丰富的云计算经验。后加入某容器创业公司任产品研发与容器云方案工作。现致力于容器服务与 Devops 等方向的学习与研究。
本文转载自 AWS 技术博客。
原文链接:
评论