如何在DigitalOcean上使用GitLab Runner自动调整GitLab连续部署

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

介绍

GitLab是一个开源工具,由软件团队用来管理其完整的开发和交付生命周期。 GitLab提供了一系列广泛的功能:问题跟踪,git存储库,持续集成,容器注册,部署和监控。 这些功能都是从一开始就构建成一个应用程序。 您可以在自己的服务器上托管GitLab,也可以使用GitLab.com ,这是一项云服务,开源项目免费提供所有顶级功能。

GitLab持续集成/持续交付(CI / CD)功能是一种有效的方法,可以在部署代码之前建立测试所有代码的习惯。 GitLab CI / CD还具有高度可扩展性,这要归功于其他工具GitLab Runner,它可以自动缩放构建队列,以避免开发团队尝试释放代码的漫长等待时间。

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

目标

我们将在DigitalOcean上构建一个可扩展的CI / CD流程,通过在平台上创建新服务器自动响应需求,并在队列为空时销毁它们。

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

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

我们将使用三台独立的服务器来构建这个项目,所以我们先来看看术语:

  • GitLab :您的托管GitLab实例或存储代码存储库的自托管实例。

  • GitLab堡垒堡垒服务器或Droplet是我们将要配置的核心。 它是用于与DigitalOcean API进行交互的控件实例,以在必要时创建Droplet并销毁它们。 此服务器上不执行任何作业。

  • GitLab跑步者 :您的跑步者是临时服务器或滴水,当需要在构建队列中执行CI / CD作业时,由堡垒服务器随时创建。 这些服务器是一次性的,并且是在您的构建被标记为传递或失败之前执行或测试您的代码的地方。

GitLab跑步图

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

先决条件

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

要在Ubuntu 16.04 Droplet上进行设置,您可以使用DigitalOcean单击图像,或按照我们的指南:“ 如何在Ubuntu 16.04上安装和配置GitLab ”。

为了本教程的目的,我们假设您在此Droplet上启用了私有网络,您可以通过遵循我们的“ 如何在现有的Droplet上启用DigitalOcean私有网络 ”指南来实现该功能 ,但这不是强制性的。

在本教程中,我们将在Droplet上使用具有管理权限的非root用户。

第1步 - 导入JavaScript项目

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

GitLab接口

登录到您的GitLab实例并单击加号图标 ,然后从下拉菜单中选择新建项目

在新项目屏幕上,选择导入项目标签,然后单击按URL回购以直接从GitHub导入我们的示例项目。

将以下克隆URL粘贴到Git存储库URL中:

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

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

您的新项目现在将位于GitLab中,我们可以开始设置CI管道。

第2步 - 建立基础设施

我们的GitLab Code Runner需要特定的配置,因为我们打算以编程方式创建Droplet来处理CI负载,随着其增长和缩小。

我们将在本教程中创建两种类型的机器:控制和产生新机器的堡垒实例,以及我们的运行器实例,它们是由堡垒Droplet产生的临时服务器,用于在需要时构建代码。 堡垒实例使用Docker来创建你的跑步者。

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

  • 灵活的Droplet - 我们将为我们的GitLab Runners创建内存优化的Droplet,因为它是一个内存密集型的过程,它将使用Docker进行容器化。 您可以根据需要在将来缩小或增大此Droplet,但我们建议使用灵活的Droplet选项作为了解管道在负载下的性能的起点。

  • DigitalOcean Spaces(对象存储) - 我们将使用DigitalOcean Spaces在创建和销毁跑步者时将持久缓存的构建组件保留下来 这减少了在CI管线繁忙时设置新跑步者所需的时间,并且允许新跑步者在其他人立即停止的地方选择跑步者。

  • 专用网络 - 我们将为您的堡垒Droplet和GitLab跑步者创建专用网络,以确保代码编译的安全性并减少所需的防火墙配置。

首先,我们将创建堡垒Droplet。 创建一个新的Droplet ,然后在选择一个图像下 ,选择一键式应用程序选项卡。 从那里, 在16.04选择Docker 17.12.0-ce (请注意,此版本在撰写本文时是最新的),然后选择最小的Droplet大小,因为我们的堡垒Droplet将管理其他Droplet的创建,而不是实际执行测试。

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

