写点什么

如何使用 AWS CodePipeline

  • 2019-11-05
  • 本文字数:5372 字

    阅读完需:约 18 分钟

如何使用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.方案架构


流程如下:


  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 端口



选择对应的子网



新建安全组,端口 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


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 界面点击创建管道 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


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 在内的服务。



*默认创建的 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" : { "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 模版源的输出。



点击添加操作。


保存管道更改。

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 技术博客。


原文链接:


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/


2019-11-05 08:001024

评论

发布
暂无评论
发现更多内容

过滤数组中重复元素,你知道最优方案吗?

麦洛

数据结构 数组 数组去重

我敢说 80% 的程序员都掉进了「老鼠赛跑」的陷阱

非著名程序员

读书笔记 程序员 程序人生 提升认知

Disruptor为何这么快

Rayjun

Java Disruptor

dubbo-go 中如何实现路由策略功能

joe

Apache 开源 微服务 dubbo Go 语言

用python爬虫保存美国农业部网站上的水果图片

遇见

Python GitHub 爬虫

有关Kotlin Companion 我们需要了解到的几个知识点

王泰

Java 编程 kotlin 编程语言

写作平台使用感受

小天同学

产品 体验 反馈

最近的一些人生感悟

小智

人生 哲学

【SpringBoot】给你的 CommandLineRunner 排个序

遇见

Java Spring Boot

关于HSTS - 强制浏览器使用HTTPS与服务器创建连接

遇见

https 安全 浏览器 TLS 证书

揭秘|为何程序员们能一直保持高收入?

丁长老

学习 程序员 写作 高薪

软件世界中的个人英雄与团队协作

王泰

团队管理 软件工程 团队协作

回"疫"录(1):口罩危机也许是一种进步

小天同学

疫情 回忆录 现实纪录

死磕Java并发编程(3):volatile关键字不了解的赶紧看看

Seven七哥

Java Java并发 volatile

Facebook在用户增长到5亿时的扩容策略

Rayjun

团队管理 扩容

回"疫"录(2):不知者无畏

小天同学

疫情 回忆录 现实纪录

死磕Java并发编程(6):从源码分析清楚AQS

Seven七哥

Java Java并发 并发编程 AQS

【SpringBoot】为什么我的 CommandLineRunner 不 run ?

遇见

Java Spring Boot

Zoom的加密算法,到底有什么问题?

X.F

算法 编码习惯 产品设计 安全 编程语言

太慢是不行的

池建强

创业 产品

像经营咖啡店一样扩容 Web 系统

Rayjun

Web 扩容

如何画一个闹钟

池建强

视觉笔记

终极 Shell

池建强

Linux Shell

敏捷(组织)转型的6个准备条件

Bob Jiang

团队管理 敏捷 组织转型

程序员陪娃看绘本之启示

孙苏勇

程序员 生活 读书 成长 陪伴

常用手机软件清单

彭宏豪95

效率工具 App 手机 移动应用

个人知识管理精进指南

非著名程序员

学习 读书笔记 知识管理 认知提升

Nginx代理Oracle数据库连接

遇见

MySQL nginx oracle 反向代理

【SpringBoot】为什么我的定时任务不执行?

遇见

Java Spring Boot 定时任务 debug

理性主义和实证主义

王泰

理性主义 实证主义 哲学 软件工程

软件工程的史前时代 -- Therac-25 事件

王泰

质量管理 软件工程 软件危机 软件测试

如何使用AWS CodePipeline_语言 & 开发_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章