如何使用 AWS CodeDeploy/CodePipeline/S3 将 Gitlab-Ci 部署到 EC2

Posted

技术标签:

【中文标题】如何使用 AWS CodeDeploy/CodePipeline/S3 将 Gitlab-Ci 部署到 EC2【英文标题】:How to deploy with Gitlab-Ci to EC2 using AWS CodeDeploy/CodePipeline/S3 【发布时间】:2016-12-04 22:31:20 【问题描述】:

我一直在使用 Gradle 在基于 Scala 的 SlackBot 项目上工作,并且一直在寻找利用 Gitlab-CI 部署到 AWS EC2 的方法。

我能够使用 Gitlab-CI 完全构建和测试我的应用程序。

如何使用 CodeDeploy 和 CodePipeline 执行从 Gitlab-CI 到 Amazon EC2 的部署?

回答作为指南来执行此操作。

【问题讨论】:

【参考方案1】:

autronix 的回答很棒,尽管在我的情况下,由于以下错误,我不得不放弃 CodePipeline 部分:The deployment failed because a specified file already exists at this location : /path/to/file。这是因为我在该位置已经有文件,因为我使用的是现有实例,并且已经在其上运行了服务器。

这是我的解决方法:

.gitlab-ci.yml 中,这是我更改的内容:

deploy:
  stage: deploy
  script:
    - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" # Downloading and installing awscli
    - unzip awscliv2.zip
    - ./aws/install
    - aws deploy push --application-name App-Name --s3-location s3://app-deployment/app.zip # Adding revision to s3 bucket
    - aws deploy create-deployment --application-name App-Name --s3-location bucket=app-deployment,key=app.zip,bundleType=zip --deployment-group-name App-Name-Fleet --deployment-config-name CodeDeployDefault.OneAtATime --file-exists-behavior OVERWRITE # Ordering the deployment of the new revision
  when: on_success
  only:
    refs:
      - dev

重要的部分是带有标志--file-exists-behavioraws deploy create-deployment 行。有three options available,OVERWRITE 是我需要的,我无法用 CodePipeline 设置这个标志,所以我选择了 cli 选项。

我还对上传 .zip 的部分进行了一些更改。我没有自己创建 .zip,而是使用 aws deploy push 命令,它将在 s3 存储桶上为我创建一个 .zip。

真的没有什么可以修改的了。

【讨论】:

【参考方案2】:

我创建了一组示例文件,以配合下面提供的指南。 这些文件可从以下链接获得: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 RoleMyDeploymentAppRole(基于上一节创建的名称) 下一步 选择合适的存储 下一步 用适当的名称标记您的实例(即MyApp-Production-Instance) 根据需要添加额外的标签 下一步 根据需要配置安全组 下一步 查看并启动您的实例

您将可以生成或使用 SSH 密钥。请选择合适的适用方法。

设置实例环境

安装 CodeDeploy 代理

登录到您新创建的 EC2 实例并按照说明操作:

http://docs.aws.amazon.com/codedeploy/latest/userguide/how-to-run-agent-install.html

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 TagsKey 下选择NameValue 下选择MyApp-Production-InstanceService Role 下,选择MyDeploymentAppRole 点击Create Application

注意:您可以将部署分配给任何相关标签,这些标签应用于所需的部署目标实例。为简单起见,仅使用名称标签来选择先前定义的实例。

AWS 代码管道

https://console.aws.amazon.com/codepipeline/home#/dashboard

下一步是继续创建 CodePipeline,它负责执行 S3 存储桶和 CodeDeploy 进程之间的连接。

要创建 CodePipeline,请按以下步骤操作:

    点击Create Pipeline 为您的管道命名(即MyAppDeploymentPipeline) 下一步 将Source Provider 设置为Amazon S3Amazon S3 location设置为您的存储桶和目标部署文件的地址(即s3://my-app-codepipeline-deployment/myapp.zip) 下一步 将Build Provider 设置为None - 这已由 Gitlab-CI 处理,稍后将介绍 下一步 将Deployment Provider 设置为AWS CodeDeployApplication 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 脚本,按阶段组织,对应于持续集成步骤中的不同阶段。

更多详情及参考,请参考以下两个链接:

http://docs.gitlab.com/ce/ci/quick_start/README.html http://docs.gitlab.com/ce/ci/yaml/README.html

您可以随时使用以下工具验证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包管理系统:pippip 是安装 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.ymlfiles 部分定义的部署位置 AfterInstall - 为钩子执行定义的脚本 ApplicationStart - 为钩子执行定义的脚本 ValidateService - 为钩子执行定义的脚本 结束 - 向 CodePipeline 发出部署已成功完成的信号

部署成功截图:

参考文献

Gitlab-CI 快速入门:http://docs.gitlab.com/ce/ci/quick_start/README.html Gitlab-CI .gitlab-ci.yml:http://docs.gitlab.com/ce/ci/yaml/README.html AWS CodePipeline 演练:http://docs.aws.amazon.com/codepipeline/latest/userguide/getting-started-w.html 安装或重新安装 AWS CodeDeploy 代理:http://docs.aws.amazon.com/codedeploy/latest/userguide/how-to-run-agent-install.html AWS CLI 入门 - 环境:http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-environment AppSpec 参考:http://docs.aws.amazon.com/codedeploy/latest/userguide/app-spec-ref.html

【讨论】:

很好的答案和详细的演练!

以上是关于如何使用 AWS CodeDeploy/CodePipeline/S3 将 Gitlab-Ci 部署到 EC2的主要内容,如果未能解决你的问题,请参考以下文章

如何在部署期间使用非 AWS 资源扩展 AWS CDK

如何使用从 AWS 兑换的免费积分?

如何使用 AWS java SDK 使用 AWS 粘合作业生成自动脚本

如何在 AWS CLI 中覆盖环境变量并使用 AWS 凭证文件?

如何使用 AWS 身份验证保护我的 wcf 服务

如何使用 AWS Lambda 在 AWS EMR 上运行 PySpark