- 概览
- 系统要求
- 支持的云提供商
- Runner 配置
- 限制 Docker Machine 执行器创建的虚拟机的数量
- 弹性伸缩算法和参数
concurrent
、limit
和IdleCount
怎样生成运行机器的上限IdleScaleFactor
策略- 弹性伸缩时间段配置
- 非峰值时间模式配置(废弃)
- 分布式 Runner 缓存
- 分布式容器镜像库镜像
config.toml
的完整示例
Docker Machine 执行器弹性伸缩配置
弹性伸缩功能引入于极狐GitLab Runner 1.1.0。
弹性伸缩提供了一种以更灵活和动态的方式使用资源的能力。
极狐GitLab Runner 可以弹性伸缩,您的基础设施可以在任何时候包含必须数量的构建实例。如果您将您的极狐GitLab Runner 配置为仅使用弹性伸缩,安装 Runner 的系统会成为所有其创建的机器的堡垒机。这个机器被称为 “Runner Manager”。
概览
当启用并正确配置了这个功能后,在按需创建的机器上就会执行作业。这些机器可以在作业完成后,运行下一个作业或者在配置的
IdleTime
后被移除。
系统要求
在配置弹性伸缩功能之前,您必须:
- 准备您的环境.
- 可选。使用极狐GitLab 提供的 Docker Machine 的派生版本,它有一些额外的修复。
支持的云提供商
弹性伸缩机制基于 Docker Machine。
Runner 配置
本部分描述了重要的弹性伸缩参数。更多关于配置细节的信息,请参见高级配置。
Runner 全局选项
参数 | 值 | 描述 |
---|---|---|
concurrent
| integer | 全局限制可以并发运行的作业的数量。这是使用所有定义的 Runner、本地和弹性伸缩的作业的最大值。它与 limit ([[runners]] 部分) 和 IdleCount ([runners.machine] 部分)一起影响创建的机器的上限。
|
[[runners]]
选项
参数 | 值 | 描述 |
---|---|---|
executor
| string | 如果想使用弹性伸缩功能, executor 必须被设置为 docker+machine 或 docker-ssh+machine 。
|
limit
| integer | 限制可以被特定令牌并发处理的作业数量。0 表示不作限制。 对于弹性伸缩,数量为此供应商(与 concurrent 和 IdleCount 一起)创建的机器数量的上限。
|
[runners.machine]
选项
可以在极狐GitLab Runner - 高级配置 - [runners.machine]
部分查看配置参数详细信息。
[runners.cache]
选项
可以在极狐GitLab Runner - 高级配置 - [runners.cache]
部分查看配置参数详细信息。
附加配置信息
当您设置 IdleCount = 0
时,还有一种特殊的模式。在这种模式下,机器永远在每个作业前按需创建(如果在闲置状态下没有可用机器)。作业完成后,弹性伸缩功能就会生效,
和下面描述的一样。
机器会等待下一个作业,如果没有需要执行的作业,经过
IdleTime
时间后,这个机器会被移除。没有作业的时候,闲置状态下不会有机器。
如果 IdleCount
设置为比 0
大的数字,则会在后台创建闲置的虚拟机。Runner 在申请处理新作业之前会获得一个现存的闲置虚拟机。
- 如果把作业分配给 Runner,这个作业会被发送到之前获得的那台虚拟机。
- 如果没有把作业分配给 Runner,那么闲置虚拟机上的锁会打开,虚拟机会被释放到资源池中。
限制 Docker Machine 执行器创建的虚拟机的数量
为了限制 Docker Machine 执行器创建的虚拟机的数量,我们在 config.toml
文件的 [[runners]]
部分中使用 limit
参数。
concurrent
参数不限制虚拟机的数量。
下面的例子展示了 config.toml
文件中为 Runner 进程设置的值:
concurrent = 100
[[runners]]
name = "first"
executor = "shell"
limit = 40
(...)
[[runners]]
name = "second"
executor = "docker+machine"
limit = 30
(...)
[[runners]]
name = "third"
executor = "ssh"
limit = 10
[[runners]]
name = "fourth"
executor = "virtualbox"
limit = 20
(...)
通过这个配置:
- 一个 Runner 进程可以创建四个不同的 Runner Worker,且他们使用不同的执行环境。
-
concurrent
值设置为 100,所以这个 Runner 会执行最多 100 个并发极狐GitLab CI/CD 作业。 - 只有
second
Runner Worker 被配置为使用 Docker Machine 执行器,因此可以自动创建虚拟机。 -
limit
设置为30
表示second
Runner Worker 可以在任意时间,在弹性伸缩虚拟机上执行最多 30 个 CI/CD 作业。 - 尽管
concurrent
定义了多个[[runners]]
worker 上全局并发的限制,limit
定义了单个[[runners]]
worker 的最大并发。
在这个例子中,Runner 进程处理:
- 对于所有
[[runners]]
worker,多达 100 个并发作业。 - 对于
first
worker,使用shell
执行器处理不多于 40 个作业。 - 对于
second
worker, 使用docker+machine
执行器处理不多于 30 个作业。此外,runner 会基于[runners.machine]
中的弹性伸缩配置维护虚拟机,但是所有状态(闲置、使用中、创建中、移除中)的虚拟机的数量不超过 30 台。 - 对于
third
worker, 使用ssh
执行器处理不多于 10 个作业。 - 对于
fourth
worker, 使用virtualbox
执行器处理不多于 20 个作业。
在第二个例子中,配置了两个 [[runners]]
worker 以使用 docker+machine
执行器。通过这个配置,每个 Runner Worker 管理一个独立的虚拟机资源池,虚拟机受 limit
参数的值的限制。
concurrent = 100
[[runners]]
name = "first"
executor = "docker+machine"
limit = 80
(...)
[[runners]]
name = "second"
executor = "docker+machine"
limit = 50
(...)
在这个例子中:
- 处理不多于 100 个作业 (
concurrent
的值)。 - Runner 进程处理两个
[[runners]]
worker 中的作业,每个都使用docker+machine
执行器。 -
first
Runner 可以创建最多 80 个虚拟机,因此这个 Runner 可以在任意时间执行最多 80 个作业。 -
second
Runner 可以创建最多 50 个虚拟机,因此这个 Runner 可以在任意时间执行最多 50 个作业。
130
(80 + 50 = 130
),但是全局级别的concurrent
的值 100
表示这个 Runner 进程可以并发执行最多 100 个作业。弹性伸缩算法和参数
弹性伸缩算法基于以下参数:
IdleCount
IdleCountMin
IdleScaleFactor
IdleTime
MaxGrowthRate
limit
每个不运行作业的机器都处于闲置状态。当极狐GitLab Runner 在弹性伸缩模式下,它会监控所有机器并确保一直有机器的 IdleCount
处于闲置状态。
IdleScaleFactor
和 IdleCountMin
设置,改变了一些这种行为。
如果闲置机器数量不足,极狐GitLab Runner
就会依据 MaxGrowthRate
的限制部署新的机器。
如果申请的机器的数量超过 MaxGrowthRate
的值,申请流程会暂停,直到创建的机器的数量低于 MaxGrowthRate
。
同时,极狐GitLab Runner 检查每台机器处于闲置状态的时间。 如果时间超过 IdleTime
的值,会自动移除机器。
示例: 我们假设已经使用以下弹性伸缩参数配置了极狐GitLab Runner:
[[runners]]
limit = 10
# (...)
executor = "docker+machine"
[runners.machine]
MaxGrowthRate = 1
IdleCount = 2
IdleTime = 1800
# (...)
最初没有作业排队的时候,极狐GitLab Runner 开启 2 台机器
(IdleCount = 2
),并将他们设置成闲置状态。注意,我们也同样将
IdleTime
设置成 30 分钟 (IdleTime = 1800
)。
现在我们假设在极狐GitLab CI 中有 5 个作业正在排队。前两个作业被发送到闲置状态的机器,这个状态的机器有 2 台。
极狐GitLab Runner 现在注意到闲置的数量少于 IdleCount
(0 < 2
),所以它会开启新机器。这些机器按顺序分配,以防超过
MaxGrowthRate
的值。
余下的 3 个作业被分配到准备好的第一台机器。作为优化, 它可以是一台忙碌状态的机器,但是已经执行完了作业,或是一台新分配的机器。我们假设机器分配过程很快,并且新机器的分配在之前的作业完成之前就已经完成了。
我们现在有 1 台闲置机器,所以极狐GitLab Runner 开启另一个新机器去满足 IdleCount
。因为有新作业在排队,那 2 个机器会保持闲置状态并且极狐GitLab Runner 也被满足。
会发生如下情况: 我们有 2 台闲置状态的机器等待新作业。5 个作业排队后,创建了新作业,所以我们一共有 7 台机器。 其中 5 台在运行作业,其中 2 台处于闲置状态,等待下个作业。
算法也是同样的方式;极狐GitLab Runner 为每台用于执行作业的机器创建一台新的闲置机器,直到满足 IdleCount
。
创建机器的数量受
limit
参数的限制。如果极狐GitLab Runner 注意到创建的机器的数量存在 limit
限制,它就会停止弹性伸缩,并且新作业必须在作业队列中排队,直到机器开始返回闲置状态。
在上面的例子中,我们一直都有 2 台闲置的机器。IdleTime
只有在超过 IdleCount
时适用。然后我们试图将机器的数量减少到
IdleCount
。
向下伸缩
作业完成后,机器被设置为闲置状态,并等待执行下一个作业。我们假设队列中没有新的作业。
在 IdleTime
指定的时间过去后,闲置机器被移除。在我们的例子中,30 分钟后,所有的机器都被移除
(最后一个作业执行完毕后的 30 分钟),并且极狐GitLab
Runner 开始保持闲置机器的 IdleCount
运行,就像例子开头那样。
总结:
- 启动极狐GitLab Runner。
- 极狐GitLab Runner 创建 2 台闲置机器。
- 极狐GitLab Runner 选择 1 个作业。
- 极狐GitLab Runner 创建 1 台机器,满足一直要有 2 台闲置机器的强烈要求。
- 作业完成后,拥有 3 台闲置机器。
- 当 3 台闲置机器中的 1 台从最后一次选择作业的时候算起超过了
IdleTime
, 会被移除。 - 极狐GitLab Runner 一直有至少 2 台闲置机器等待作业。
下面是作业状态和机器状态的比较图表。
concurrent
、limit
和 IdleCount
怎样生成运行机器的上限
没有魔法方程告诉您怎样设置 limit
或
concurrent
。根据您的需求操作。闲置机器的 IdleCount
是一个加速功能。您不必等待 10s/20s/30s
创建实例。但是作为一个用户,您希望您的所有机器(您付费的)都运行作业,而不是处于闲置状态。所以您应该将 concurrent
和 limit
设置为您愿意支付的机器的最大数量的值。
至于 IdleCount
,应该设置为当队列中没有作业时,生成未使用机器的最小数量的值。
我们假设下面的例子:
concurrent=20
[[runners]]
limit = 40
[runners.machine]
IdleCount = 10
在上面的场景中,我们可以拥有的机器总数是 30。
所有机器(构建中和闲置)的 limit
可以是 40。我们可以拥有 10 台闲置的机器,但是 concurrent
作业是 20。所以我们一共可以拥有 20
台并发机器运行作业和 10 台闲置机器,总计 30 台。
但是当 limit
小于可以创建的机器的总数时会发生什么呢? 下面举例说明:
concurrent=20
[[runners]]
limit = 25
[runners.machine]
IdleCount = 10
在这个例子中,您可以拥有最多 20 个并发作业和 25 台机器。
最坏的情况下,您不可以拥有 10 台闲置机器,只能有 5 台,因为 limit
是 25。
IdleScaleFactor
策略
IdleCount
参数定义了 Runner 应该保持的闲置机器的静态数量。
您赋的值取决于您的用例。
您开始可以分配一个相对较少的闲置状态的机器,并让它们根据当前使用情况自动适应更大的数量。为达到这个效果,您需要使用实验性的 IdleScaleFactor
设置。
IdleScaleFactor
内部是一个 float64
值,需要使用浮点格式。
例如: 0.0
、 1.0
或 1.5
等。如果使用了整数格式(例如 IdleScaleFactor = 1
),
Runner 的进程会失败报错:
FATAL: Service run failed error=toml: cannot load TOML value of type int64 into a Go float
。当您使用这个设置,极狐GitLab Runner 会尽量保持一定数量的处于闲置状态的机器。
然而,这个数量并不是静态的。极狐GitLab Runner 不再使用 IdleCount
,
而是检查正在使用中的机器的数量,并将期望的闲置容量定义为那个数量的一个因素。
当然,如果没有当前使用的机器,IdleScaleFactor
会取值为没有需要保持的闲置机器。
由于弹性伸缩算法的工作方式,如果 IdleCount
大于 0
(只有那个时候
IdleScaleFactor
才适用),Runner 不会在没有能够处理作业的闲置机器的情况下要求处理作业。没有新作业,使用的机器的数量就不会增加,所以 IdleScaleFactor
会一直等于
0
。这也会将 Runner 阻塞到一种不可用的状态。
因此,我们引入了第二种设置: IdleCountMin
。它定义了无论 IdleScaleFactor
的值为多少,
需要保持的闲置机器的最小数量。如果使用了 IdleScaleFactor
,那么这个设置不可以设置为小于 1。如果设置为 1,Runner 会自动将它设置为 1。
您也可以使用 IdleCountMin
定义应该一直可用的闲置机器的最小数量。
这允许新作业进入队列快速启动。 至于 IdleCount
,您赋的值取决于您的用例。
示例:
concurrent=200
[[runners]]
limit = 200
[runners.machine]
IdleCount = 100
IdleCountMin = 10
IdleScaleFactor = 1.1
在这种情况下,当 Runner 接近了决策点,它会检查当前使用的机器的数量。
假设当前有 5 台闲置机器和 10 台正在使用的机器。 乘以 IdleScaleFactor
,
Runner 决定应该有 11 台闲置机器,所以它会再创建 6 台。
如果您有 90 台闲置机器和 100 台正在使用的机器。基于 IdleScaleFactor
,极狐GitLab Runner 判断应该有 100 * 1.1 = 110
台闲置机器。 因此它又会创建新机器。然而,当达到
100
台 闲置机器时,它会发现这个数量是 IdleCount
定义的上限,
就不会再创建新的闲置机器了。
如果正在使用的闲置机器的数量从 100 下降到了 20,期望的闲置机器的数量是 20 * 1.1 = 22
。
极狐GitLab Runner 会慢慢开始关闭机器。如上所述,极狐GitLab Runner 会移除不用于 IdleTime
的机器。因此,不会大幅度地移除太多闲置虚拟机。
如果闲置机器的数量将为 0, 期望的闲置机器的数量是 0 * 1.1 = 0
。
然而,这个数量小于定义的 IdleCountMin
设置,所以 Runner 会慢慢开始移除闲置虚拟机,
只保留 10 台。这个点过后,向下伸缩会停止,Runner 保持拥有 10 台闲置状态的机器。
弹性伸缩时间段配置
引入于极狐GitLab Runner 13.0。
弹性伸缩可以配置为,在不同时间段拥有不同的值。 组织机构可能会在固定的时间大量处理作业, 其他时间作业数量很少。 例如,大多数商业公司的工作时间为周一到周五的固定时间,比如上午 9 点到下午 6 点。 晚上和周末不会启动流水线。
您可以通过 [[runners.machine.autoscaling]]
部分配置时间段。
每个都支持基于一组 Periods
设置 IdleCount
和 IdleTime
。
弹性伸缩时间段如何工作
在 [runners.machine]
设置中,您可以添加多个 [[runners.machine.autoscaling]]
部分,每个都有它自己的 IdleCount
、 IdleTime
、 Periods
和 Timezone
属性。每个配置都应该定义一个部分,按顺序从最普通的场景到最具体的场景。
所有的部分都被解析。最后一个匹配当前时间的部分是活跃的。如果没有匹配的部分,会使用 [runners.machine]
的根的值。
示例:
[runners.machine]
MachineName = "auto-scale-%s"
MachineDriver = "google"
IdleCount = 10
IdleTime = 1800
[[runners.machine.autoscaling]]
Periods = ["* * 9-17 * * mon-fri *"]
IdleCount = 50
IdleTime = 3600
Timezone = "UTC"
[[runners.machine.autoscaling]]
Periods = ["* * * * * sat,sun *"]
IdleCount = 5
IdleTime = 60
Timezone = "UTC"
在本配置中,每个工作日的 9:00 点和 16:59 点(UTC),超量部署了机器,用以在运行时间处理大量流量。在周末, IdleCount
为适应流量下降,下降为 5。
其余时间,使用根 IdleCount = 10
和 IdleTime = 1800
中的默认值。
您可以指定时间段中的 Timezone
,例如 "Australia/Sydney"
。如果您没有指定,
会使用每个 Runner 的主机机器的系统设置。
这个默认值可以被明确描述为 Timezone = "Local"
。
更多关于 [[runner.machine.autoscaling]]
部分语法的内容,请参见极狐GitLab Runner - 高级配置 - [runners.machine]
部分。
非峰值时间模式配置(废弃)
这个设置已被废弃,并于极狐GitLab Runner 14.0 移除。
弹性伸缩不可以再配置非峰值模式时间段,而是将其转化为弹性伸缩时间段。
将非峰值配置转化为弹性伸缩配置
将非峰值配置转化为弹性伸缩配置,创建 [[runners.machine.autoscaling]]
部分,并按以下规则添加内容:
-
Periods
字段从OffpeakPeriods
取值。 -
IdleCount
字段从OffpeakIdleCount
取值。 -
IdleTime
字段从OffpeakIdleTime
取值。 -
Timezone
字段从OffpeakTimezone
取值。
通过例子展示以下非峰值配置的转化:
[runners.machine]
MachineName = "auto-scale-%s"
MachineDriver = "google"
IdleCount = 10
IdleTime = 1800
OffPeakPeriods = ["* * 9-17 * * mon-fri *"]
OffPeakIdleCount = 50
OffPeakIdleTime = 3600
OffPeakTimezone = "UTC"
转化结果:
[runners.machine]
MachineName = "auto-scale-%s"
MachineDriver = "google"
IdleCount = 10
IdleTime = 1800
[[runners.machine.autoscaling]]
Periods = ["* * 9-17 * * mon-fri *"]
IdleCount = 50
IdleTime = 3600
Timezone = "UTC"
分布式 Runner 缓存
为加快您的作业,极狐GitLab Runner 提供了缓存机制, 用以将选中的目录和/或文件在后续作业中保存和共享。
当作业在同一个主机上运行时,这种方式没有问题。但是当您开始使用极狐GitLab Runner 弹性伸缩功能时,您的大部分作业都会在新(或几乎新的)主机上运行,这些主机在新 Docker 容器上执行作业。在这种情况下,您就无法使用缓存功能。
为解决这个问题,引入了分布式 Runner 缓存功能和弹性伸缩功能。
本功能使用配置的对象存储服务器在使用的 Docker 主机上共享缓存。 极狐GitLab Runner 查询服务器,下载这些归档以还原缓存,或者将其上传以归档缓存。
启用分布式缓存,您需要使用 [runners.cache]
指示,在 config.toml
中对其进行定义。
[[runners]]
limit = 10
executor = "docker+machine"
[runners.cache]
Type = "s3"
Path = "path/to/prefix"
Shared = false
[runners.cache.s3]
ServerAddress = "s3.example.com"
AccessKey = "access-key"
SecretKey = "secret-key"
BucketName = "runner"
Insecure = false
在上面的例子中,S3 URL 遵循这个结构
http(s)://<ServerAddress>/<BucketName>/<Path>/runner/<runner-id>/project/<id>/<cache-key>
。
在两个或多个 Runner 之间共享缓存,将 Shared
标志设置为 true。
这个标志从 URL (runner/<runner-id>
)中移除了 Runner 令牌,
所有配置的 Runner 共享同一个缓存。
您也可以设置 Path
,当启用共享缓存时,在 Runner 中分离缓存。
分布式容器镜像库镜像
为加快 Docker 容器内执行的作业,您可以使用 Docker 库镜像服务。这个服务在 Docker 机和所有使用的镜像库之间提供了代理。 镜像库镜像一次将图像下载下来。 在每个新主机上,或在镜像不可用的现存的主机上,图像从配置的镜像库镜像上下载下来。
如果镜像在您的 Docker 机 LAN 中,图像下载步骤在主机上会快很多。
配置 Docker 镜像库镜像,您必须向 config.toml
中的配置添加 MachineOptions
。
[[runners]]
limit = 10
executor = "docker+machine"
[runners.machine]
(...)
MachineOptions = [
(...)
"engine-registry-mirror=http://10.11.12.13:12345"
]
10.11.12.13:12345
是 IP 地址和端口号,您的镜像库镜像正在侦听来自 Docker 服务的连接。Docker Machine 创建的主机必须可以访问。
详情请参见使用容器代理。
config.toml
的完整示例
下面的 config.toml
使用 google
Docker Machine 驱动:
concurrent = 50 # All registered runners can run up to 50 concurrent jobs
[[runners]]
url = "https://gitlab.com"
token = "RUNNER_TOKEN" # Note this is different from the registration token used by `gitlab-runner register`
name = "autoscale-runner"
executor = "docker+machine" # This runner is using the 'docker+machine' executor
limit = 10 # This runner can execute up to 10 jobs (created machines)
[runners.docker]
image = "ruby:2.7" # The default image used for jobs is 'ruby:2.7'
[runners.machine]
IdleCount = 5 # There must be 5 machines in Idle state - when Off Peak time mode is off
IdleTime = 600 # Each machine can be in Idle state up to 600 seconds (after this it will be removed) - when Off Peak time mode is off
MaxBuilds = 100 # Each machine can handle up to 100 jobs in a row (after this it will be removed)
MachineName = "auto-scale-%s" # Each machine will have a unique name ('%s' is required)
MachineDriver = "google" # Refer to Docker Machine docs on how to authenticate: https://docs.docker.com/machine/drivers/gce/#credentials
MachineOptions = [
"google-project=GOOGLE-PROJECT-ID",
"google-zone=GOOGLE-ZONE", # e.g. 'us-central-1'
"google-machine-type=GOOGLE-MACHINE-TYPE", # e.g. 'n1-standard-8'
"google-machine-image=ubuntu-os-cloud/global/images/family/ubuntu-1804-lts",
"google-username=root",
"google-use-internal-ip",
"engine-registry-mirror=https://mirror.gcr.io"
]
[[runners.machine.autoscaling]] # Define periods with different settings
Periods = ["* * 9-17 * * mon-fri *"] # Every workday between 9 and 17 UTC
IdleCount = 50
IdleCountMin = 5
IdleScaleFactor = 1.5 # Means that current number of Idle machines will be 1.5*in-use machines,
# no more than 50 (the value of IdleCount) and no less than 5 (the value of IdleCountMin)
IdleTime = 3600
Timezone = "UTC"
[[runners.machine.autoscaling]]
Periods = ["* * * * * sat,sun *"] # During the weekends
IdleCount = 5
IdleTime = 60
Timezone = "UTC"
[runners.cache]
Type = "s3"
[runners.cache.s3]
ServerAddress = "s3.eu-west-1.amazonaws.com"
AccessKey = "AMAZON_S3_ACCESS_KEY"
SecretKey = "AMAZON_S3_SECRET_KEY"
BucketName = "runner"
Insecure = false
注意 MachineOptions
参数包含 google
驱动的选项,Docker Machine 使用该驱动生成托管在 Google Compute Engine 上的机器,和 Docker Machine 自身的选项(engine-registry-mirror
)。