引言

Gitlab 是一个开放源码工具,供软件团队用于管理其整个开发和交付周期。 提供了一系列广泛的功能: 问题跟踪、 git 存储库、持续集成、容器注册、部署和监控。 这些特性都是作为单个应用程序从头开始构建的。 你可以在自己的服务器上托管 GitLab,或者使用 GitLab. com,这是一个云服务,开源项目可以免费获得所有顶级功能。

Gitlab 的持续集成 / 持续交付(ci / cd)功能是一种有效的方法,可以在部署之前培养测试所有代码的习惯。 Gitlab ci / cd 还具有高度可伸缩性,这要归功于另外一个工具 GitLab Runner,它能够自动扩展构建队列,以避免开发团队试图发布代码时的长等待时间。

在本指南中,我们将演示如何配置一个高度可扩展的 GitLab 基础设施,该基础设施管理自身的成本,并通过增加和减少可用的服务器容量自动响应负载。

目标

我们将在 DigitalOcean 上构建一个可伸缩的 ci / cd 进程,该进程通过在平台上创建新服务器来自动响应需求,并在队列空闲时销毁这些服务器。

这些可重复使用的服务器由 GitLab Runner 进程产生,并在没有任务运行时自动删除,从而降低了团队的成本和管理开销。

正如我们将在本教程中解释的那样,您可以控制在任何给定的时间内创建多少台计算机,以及它们在被销毁之前保留的时间长度。

我们将使用三个独立的服务器来构建这个项目,所以让我们首先回顾一下术语:

  • Gitlab: 您托管的 GitLab 实例或存储代码库的自托管实例。
  • Bastion: Bastion 服务器或者是熔滴是我们将要配置的核心。 它是控制实例,用于与 DigitalOcean API 进行交互,以创建液滴并在必要时摧毁它们。 此服务器上不执行任何作业。
  • Gitlab Runners: 当需要在构建队列中执行 ci / cd 作业时,您的 Runners 是由 bastion 服务器动态创建的临时服务器或飞沫。 这些服务器是一次性的,并且是在将构建标记为传递或失败之前执行或测试代码的地方。

通过利用 GitLab 的每个组件,ci / cd 流程将使您能够根据需求进行响应扩展。 考虑到这些目标,我们准备开始与 GitLab 和 DigitalOcean 建立我们的持续部署。

先决条件

本教程假设您已经在您自己的服务器上或通过托管服务配置了 GitLab,并且您已经拥有一个 DigitalOcean 帐户。

你可以使用 DigitalOcean 一键式图片,或者按照我们的指南: “如何在 Ubuntu 16.04上安装和配置 GitLab。”

对于本教程的目的,我们假设您在这个液滴上启用了私人网络,您可以通过遵循我们的指南“如何在现有液滴上启用数字笔记本私人网络”来实现,但它不是强制性的。

在整个教程中,我们将使用对我们的飞溅具有管理员权限的非根用户。

步骤1ー导入 JavaScript 项目

首先,我们将在现有的 GitLab 实例中创建一个新的示例项目,其中包含一个示例 Node.js 应用程序。

登录到 GitLab 实例,点击加号图标,然后从下拉菜单中选择 New project。

在新的项目屏幕上,选择 Import project 标签,然后单击 Repo by URL,直接从 GitHub 导入我们的示例项目。

将下面的克隆 URL 粘贴到 Git 存储库 URL:

https://github.com/do-community/hello_hapi.git

这个存储库是一个用于演示的基本 JavaScript 应用程序,我们不会在生产环境中运行它。 要完成导入,请单击“新建项目”按钮。

您的新项目现在将在 GitLab,我们可以开始建立我们的 CI 管道。

第二步ー建立基础设施

我们的 GitLab 代码运行器需要特定的配置,因为我们计划通过编程创建液滴来处理增长和收缩的 CI 负载。

在本教程中,我们将创建两种类型的机器: 一种是 bastion 实例,它控制并生成新的机器; 另一种是我们的 runner 实例,它是 bastion 熔滴产生的临时服务器,在需要时构建代码。 Bastion 实例使用 Docker 创建您的参赛者。