选择专用网络监控选项,然后点击创建Droplet

我们还需要设置用于缓存的存储空间。 按照“ 如何创建DigitalOcean空间和API密钥 ”中的步骤,在与托管GitLab实例相同或最近的数据中心中创建一个新空间以及一个API密钥。

注意这个键,因为我们稍后会在教程中需要它。

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

第3步 - 配置GitLab Runner Bastion服务器

随着新的Droplet准备就绪,我们现在可以配置GitLab Runner。 我们将从GitLab和GitHub存储库安装脚本。

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

使用SSH连接到Droplet,进入/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安装。

第4步 - 获取跑步者注册令牌

要将GitLab Runner链接到现有的GitLab安装,我们需要通过获取一个令牌来验证您的代码存储库的运行程序,从而将这两个实例链接在一起。

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

在屏幕左侧,将鼠标悬停在概览上,然后从显示的列表中选择跑步者

如何为新项目设置共享运行程序的Runners页面下,复制第3步中显示的令牌,并记下它以及来自第2步的GitLab实例的可公开访问的URL。如果您正在使用HTTPS for Gitlab,确保它不是自签名证书,否则GitLab Runner将无法启动。

第5步 - 在Bastion Droplet上配置GitLab

回到与堡垒Droplet的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 Web界面中识别它。 为了清晰起见,我们建议将这个实例命名为独特的,如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创建新的Droplet,因此我们将在此处选择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

现在你已经完成了核心堡垒跑步者的配置! 此时它应该出现在我们为获取令牌而访问的GitLab管理设置的GitLab Runner页面中。

如果您在执行这些步骤时遇到任何问题,则GitLab Runner文档包含用于故障排除的选项。

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

为了在构建队列繁忙时加快Droplet创建速度,我们将利用Bastion Droplet上的Docker缓存工具将常用容器的图像存储在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设置我们的访问令牌。

第7步 - 收集DigitalOcean凭证

现在我们需要创建GitLab Runner将使用您的DigitalOcean帐户创建新Droplet的凭据。

访问您的DigitalOcean 仪表板并点击API 在下一个屏幕上,查找个人访问令牌并单击生成新令牌

为新标记提供一个您将识别的名称,例如GitLab Runner Access并确保启用了读写范围,因为我们需要Droplet创建新机器而无需人工干预。

将令牌复制到某个安全的地方,我们将在下一步中使用它。 您无法再次检索此令牌而无需重新生成该令牌,因此请确保其安全存储。

第8步 - 编辑GitLab Runner配置文件

为了将所有这些组件集中在一起,我们需要完成配置我们的堡垒Droplet与您的DigitalOcean帐户进行通信。

在通往SSH底层Droplet的SSH连接中,使用您喜欢的文本编辑器(如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 

一旦添加新行,根据您的设置自定义访问令牌,区域和Droplet大小。 为了本教程的目的,我们使用了1GB的最小Droplet尺寸,并在NYC3中创建了Droplet。 一定要使用与您的案例相关的信息。

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

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

gitlab-runner restart

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

第9步 - 测试你的GitLab跑步者

此时,我们的GitLab Runner bastion Droplet已配置好,并且能够在CI队列填满时按需创建DigitalOcean Droplet。 我们需要对其进行测试,以确保它可以正常工作,方法是前往您的GitLab实例以及我们在第1步中导入的项目。

要触发构建,请单击它编辑readme.md文件,然后单击编辑 ,然后将任何相关测试文本添加到该文件,然后单击提交更改

现在会自动触发构建,可以在左侧导航栏中项目的CI / CD选项下找到构建。

在此页面上,您应该看到一个具有运行状态的管道条目。 在您的DigitalOcean帐户中,您将看到许多由GitLab Runner自动创建的Droplet,以便构建此更改。

恭喜! 您的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的一系列博文 ,了解如何充分利用持续集成管道。