如何使用 AWS CodePipeline

阅读数:153 2019 年 11 月 5 日 08:00

如何使用AWS CodePipeline

作者:郭威

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. 方案架构

如何使用AWS CodePipeline

流程如下:

  1. 开发者将一个新版本的代码工程提交到 GitHub
  2. Pipeline 的 Source 阶段,检测到指定 GitHub 的 repo 有新版本的更新,从 GitHub 上拉取代码工程,开启已设定好的 CICD Pipeline
  3. Pipeline 的 Build 阶段,AWS CodeBuild 将新版本的代码工程打包为 Docker 镜像
  4. AWS CodeBuild 将打包好的镜像推送到 Amazon ECR
  5. Pipeline 的 Deploy 阶段,AWS CodePipeline 触发 AWS CloudFormation,其定义了 Amazon ECS 的 Task definition 和 service
  6. AWS CloudFormation 创建新版本的 Task definition 关联到新版本的 Docker 镜像,并更新 Service
  7. 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 端口

如何使用AWS CodePipeline

选择对应的子网

如何使用AWS CodePipeline

新建安全组,端口 80,并新建目标组

如何使用AWS CodePipeline

注册目标此时不选择,ECS 创建服务时会注册集群和对应端口进来。

下一步审核后创建。

3.1.3 ECS 宿主机集群

在 ECS 的界面下,创建集群

如何使用AWS CodePipeline

实例配置保持默认或根据情况自行选择,示例中保持默认。

联网配置,选择创建好的 VPC,子网,创建 Role 允许宿主机上的 ECS 代理调用 ECS 服务的 API。

创建后画面下面会显示集群信息

如何使用AWS CodePipeline

集群一览会显示

如何使用AWS CodePipeline

修改 ECS 宿主机集群的安全组,inbound 源设置为建好的应用负载均衡器的安全组 ID

如何使用AWS CodePipeline

3.1.4 ECR 镜像仓库创建

创建一个用于 Build 阶段上传存放软件工程 Docker 镜像的镜像仓库

ECS 界面下,创建存储库,创建好后如下

如何使用AWS CodePipeline

3.1.5 S3 桶创建

创建一个 S3 桶用来存放 Deploy 阶段 CloudFormation 使用的脚本模版,创建桶时选择和以上服务同一 Region,并且打开桶的版本控制。

如何使用AWS CodePipeline

将 CloudFormation 模版压缩 zip 后上传到桶中。

示例中将模版文件 service.yaml 放在 templates 文件夹后压缩为 templates.zip。

service.yaml 如下,注意缩进

Java

复制代码
Parameters:
Tag:
Type: String
Default: latest
DesiredCount:
Type: Number
Default: 0
TargetGroup:
Type: String
Cluster:
Type: String
Repository:
Type: String
Resources:
ECSServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument: |
{
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": [ "ecs.amazonaws.com" ]},
"Action": [ "sts:AssumeRole" ]
}]
}
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource: "*"
Effect: Allow
Action:
- ec2:*
- elasticloadbalancing:*
Service:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref Cluster
Role: !Ref ECSServiceRole
DesiredCount: !Ref DesiredCount
TaskDefinition: !Ref TaskDefinition
LoadBalancers:
- ContainerName: simple-app
ContainerPort: 80
TargetGroupArn: !Ref TargetGroup
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub ${AWS::StackName}-simple-app
ContainerDefinitions:
- Name: simple-app
Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${Repository}:${Tag}
EntryPoint:
- /usr/sbin/apache2
- -D
- FOREGROUND
Essential: true
Memory: 128
MountPoints:
- SourceVolume: my-vol
ContainerPath: /var/www/my-vol
PortMappings:
- ContainerPort: 80
Environment:
- Name: Tag
Value: !Ref Tag
- Name: busybox
Image: busybox
EntryPoint:
- sh
- -c
Essential: false
Memory: 128
VolumesFrom:
- SourceContainer: simple-app
Command:
- /bin/sh -c "while true; do /bin/date > /var/www/my-vol/date; sleep 1; done"
Volumes:
- Name: my-vol