下面是我们将要使用的 DigitalOcean 产品,以及每个组件的用途:

  • 柔性液滴ー我们将为 GitLab 跑步者创建内存优化液滴,因为这是一个内存密集型的过程,将使用 Docker 运行一个集装箱化。 你可以在未来根据需要缩小或增大这个液滴,但是我们推荐柔性液滴选项作为一个起点,以了解你的管道在负载下将如何运作。
  • Digitalocean Spaces (对象存储)ー我们将使用 DigitalOcean Spaces 来持久存储缓存的构建组件,当它们被创建和销毁时。 这就减少了在 CI 管道繁忙时建立一个新的跑步者所需的时间,并允许新的跑步者立即从其他人离开的地方接手。
  • 专用网络ーー我们将为您的 bastion spill 和 GitLab 参赛者创建一个专用网络,以确保安全的代码编译和减少所需的防火墙配置。

首先,我们将创建 bastion 雾滴。 创建一个新的液滴,然后在“选择一张图片”下面,选择“单击应用程序”选项卡。 从那里,选择 Docker 17.12.0-ce 的16.04(注意,这个版本是目前的写作时) ,然后选择最小的液滴大小可用,因为我们的堡垒液滴将管理其他液滴的创建,而不是实际执行测试。

建议您在包含 DigitalOcean Spaces 的数据中心创建服务器,以便使用前面提到的对象存储缓存特性。

选择“专用网络和监视”选项,然后单击“创建液滴”。

我们还需要设置用于缓存的存储空间。 按照“ How To Create a DigitalOcean Space and API Key”中的步骤,在与您托管的 GitLab 实例相同或最近的数据中心中创建一个新的 Space,以及一个 API Key。

注意这个关键字,因为我们将在后面的教程中需要它。

现在是时候让我们的线人开始了!

第三步ー配置 GitLab Runner Bastion 服务器

准备好新鲜的液滴后,我们现在可以配置 GitLab Runner 了,我们将从 GitLab 和 GitHub 库中安装脚本。

作为最佳实践,请确保在运行下面的完整命令之前检查脚本以确认您将要安装的内容。

使用 SSH 连接到熔滴,进入 / tmp 目录,然后将 GitLab Runner 的官方库添加到 Ubuntu 的包管理器:

  • cd /tmp
  • curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash

一旦添加,安装 GitLab Runner 应用程序:

  • sudo apt-get install gitlab-runner

我们还需要安装 Docker Machine,这是一个附加的 Docker 工具,可以帮助在云提供商上自动部署容器:

  • curl -L https://github.com/docker/machine/releases/download/v0.14.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && \
  • sudo install /tmp/docker-machine /usr/local/bin/docker-machine

安装完成后,我们就可以连接 GitLab Runner 和 GitLab 安装了。

第四步ー取得参赛者注册令牌

要链接 GitLab Runner 到你现有的 GitLab 安装,我们需要通过获得一个令牌来验证你的 Runner 到你的代码仓库的身份,将两个实例链接在一起。

以管理员用户身份登录到现有的 GitLab 实例,然后单击扳手图标进入管理员设置区域。

在屏幕左侧,将鼠标悬停在 Overview 上,然后从出现的列表中选择选手。

在 Runners 页面的 How to setup a shared Runner for a new project section,复制步骤3中显示的令牌,并将其与第2步 GitLab 实例的公开可访问 URL 一起记录下来。 如果您正在 Gitlab 中使用 HTTPS,请确保它不是一个自签名证书,否则 Gitlab Runner 将无法启动。

步骤5ー在 Bastion 雾滴上配置 GitLab

回到你的 SSH 连接中,运行下面的命令:

  • sudo gitlab-runner register

这将启动链接过程,并向您提出一系列问题。

在下一步,输入前一步的 GitLab 实例 URL:

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com)
https://example.digitalocean.com

输入从 GitLab 实例中获得的令牌:

Please enter the gitlab-ci token for this runner
sample-gitlab-ci-token

