亚马逊AWS官方博客
基于 GitLab 与 Amazon CodeBuild 实现持续集成
![]() |
背景
随着 AWS 近期的调整,从 2024 年 7 月 25 日起,CodeCommit 停止了新用户注册,此后也是仅维护现有服务的基本功能,因此 AWS 新用户需要寻求源代码管理的替代方案。作为成熟的源代码托管平台,GitLab 支持创建无限数量的公共和私有代码仓库,并提供直观的 Web 界面用于代码浏览和管理。其完善的分支管理、标签功能以及强大的代码搜索能力,能够全面满足企业的开发需求。与此同时,AWS 发布了一系列的 GitLab 和 CodeBuild、CodePipeline 集成的新功能,可以有效帮助客户在使用 GitLab 作为源代码管理平台的同时,继续实现与 AWS CI/CD 产品的结合,并实现强大完整的 DevOps 解决方案,这些无疑都对 GitLab 作为 CodeCommit 替代方案提供了支持。
在 DevOps 实践中,持续集成(Continuous Integration,CI)扮演着关键角色。AWS CodeBuild 作为一个完全托管的持续集成服务,能够执行源代码编译、测试运行以及软件包生成等任务。通过将 GitLab 与 CodeBuild 相结合,企业可以实现一个自动化的构建和测试环境,不仅能更快地发现和修复缺陷,减少集成问题,还能帮助团队更快速、更可靠地交付高质量的软件产品。
本文将重点探讨如何实现 GitLab(gitlab.com)与 CodeBuild 的集成来打造一个完善的持续集成环境,帮助开发团队提升开发效率和代码质量。本文主要分为两个部分,第一部分介绍 GitLab 与 CodeBuild 的授权连接;第二部分通过实践来介绍 GitLab 与 CodeBuild 实现源代码构建持续集成的两种方式;源代码包括两个 repository,可以分别从 GitLab 的 hello-ci1 和 hello-ci2 这两个链接获取。
前提准备
在开始之前,我们需要做好以下工作:
- GitLab 账号;
- AWS Account;
- 一个至少具有 IAM、CodeConnection、CodeBuild、ECR(Elastic Container Registry)权限的 AWS IAM 用户。
第一部分:创建与 GitLab 的授权连接
AWS CodeConnection 是 AWS 提供的一项服务,可用于建立 AWS 资源和第三方外部代码仓库(包括 GitLab)的连接。用户可以通过使用 CodeConnection 建立的连接结合与 CodeBuild、CodePipeline 的集成来实现代码触发 CI/CD 流水线的功能。下面我们详细介绍建立 GitLab 授权连接的步骤。
登录 AWS Management Console,打开 AWS 开发者工具控制台,网址为 https://console.aws.amazon.com/codesuite/settings/connections。打开后的页面显示如下,点击右上角的“Create connection”,进入到创建 Connection 的页面。
![]() |
在“Select a provider”下,选择 GitLab,并在“Create Gitlab connection”下的连接名称处输入 Connection 的名字,点击右下角的“Connect to GitLab”继续。
![]() |
如果您还没有在浏览器中登入您的 GitLab,此时会显示 Gitlab 的登录页面,如下图所示,选择您所使用的登录方式登录 GitLab.com。
![]() |
在您已经登录过或者完成登录后,会进入“AWS Connect for GitLab”一个授权页面,点击“Authorize AWS Connector for GitLab”来完成授权。
![]() |
完成授权后,浏览器会跳转回 AWS 控制台页面,此时选择“Connect”来继续完成连接的创建。
![]() |
到这一步,我们就完成了 GitLab 与 CodeConnection 的 connection 的建立,如下图所示,该 connection 已处于 Available 的状态,表示 connection 已经创建成功。
![]() |
这个授权连接其实是通过 GitLab 的 Applications 提供的 Oauth 的功能来实现的,而且我们在 GitLab 中 User Settings/Applications 页面下可以看到我们创建的连接。授权链接的取消可以通过我们在 CodeConnection 删除 connection 来实现,而在 GitLab 侧也提供了“Revoke”的方式,以便用户在某些特殊情况下从 GitLab 上取消授权连接。
![]() |
第二部分:GitLab 与 CodeBuild 持续集成实现
方式一:使用 Webhook PUSH event 调用 CodeBuild
AWS Codebuild 支持与 GitLab 的 Webhook event 集成,通过配置相应的 Webhook event 来触发 CodeBuild project 的执行,在该方式中,我们将选择在 main 分支下当 PUSH event 发生时来触发 CodeBuild project 执行来实现持续集成,并将生成的镜像推送到 ECR( Elastic Container Registry)。下面我们以 GitLab 中的 hello-ci1 来详细介绍该方式的实现。
首先,我们需要在 ECR 中准备一个 repository,命名为 hello-ci1, 作为我们的镜像仓库。详细的创建步骤请参考 Creating a private repository 官方文档。
其次,我们来创建 CodeBuild project 执行所需要的 role,命名为 codebuild-hello-ci-service-role。该 role 的主要权限包括 CodeBuild project 来完成镜像到 ECR 的推送。其他的 CodeBuild 需要的权限,我们在随后创建 CodeBuild project 的时候,留给 CodeBuild 来帮我们自动进行管理。 以下是 codebuild-hello-ci-service-role 的 policy 的描述。
接下来,我们来创建 CodeBuild project。进入 CodeBuild 控制台页面后,点击右侧 Create Project 按钮,进入 Create Build Project 页面。在 Project configuration 部分的 Project Name 下,输入 project 名称 hello-ci1。在 source 部分选择 GitLab 作为 Source Provider,在 Credential 部分有两个选择 Default source credential 和 Custom source credential,这主要是为多个 GitLab 账号的集成提供便利。如果我们是第一次进行在 CodeBuild 与 GitLab 的集成,你会看到如下图的提示。
![]() |
如果我们选择设置 Default source credential,那么点击 Manage default source credential 来完成 Default 的设置,如下图所示,在 connection 部分选择所需要指定为默认的 connection 的名字。指定完成后,默认情况下的 GitLab 的账号就是我们 gitlab-ci 中授权的 GitLab 的账号。
![]() |
也可以选择 Custom source credential 来明确在这里指定所要使用的 GitLab 的 connection。我们这里选择 Custom source credential,在 Connection 部分选择 gitlab-ci 的 arn,然后在 Repository 部分选择我们要使用的 repository hello-ci1。Source version 部分我们填写默认分支 main。
![]() |
要实现 GitLab 与 CodeBuild 的自动化集成,我们需要来配置 Webhook,这样当代码在 GitLab 代码仓库有 Webhook 监控的事件发生时,就会触发 CodeBuild project 来进行调用执行,这里为了简便,我们只在 Webhook event filter groups 中只指定了 PUSH 事件,表明当在 main branch 发生 PUSH 事件时,CodeBuild project 会被触发并进行执行。
![]() |
此外,在 Environment 部分,我们还需要进行两个配置,一个是 service role 部分,我们选择在上面创建的 codebuild-hello-ci-service-role 作为该 project 的 role,并勾选 Allow AWS CodeBuild to modify this service role so it can be used with this build project 来让 CodeBuild project 来自行添加它自身所需的一些权限到我们的 Role。
![]() |
因为我们还需要在 CodeBuild 环境中进行 docker 镜像的制作,在 Additional configuration 部分,我们勾选 privileged 来获取相应的权限提升。
在 Buildspec 部分,因为我们在代码中生成了 buildspec.yml,所以在这里我们选择“Use a buildspec file”来指定使用 buildspec.yml 作为 codebuild project 执行命令的文件。
![]() |
Buildspec.yml 文件的内容如下:
其它的配置部分,我们按照默认设置就可以了,点击 Create Project 来完成 CodeBuild project 的创建。
我们回过头来观察下 GitLab 上的变化,此时,我们来到 GitLab 上 hello-ci1 的 Settings>Webhooks页面,会发现在 GitLab 上有一个刚创建出来的 codebuild-webhook。GitLab 对 CodeBuild 的触发就是源自这里的 Webhook。
![]() |
这样,我们就完成了 GitLab 与 CodeBuild 的集成,此时如果我们向 hello-ci1 的 main branch 推送代码,CodeBuild 就会自动执行 project hello-ci1, 最终编译后的镜像被推送到 ECR 的 hello-ci1。
第二种方式:使用 GitLab Runner 与 CodeBuild 来实现持续集成
GitLab 内置了 CI/CD pipeline 的功能,pipeline 的 job 的执行是有 GitLab Runner 来完成的。您可以运行 pipeline 的 job 在 GitLab-hosted runners 上,这会由 GitLab 完全管理,这可能会面临资源不足而导致 job 排队等待执行,也可以在自己管理的实例上安装注册 GitLab Runner,从而运行 CI/CD 的 job 在自己的实例资源上。AWS CodeBuild 提供了作为 GitLab Runner 的能力,我们可以创建并配置 CodeBuild project 来实现这一集成方式。这一方式的集成,可以让我们借助 CodeBuild 来继续使用 GitLab 提供的 CI/CD pipeline 的功能来实现持续集成。
创建 CodeBuild project 的主要步骤和第一种方式的步骤基本一样,主要的不同是在 Webhook 和 Buildspec 部分,下面详细介绍。
同样的,我们首先需要在 ECR 中准备一个 repository,命名为 hello-ci2, 作为我们的镜像仓库。
在 Webhook 配置部分,我们在 CodeBuild project 页面下的 Webhook event filter groups 选择 WORKFLOW_JOB_QUEUED 事件类型,如下图所示,指定 GitLab Pipeline 的 Job event 来触发 Codebuild project。
![]() |
在选择完这一类型后,Buildspec 部分会出现不同于第一种方式的描述。
![]() |
默认情况下,CodeBuild project 运行时可以忽略 buildspec 部分,不执行 buildspec 提供的命令,而是会执行 GitLab CI/CD pipeline 定义的命令,这些命令定义在 helloc-ci2 的.gitlab-ci.yml 文件中,在.gitlab-ci.yml 中通过在 tag 中指定 codebuild-<codebuild-project-name>-$CI_PROJECT_ID-$CI_PIPELINE_IID-$CI_JOB_NAME
来注册 CodeBuild project 作为 job 执行的 GitLab Runner。详细的.gitlab-ci.yml 的内容如下:
为了进行比较,我们在该文件中定义了三个阶段,我们只在第三个阶段定义了 tag: codebuild-hello-ci2-$CI_PROJECT_ID-$CI_PIPELINE_IID-$CI_JOB_NAME,也就是说只有第三个阶段会在我们的 CodeBuild project 中运行。此时,我们如果进行源代码的更改或者执行 pipeline,会完成 GitLab pipeline 的执行,并在 GitLab 的 pipeline 中呈现 job 的执行情况,而最终的镜像也会被推送到 ECR 的 hello-ci2 repository。
![]() |
在这篇博客中,我们介绍了 GitLab 与 CodeBuild 集成的两种方式,实现了基本的持续集成。CodeBuild 还支持其他多种 Webhook event 可以满足不同 GitLab event 事件的集成以及在 GitLab pipeline 方式下的多种灵活配置来完成更复杂的持续集成。在实践过程中,你会发现两者的结合可以实现强大、完善的 DevOps 解决方案。