到此基础设施部分的搭建工作结束。

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

在 AWS CodePipeline 界面点击创建管道 Pipeline,可以看到画面左侧一个基本流程,从源,到生成 Build,到部署 Deploy,到角色等配置。实际应用中用户可以随实际需要,或随着 CICD 流程的由简入繁在创建后编辑加入新的阶段或操作。

如何使用AWS CodePipeline

点击下一步。

3.2.1 Source 阶段配置

源提供商下拉菜单选择 GitHub,

点击连接到 GitHub 来授权访问权,来允许 AWS CodePipeline 从 GitHub 上获取软件工程源内容,认证后选择 GitHub 上软件工程所在位置和分支

如何使用AWS CodePipeline

此次实例使用的 Demo 软件工程可以从以下链接 Fork:

https://github.com/awslabs/ecs-demo-php-simple-app

点击下一步。

3.2.2 Build 阶段配置

AWS CodePipeline 在 Build 阶段支持包括 AWS CodeBuild,Jenkins 在内的引擎,此方案选用 AWS 托管的 CodeBuild 服务

如何使用AWS CodePipeline

选择新建构建项目

如何使用AWS CodePipeline

选择 AWS CodeBuild 托管的镜像,支持 Ubuntu 系统,运行时支持包括 Java,Python,Go 语言,Node.js,Docker 在内的众多选择,此次方案使用 Docker。

如何使用AWS CodePipeline

构建规范这里选择使用 buildspec.yml,里面预定了 AWS CodeBuild 在 Build 生命周期中要执行的动作,如 login 到 ECR,打包 Docker 镜像,给 Docker 镜像打 tag,上传 Docker 镜像到已 login 的 ECR 镜像仓库。

如何使用AWS CodePipeline

Buildspec.yml 放在 GitHub 软件工程源代码目录中,如果复制粘贴的话注意 yaml 文件的缩进

Java

复制代码
version: 0.2
phases:
pre_build:
commands:
- $(aws ecr get-login)
- TAG="$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | head -c 8)"
build:
commands:
- docker build --tag " 替换创建好的 ECR 镜像仓库的 URI:${TAG}" .
post_build:
commands:
- docker push " 替换创建好的 ECR 镜像仓库的 URI:${TAG}"
- printf '{"tag":"%s"}' $TAG > build.json
artifacts:
files: build.json

选择 Role

新建一个 Role,这个 Role 允许 AWS CodeBuild 来调用相关的 AWS 服务,此方案中需要调用包括 S3,ECR,CloudWatch 在内的服务。

如何使用AWS CodePipeline

* 默认创建的 Role 不具备对 ECR 的权限,需要在保存构建项目后,到 IAM 找到新创建的 Role,编辑添加对 ECR 的权限否则后面 Pipeline 执行到 Build 时会报错。

保存构建项目。

如何使用AWS CodePipeline

点击下一步。

3.2.3 Deploy

AWS CodePipeline 部署阶段支持包括 AWS CloudFormation,AWS CodeDeploy,AWS Elastic Beanstalk 在内的服务提供商,此方案选用 AWS CloudFormation 来部署 ECS 容器服务。

如何使用AWS CodePipeline

这里暂时选择无部署,等 Pipeline 创建好后,编辑引入 Deploy 的 CloudFormation 模版源,再进行配置。

点击下一步。

3.2.4 角色

配置 AWS CodePipeline 对 AWS 服务的调用权限,包括 S3,AWS CodeBuild,AWS CloudFormation,IAM 等。点击创建角色到 IAM 界面选择相对应的策略创建。

如何使用AWS CodePipeline

创建好后画面回到 Pipeline,IAM 创建好的 Role 已经显示在里面。

如何使用AWS CodePipeline

点击下一步。

3.2.5 审核后创建管道。

管道创建好后会自动运行,现有的从 GitHub 软件工程源代码抓取工程,打包 Docker 镜像并推送到 ECR 上。界面上显示如图

如何使用AWS CodePipeline

3.2.6 添加 Deploy 阶段 CloudFormation 需要的模版源以及配置 Deploy 阶段