在 GitLab 网页界面中输入一个描述,帮助您识别它。 我们建议将这个实例命名为一些独特的名称,比如为了清晰起见,可以使用 runner-bastion。

Please enter the gitlab-ci description for this runner
[yourhostname] runner-bastion

如果相关,您可以输入您将与您的运行程序一起构建的代码的标记。 但是,我们建议在这个阶段保留空白。 稍后从 GitLab 界面可以很容易地改变这一点。

Please enter the gitlab-ci tags for this runner (comma separated):
code-tag

选择您的跑步者是否应该能够运行无标记作业。 这个设置允许您选择您的跑步者是否应该构建没有标记的存储库,或者是否需要特定的标记。 在这种情况下选择 true,这样您的运行程序可以执行所有存储库。

Whether to run untagged jobs [true/false]: true

选择这个运行程序是否应该在你的项目之间共享,或者锁定到当前的运行程序,这会阻止它构建除指定代码以外的任何代码。 现在选择 false,因为稍后可以在 GitLab 的界面中更改:

Whether to lock Runner to current project [true/false]: false

选择执行者,将建立您的机器。 因为我们将使用 Docker 创建新的飞沫,我们将选择 Docker + machine 在这里,但你可以在这个兼容性图表中阅读更多关于每种方法的优点:

Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
docker+machine

你会被问到对于没有明确定义的项目应该使用哪个图像,我们会选择一个基本的、安全的默认图像:

Please enter the Docker image (e.g. ruby:2.1):
alpine:latest

现在您已经完成了配置核心 bastion runner! 此时,它应该出现在 GitLab 管理设置的 GitLab Runner 页面中,我们通过访问这个页面来获得令牌。

如果您在这些步骤中遇到任何问题,GitLab Runner 文档包含故障排除选项。

第6步ー配置 Docker 缓存和 Docker 机器

为了在构建队列忙碌的时候加速液滴的创建,我们将利用 Docker 在 Bastion dropping 上的缓存工具来存储你常用的容器在 DigitalOcean Spaces 上的图像。

为此,使用以下命令在 SSH shell 上升级 Docker Machine:

  • curl -L https://github.com/docker/machine/releases/download/v0.14.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && sudo install /tmp/docker-machine /usr/local/bin/docker-machine

随着 Docker Machine 的升级,我们可以继续设置 GitLab Runner 使用的访问令牌。

第七步ー收集数码证书

现在我们需要创建凭证,GitLab Runner 将使用你的 DigitalOcean 帐户创建新的液滴。

访问你的 DigitalOcean 指示板并点击 API。 在下一个屏幕上,查找个人访问令牌并单击生成新令牌。

给这个新的令牌起一个你能认出来的名字,比如 GitLab Runner Access,并确保读写范围都是可用的,因为我们需要液滴在没有人工干预的情况下制造新的机器。

复制令牌到安全的地方,因为我们将在下一步使用它。 您不能在不重新生成该令牌的情况下再次检索该令牌,因此请确保安全地存储该令牌。

第8步ー编辑 GitLab Runner Configuration Files

为了将所有这些组件集合在一起,我们需要完成配置 bastion 雾滴来与您的 DigitalOcean 帐户进行通信。

在你的 SSH 连接到你的 bastion 雾滴,使用你最喜欢的文本编辑器,如 nano,打开 GitLab Runner 配置文件进行编辑:

  • nano /etc/gitlab-runner/config.toml

这个配置文件负责您的 CI 设置使用的规则,这些规则用于根据需要进行上下扩展。 要按需配置自动缩放的堡垒,您需要添加以下行:

/etc/gitlab-runner/config.toml
concurrent = 50   # All registered Runners can run up to 50 concurrent builds

