我创建了一组示例文件,以配合下面提供的指南。
这些文件可从以下链接获得:https://gitlab.com/autronix/gitlabci-ec2-deployment-samples-guide/
范围
本指南假定以下内容
- Gitlab EE 托管项目 - 可以在私有 CE/EE 实例上运行(未测试)
- Gitlab 作为 GIT 版本控制存储库
- Gitlab-CI 作为持续集成引擎
- 现有 AWS 账户
- AWS EC2 作为部署的目标生产或暂存系统
- 运行 Amazon Linux AMI 的 AWS EC2 实例
- AWS S3 作为部署文件的存储工具
- AWS CodeDeploy 作为项目的部署引擎
- AWS CodePipeline 作为部署管道
提供的 .gitlab-ci.yml 示例基于 Java/Scala + Gradle 项目。
该脚本作为通用示例提供,在通过此方法实施持续交付时需要根据您的特定需求进行调整。
本指南将假定用户具备 AWS 服务的基本知识以及如何执行必要的任务。
注意:本示例中提供的指南使用 AWS 控制台执行任务。虽然此处执行的任务可能有 CLI 等效项,但本指南不会涵盖这些内容。
动机
创建这些脚本和部署指南的动机来自于缺乏合适的教程来展示如何使用 Gitlab 和 AWS EC2 实施持续交付。
Gitlab 通过与 Digital Ocean 合作推出了免费提供的 CI 引擎,使用户存储库能够免费从优质 CI 中受益。
使用 Gitlab 的主要优势之一是它们提供了内置的持续集成容器,用于运行各个步骤并验证构建。
不幸的是,Gitblab 和 AWS 提供的集成允许在通过构建之后执行持续交付。
本指南和脚本 (https://gitlab.com/autronix/gitlabci-ec2-deployment-samples-guide/) 提供了我为使用 Gitlab 和 AWS EC2 获得成功的 CI 和 CD 所采取的步骤的简化版本,可以帮助其他任何人开始使用这种类型的实施。
在 AWS 上设置环境
确保持续交付过程成功的第一步是在 AWS 上设置必要的对象,以使部署过程成功。
AWS IAM 用户
最初的要求是设置一个 IAM 用户:
https://console.aws.amazon.com/iam/home#users
- 创建用户
-
附加以下权限:
- CodePipelineFullAccess
- AmazonEC2FullAccess
- AmazonS3FullAccess
- AWSCodeDeployFullAccess
-
内联政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:*",
"codedeploy:*",
"ec2:*",
"elasticloadbalancing:*",
"iam:AddRoleToInstanceProfile",
"iam:CreateInstanceProfile",
"iam:CreateRole",
"iam:DeleteInstanceProfile",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:GetInstanceProfile",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListInstanceProfilesForRole",
"iam:ListRolePolicies",
"iam:ListRoles",
"iam:PassRole",
"iam:PutRolePolicy",
"iam:RemoveRoleFromInstanceProfile",
"s3:*"
],
"Resource": "*"
}
]
}
生成安全凭证
注意:上面列出的政策范围非常广泛。您可以通过创建仅限制对某些资源的访问的自定义策略来调整您的要求。
注意:请将这些凭据保存在安全的位置。您将在后面的步骤中需要它们。
AWS EC2 实例和角色
CodeDeploy 的实例角色
https://console.aws.amazon.com/iam/home#roles
创建一个新角色,该角色将分配给您的 EC2 实例以访问 S3,
- 根据您的命名约定设置名称(即
MyDeploymentAppRole)
- 选择
Amazon EC2 以允许 EC2 实例运行其他 AWS 服务
- 附加以下策略:
- AmazonEC2FullAccess
- AmazonS3FullAccess
- AWSCodeDeployRole
注意:上面列出的政策范围非常广泛。您可以通过创建仅限制对某些资源的访问的自定义策略来调整您的要求。
启动实例
https://console.aws.amazon.com/ec2/v2/home
点击Launch Instance并按照以下步骤操作:
- 选择
Amazon Linux AMI 2016.03.3 (HVM), SSD Volume Type
- 选择所需的实例类型(默认为t2.micro)
- 选择
IAM Role为MyDeploymentAppRole(基于上一节创建的名称)
- 选择合适的存储
- 用适当的名称标记您的实例(即
MyApp-Production-Instance)
- 根据需要配置安全组
- 查看并启动您的实例
您将可以生成或使用 SSH 密钥。请选择合适的适用方法。
设置实例环境
安装 CodeDeploy 代理
登录到您新创建的 EC2 实例并按照说明操作:
CodeDeploy 重要路径:
- CodeDeploy 部署基目录:
/opt/codedeploy-agent/deployment-root/
- CodeDeploy 日志文件:
/var/log/aws/codedeploy-agent/codedeploy-agent.log
提示:运行tail -f /var/log/aws/codedeploy-agent/codedeploy-agent.log 以实时跟踪部署。
安装您的项目先决条件
如果您的项目有任何先决条件要运行,请确保在运行部署之前安装这些先决条件,否则您的启动脚本可能会失败。
AWS S3 存储库
https://console.aws.amazon.com/s3/home
在此步骤中,您需要创建一个 S3 存储桶来保存您的部署文件。
只需按照以下步骤操作:
- 选择
Create Bucket
- 选择存储桶名称(即
my-app-codepipeline-deployment)
- 选择地区
- 在您的存储桶的控制台中选择
Properties
- 展开
Versioning 菜单
- 选择
Enable Versioning
AWS CodeDeploy
>
https://console.aws.amazon.com/codedeploy/home#/applications
现在基本元素已经设置好了,我们准备在 CodeDeploy 中创建部署应用程序
要创建 CodeDeploy 部署应用程序,请执行以下步骤:
- 选择
Create New Application
- 选择一个应用程序名称(即
MyApp-Production)
- 选择部署组名称(即
MyApp-Production-Fleet)
- 选择将受此部署影响的 EC2 实例 -
Search by Tags
- 在
Key 下选择Name
- 在
Value 下选择MyApp-Production-Instance
- 在
Service Role 下,选择MyDeploymentAppRole
- 点击
Create Application
注意:您可以将部署分配给任何相关标签,这些标签应用于所需的部署目标实例。为简单起见,仅使用名称标签来选择先前定义的实例。
AWS 代码管道
https://console.aws.amazon.com/codepipeline/home#/dashboard
下一步是继续创建 CodePipeline,它负责执行 S3 存储桶和 CodeDeploy 进程之间的连接。
要创建 CodePipeline,请按以下步骤操作:
- 点击
Create Pipeline
- 为您的管道命名(即
MyAppDeploymentPipeline)
- 将
Source Provider 设置为Amazon S3
- 将
Amazon S3 location设置为您的存储桶和目标部署文件的地址(即s3://my-app-codepipeline-deployment/myapp.zip)
- 下一步
- 将
Build Provider 设置为None - 这已由 Gitlab-CI 处理,稍后将介绍
- 将
Deployment Provider 设置为AWS CodeDeploy
- 将
Application Name 设置为您的CodeDeploy 应用程序的名称(即MyApp-Production)
- 将
Deployment Group 设置为您的CodeDeploy 部署组的名称(即MyApp-Production-Fleet)
- 下一步
- 创建或选择管道服务角色
- 查看并点击
Create Pipeline
在 Gitlab 上搭建环境
现在 AWS 环境已准备好接收应用程序部署,我们可以继续设置 CI 环境和设置,以确保使用 S3、CodeDeploy 和 CodePipeline 构建代码并将其部署到 EC2 实例。
Gitlab 变量
为了使部署工作,我们需要在项目存储库中设置一些环境变量。
在您的 Gitlab 项目中,导航到您的项目的 Variables 区域并设置以下变量:
-
AWS_DEFAULT_REGION => 您的 AWS 区域
-
AWS_SECRET_ACCESS_KEY => 您的 AWS 用户凭证密钥(在您为用户生成凭证时获得)
-
AWS_ACCESS_KEY_ID => 您的 AWS 用户凭证密钥 ID(在您为用户生成凭证时获得)
-
AWS_S3_LOCATION => 部署 zip 文件的位置(即s3://my-app-codepipeline-deployment/my_app.zip)
Gitlab-CI 容器执行的脚本可以访问这些变量。
启动脚本
提供了一个简单的启动脚本 (https://gitlab.com/autronix/gitlabci-ec2-deployment-samples-guide/blob/master/deploy/extras/my_app.sh) 以允许部署执行以下任务:
- 启动应用程序并创建 PID 文件
- 通过PID文件查看应用状态
- 停止应用程序
你可以在deploy/extras/my_app.sh下找到这个脚本
创建 gitlab-ci.yml
gitlab-ci.yml 文件负责执行与给定提交相关的持续集成任务。
它充当一组简化的 shell 脚本,按阶段组织,对应于持续集成步骤中的不同阶段。
更多详情及参考,请参考以下两个链接:
您可以随时使用以下工具验证gitlab-ci.yml 文件的语法:https://gitlab.com/ci/lint
出于部署目的,我们将仅介绍本指南提供的示例的最后一部分:
deploy-job:
# Script to run for deploying application to AWS
script:
- apt-get --quiet install --yes python-pip # AWS CLI requires python-pip, python is installed by default
- pip install -U pip # pip update
- pip install awscli # AWS CLI installation
- $G build -x test -x distTar # # Build the project with Gradle
- $G distZip # creates distribution zip for deployment
- aws s3 cp $BUNDLE_SRC $AWS_S3_LOCATION # Uploads the zipfile to S3 and expects the AWS Code Pipeline/Code Deploy to pick up
# requires previous CI stages to succeed in order to execute
when: on_success
stage: deploy
environment: production
cache:
key: "$CI_BUILD_NAME/$CI_BUILD_REF_NAME"
untracked: true
paths:
- build/
# Applies only to tags matching the regex: ie: v1.0.0-My-App-Release
only:
- /^v\d+\.\d+\.\d+-.*$/
except:
- branches
- triggers
这部分表示与前一个(如果有的话)C.I. 之后的部署相关联的整个作业。阶段。
与部署相关的部分是这样的:
# Script to run for deploying application to AWS
script:
- apt-get --quiet install --yes python-pip # AWS CLI requires python-pip, python is installed by default
- pip install -U pip # pip update
- pip install awscli # AWS CLI installation
- $G build -x test -x distTar # # Build the project with Gradle
- $G distZip # creates distribution zip for deployment
- aws s3 cp $BUNDLE_SRC $AWS_S3_LOCATION # Uploads the zipfile to S3 and expects the AWS Code Pipeline/Code Deploy to pick up
第一步是安装python包管理系统:pip。
pip 是安装 AWS CLI 所必需的,这是将部署文件上传到 AWS S3 所必需的
在本例中,我们使用的是 Gradle(由环境变量 $G 定义); Gradle 提供了一个模块来自动压缩部署文件。根据您要部署的项目类型,此方法会有所不同,用于生成分发 zip 文件 my_app.zip。
aws s3 cp $BUNDLE_SRC $AWS_S3_LOCATION 命令将分发 zip 文件上传到我们之前定义的 Amazon S3 位置。然后,CodePipeline 会自动检测该文件,对其进行处理并发送到 CodeDeploy。
最后,CodeDeploy 通过 appspec.yml 文件指定的 CodeDeploy 代理执行必要的任务。
创建 appspec.yml
appspec.yml 定义了 CodeDeploy 在收到部署文件后要遵循的行为。
随本指南一起提供了一个示例文件,以及在部署的各个阶段要执行的示例脚本。
有关如何构建appspec.yml 文件的更多信息,请参阅 CodeDeploy AppSpec 规范:http://docs.aws.amazon.com/codedeploy/latest/userguide/app-spec-ref.html
生成部署 ZipFile
为了使 CodeDeploy 正常工作,您必须为您的应用程序创建一个正确生成的 zip 文件。
压缩文件必须包含:
- 拉链根
-
appspec.yml => CodeDeploy 部署说明
- 部署阶段脚本
- 提供的样本将放置在 zip 文件中的
scripts 目录中,需要将存在 my_app.sh 脚本添加到应用程序目录的根目录(即 zip 中的 my_app 目录)李>
- 分发代码 - 在我们的示例中,它将位于
my_app 目录下
Gradle 和 Maven 等工具能够生成分发 zip 文件,并对 zip 生成过程进行某些更改。
如果你不使用这样的工具,你可能不得不指示 Gitlab-CI 以不同的方式生成这个 zip 文件;此方法超出了本指南的范围。
将您的应用程序部署到 EC2
本指南的最后一步实际上是执行成功的部署。
持续集成的阶段由gitlab-ci.yml 中设置的规则定义。本指南提供的示例将为与以下正则表达式匹配的任何引用启动部署:/^v\d+\.\d+\.\d+-.*$/。
在这种情况下,通过 git 将标签 v1.0.0-My-App-Alpha-Release 推送到远程 Gitlab 将启动部署过程。您可以根据您的项目要求调整这些规则。
提供的gitlab-ci.yml 示例将在检测标签v1.0.0-My-App-Alpha-Release 时执行以下工作:
- 构建作业 - 编译源代码
- 测试作业 - 运行单元测试
- deploy-job - 编译源代码,生成分发 zip,将 zip 上传到 Amazon S3
分发 zip 上传到 Amazon S3 后,将执行以下步骤:
- CodePipeline 检测到 S3 zip 文件的修订版本发生变化
- CodePipeline 验证文件
- CodePipeline 发送信号表明 CodeDeploy 的捆绑包已准备就绪
- CodeDeploy 执行部署步骤
- 开始 - 部署初始化
- 应用程序停止 - 为挂钩执行定义的脚本
- DownloadBundle - 通过 CodePipeline 从 S3 存储库获取捆绑文件
- BeforeInstall - 为钩子执行定义的脚本
- 安装 - 将内容复制到由
appspec.yml 的files 部分定义的部署位置
- AfterInstall - 为钩子执行定义的脚本
- ApplicationStart - 为钩子执行定义的脚本
- ValidateService - 为钩子执行定义的脚本
- 结束 - 向 CodePipeline 发出部署已成功完成的信号
部署成功截图:
参考文献