点击编辑,点击 Source 阶段右上角的画笔图标

如何使用AWS CodePipeline

可以看到 AWS CodePipeline 的编辑界面在南北纵向和东西横向都可以添加

如何使用AWS CodePipeline

在 GitHub 这个 Source 右侧,点击添加操作,选择源,操作名称 Template,选择 S3,输入创建好的 S3 桶的地址

如何使用AWS CodePipeline

画面往下拉,注意在输出项目这里,输入 Template。

Pipeline 中各阶段的传递需要制定南北向的输入输出,即 Source 阶段 S3 源的输出 Template,在 Deploy 阶段用输入 Template 来衔接。

如何使用AWS CodePipeline

点击更新。

点击 Build 阶段下面的添加阶段,画面右侧选择部署,选择 AWS CloudFormation

如何使用AWS CodePipeline

操作模式选择创建或更新堆栈,输入创建的堆栈名称,模版这里输入 Template::templates/service.yaml,也就是对应的输入是 S3 源桶中 templates.zip 里的 service.yaml 文件。功能选择 CAPABILITY_NAMED_IAM。

如何使用AWS CodePipeline

同样需要创建一个 Role,允许 AWS CloudFormation 调用包括 IAM,ECS,ECR 在内的 AWS 服务。

如何使用AWS CodePipeline

在 IAM 界面创建好后选择 Role。

高级这里点开

如何使用AWS CodePipeline

在参数覆盖这里输入 CloudFormation 需要传入的参数,其中的固定参数也可以在 S3 的 service.yaml 中直接定义。

Java

复制代码
{
"Tag" : { "Fn::GetParam" : [ "MyAppBuild", "build.json", "tag" ] },
"DesiredCount": "2",
"Cluster": "CICD-DEMO-CLUSTER-01",
"TargetGroup": "arn:aws:elasticloadbalancing:us-east-2:305890642658:targetgroup/CICD-DEMO-TG-01/b7649674ee8ab97b",
"Repository": "cicd-demo-ecr-01"
}

Tag 是 Build 阶段传出的 Docker 镜像 Tag 使用的值,传入 CloudFormation 中用于建立 Task Definition 的 Container 时从 ECR 拉取对应版本的 Docker 镜像。

DesiredCount,即想要在 ECS 的 Service 中建立的 Task 的数量。

Cluster,即建立好的宿主机集群的名称。

TargetGroup,即建立好的宿主机集群的应用负载均衡器的 ARN。

Repository,即建立好的 ECR 的镜像仓库名称。

输入项目这里输入 Build 阶段和 S3 模版源的输出。

如何使用AWS CodePipeline

点击添加操作。

保存管道更改。

4. 运行以及模拟版本更新

4.1 运行

访问负载均衡器的 DNS 地址来确认目前服务已经运行正常。

如何使用AWS CodePipeline

4.2 模拟版本更新

4.2.1 修改代码

在开发本地更新代码,示例中在 src/index.php 加入一行文字

<h1 style="color:FF7F00;">Amazon ECS Awesome!</h1>

4.2.2 提交新版本后查看 AWS CodePipeline 各阶段触发

如何使用AWS CodePipeline

4.2.3 刷新服务来确认新修改的部分已经发布

如何使用AWS CodePipeline

作者简介

如何使用AWS CodePipeline

郭威,目前在 AWS 负责推广针对初创企业的最佳云计算架构实践。具有 8 年软件设计研发,存储,容器与云计算方案经验。曾任某跨国外企高级研发经理与售前经理,在广电视频行业,金融行业等方面有丰富的云计算经验。后加入某容器创业公司任产品研发与容器云方案工作。现致力于容器服务与 Devops 等方向的学习与研究。

本文转载自 AWS 技术博客。

原文链接:
https://amazonaws-china.com/cn/blogs/china/how-to-implement-the-continuous-integrated-continuous-deployment-solution-on-amazon-ecs-using-aws-codepipelineaws-codebuild-and-aws-cloudformation/

欲了解 AWS 的更多信息,请访问【AWS 技术专区】

评论

发布