[[runners]]
  url = "https://example.digitalocean.com"
  token = "existinggitlabtoken"             # Note this is different from the registration token used by `gitlab-runner register`
  name = "example-runner"
  executor = "docker+machine"        # This Runner is using the 'docker+machine' executor
  limit = 10                         # This Runner can execute up to 10 builds (created machines)
  [runners.docker]
    image = "alpine:latest"               # Our secure image
  [runners.machine]
    IdleCount = 1                    # The amount of idle machines we require for CI if build queue is empty
    IdleTime = 600                   # Each machine can be idle for up to 600 seconds, then destroyed
    MachineName = "gitlab-runner-autoscale-%s"    # Each machine will have a unique name ('%s' is required and generates a random number)
    MachineDriver = "digitalocean"   # Docker Machine is using the 'digitalocean' driver
    MachineOptions = [
        "digitalocean-image=coreos-stable", # The DigitalOcean system image to use by default
        "digitalocean-ssh-user=core", # The default SSH user
        "digitalocean-access-token=DO_ACCESS_TOKEN", # Access token from Step 7
        "digitalocean-region=nyc3", # The data center to spawn runners in
        "digitalocean-size=1gb", # The size (and price category) of your spawned runners
        "digitalocean-private-networking" # Enable private networking on runners
    ]
  [runners.cache]
    Type = "s3"   # The Runner is using a distributed cache with the S3-compatible Spaces service
    ServerAddress = "nyc3.spaces.digitaloceanspaces.com"
    AccessKey = "YOUR_SPACES_KEY"
    SecretKey = "YOUR_SPACES_SECRET"
    BucketName = "your_bucket_name"
    Insecure = true # We do not have a SSL certificate, as we are only running locally 

添加新线条后,根据设置自定义访问标记、区域和液滴大小。 在本教程中,我们使用了1gb 的最小液滴大小,并在 NYC3中创建了我们的液滴。 一定要使用与你的案例相关的信息。

您还需要自定义缓存组件,并从基础结构配置步骤、访问密钥、秘钥和创建的 Space 的名称中输入 Space 的服务器地址。

完成后,重新启动 GitLab Runner 以确保配置正在使用:

  • gitlab-runner restart

如果您想了解更多可用的选项,包括非高峰时段,您可以阅读 GitLab 的高级文档。

第九步: 测试你的 GitLab 跑步者

在这一点上,我们的 GitLab Runner bastion spill 已经配置好了,并且随着 CI 队列的填满,可以按需创建 DigitalOcean spils。 我们需要通过前往 GitLab 实例和我们在步骤1中导入的项目来测试它,以确保它工作正常。

要触发构建,请单击 readme.md 文件,然后单击 edit,并将任何相关的测试文本添加到该文件中,然后单击 Commit changes。

现在构建将被自动触发,可以在项目的左侧导航的 ci / cd 选项下找到。

在这个页面上,您应该看到一个具有运行状态的管道条目。 在你的 DigitalOcean 账户中,你会看到 GitLab Runner 自动创建的一些液滴,这些液滴是为了实现这个改变。

祝贺你! 您的 CI 管道是可扩展的,现在可以管理自己的资源使用。 在指定的空闲时间之后,应该自动销毁计算机,但是我们建议手动验证这一点,以确保您不会意外收到账单。

故障排除

在某些情况下,GitLab 可能会报告跑步者无法到达,因此不执行任何操作,包括部署新的跑步者。 你可以通过停止 GitLab Runner,然后在调试模式下重新启动来解决这个问题:

  • gitlab-runner stop
  • gitlab-runner --debug start

输出应该抛出一个错误,这将有助于确定是哪个配置导致了问题。

如果您的配置创建了太多的机器,并且您希望同时删除它们,您可以运行以下命令来销毁它们:

  • docker-machine rm $(docker-machine ls -q)

关于更多的故障排除步骤和其他配置选项,你可以参考 GitLab 的文档。

总结

您已经成功地使用 GitLab Runner 和 Docker 建立了自动化的 ci / cd 管道。 从这里开始,你可以使用 Docker Registry 配置更高级别的缓存来优化性能,或者探索在特定的 GitLab 代码运行器中使用标记代码构建。

更多关于 GitLab Runner 的信息,请参阅详细的文档,或者了解更多,你可以阅读 GitLab 关于如何充分利用持续集成管道的系列博客文章。

这篇文章也出现在 GitLab 博客上。