规划并运维实例或群组 Runner 集群
在共享服务模式下扩展 Runner 集群时,请应用以下最佳实践和建议。
当您托管一组实例 Runner 时,需要一套经过周密规划的基础设施,并考虑以下方面:
- 计算容量。
- 存储容量。
- 网络带宽和吞吐量。
- 作业类型(包括编程语言、操作系统平台和依赖库)。
请使用这些建议,根据您所在组织的需求制定极狐GitLab Runner 部署策略。
考虑您的工作负载和环境
在部署 Runner 之前,请考虑您的工作负载和环境需求。
- 列出您计划接入极狐GitLab 的团队。
- 编录您所在组织正在使用的编程语言、Web 框架和库。例如 Go、C++、PHP、Java、Python、JavaScript、React、Node.js。
- 估算每个团队每小时、每天可能执行的 CI/CD 作业数量。
- 确认是否有团队的构建环境需求无法通过使用容器来满足。
- 确认是否有团队的构建环境需求最适合通过为该团队配备专用 Runner 来满足。
- 估算支持预期需求所需的计算容量。
您可以选择不同的基础设施技术栈来托管不同的 Runner 集群。例如,您可能需要在公有云中部署一些 Runner,在本地部署另一些。
Runner 集群上 CI/CD 作业的性能与集群环境直接相关。如果您要执行大量资源密集型 CI/CD 作业,不建议将集群托管在共享计算平台上。
Runner、执行器和自动扩缩能力
gitlab-runner 可执行文件负责运行您的 CI/CD 作业。每个 Runner 都是一个独立的进程,它获取作业执行请求,并根据预定义的配置处理这些请求。作为独立进程,每个 Runner 都可以创建“子进程”(也称为“工作进程”)来运行作业。
并发和限制
自动扩缩 Runner(如 Docker Machine 和 Kubernetes)的限制与不自动扩缩的 Runner 不同。
- 在不自动扩缩的 Runner 上,limit 定义该 Runner 在主机系统上的容量。
- 在自动扩缩的 Runner 上,limit 是您希望运行的 Runner 总数。
有关 concurrency、limit 和 request_concurrency 如何相互作用以控制作业流的更多信息,请参阅极狐GitLab Runner 并发调优的 KB 文章。
基本配置:一个 Runner Manager,一个 Runner
在最基本的配置中,您在受支持的计算架构和操作系统上安装极狐GitLab Runner 软件。例如,您可能有一台运行 Ubuntu Linux 的 x86-64 虚拟机(VM)。
安装完成后,您只需执行一次 Runner 注册命令,并选择 shell 执行器。然后编辑 Runner 的 config.toml 文件,将并发设置为 1。
toml1concurrent = 1 2 3[[runners]] 4 name = "instance-level-runner-001" 5 url = "" 6 token = "" 7 executor = "shell"
此 Runner 可以处理的极狐GitLab CI/CD 作业直接在您安装 Runner 的主机系统上执行。这就像您自己在终端中运行 CI/CD 作业命令一样。在这种情况下,由于您只执行了一次注册命令,config.toml 文件中只包含一个 [[runners]] 节。假设您将并发值设置为 1,那么在此系统上只有一个 Runner“工作进程”可以为该 Runner 进程执行 CI/CD 作业。
中级配置:一个 Runner Manager,多个 Runner
您也可以在同一台机器上注册多个 Runner。这样做时,Runner 的 config.toml 文件中会有多个 [[runners]] 节。如果所有额外的 Runner 工作进程都使用 shell 执行器,并且您将全局 concurrent 设置值更新为 3,那么该主机最多可以同时运行三个作业。
toml1concurrent = 3 2 3[[runners]] 4 name = "instance_level_shell_001" 5 url = "" 6 token = "" 7 executor = "shell" 8 9[[runners]] 10 name = "instance_level_shell_002" 11 url = "" 12 token = "" 13 executor = "shell" 14 15[[runners]] 16 name = "instance_level_shell_003" 17 url = "" 18 token = "" 19 executor = "shell" 20
您可以在同一台机器上注册许多 Runner 工作进程,每个都是一个独立的进程。每个工作进程的 CI/CD 作业性能取决于主机系统的计算容量。
自动扩缩配置:一个或多个 Runner Manager,多个工作进程
当极狐GitLab Runner 设置为自动扩缩时,您可以将一个 Runner 配置为其他 Runner 的管理器。您可以使用 docker-machine 或 kubernetes 执行器来实现。在这种仅作为管理器的配置中,Runner 代理本身不执行任何 CI/CD 作业。
Docker Machine 执行器
- Runner Manager 使用 Docker 按需预配虚拟机实例。
- 在这些 VM 上,极狐GitLab Runner 使用您在 .gitlab-ci.yml 文件中指定的容器镜像执行 CI/CD 作业。
- 您应在各种机器类型上测试 CI/CD 作业的性能。
- 您应考虑根据速度或成本优化您的计算主机。
Kubernetes 执行器
使用 Kubernetes 执行器:
- Runner Manager 在目标 Kubernetes 集群上预配 Pod。
- CI/CD 作业在每个 Pod 上执行,每个 Pod 由多个容器组成。
- 用于作业执行的 Pod 通常比托管 Runner Manager 的 Pod 需要更多的计算和内存资源。
Runner Manager 和 Kubernetes 集群
Runner Manager 和 Kubernetes 集群之间没有固定的一对一关系。
单个 Runner Manager 可以在其 config.toml中有多个 [[runners]] 条目。每个 Runner 条目都有自己的执行器配置。因此,对于使用 Kubernetes 执行器的 Runner,可以为每个 Runner 独立配置 Kubernetes API 连接。
此配置允许一个 Runner Manager 使用多个 Kubernetes 集群。对于每个集群,在该 Runner 条目的 [runners.kubernetes] 节中设置 host 及其凭证。context 设置仅在 host 为空时适用。在挂载了服务账号令牌的 Pod 中运行的管理器使用其自己的集群,并忽略 context。Runner Manager 也可以在其管理的 Kubernetes 集群之外运行,前提是它能够连接到 Kubernetes API。concurrent 设置限制所有 Runner 条目的作业数,包括针对不同集群的条目。
也可以将多个 Runner Manager 配置为使用同一个 Kubernetes 集群。
复用 Runner 配置
每个与同一 Runner 认证令牌关联的 Runner Manager 都会被分配一个 system_id 标识符。system_id 标识正在使用该 Runner 的机器。使用同一认证令牌注册的 Runner 会通过唯一的 system_id. 归组到单个 Runner 条目下。
将相似的 Runner 归组到单个配置下可以简化 Runner 集群的运维。
以下是一个可以将相似 Runner 归组到单个配置下的示例场景:
平台管理员需要使用标签 docker-builds-2vCPU-8GB 提供多个具有相同底层虚拟机实例规格(2 vCPU、8 GB RAM)的 Runner。他们希望至少有两个这样的 Runner,用于高可用性或扩缩。管理员无需在 UI 中创建两个不同的 Runner 条目,而是可以为所有具有相同计算实例规格的 Runner 创建一个 Runner 配置。他们可以复用该 Runner 配置的认证令牌来注册多个 Runner。每个注册的 Runner 都会继承 docker-builds-2vCPU-8GB 标签。对于单个 Runner 配置的所有子 Runner,system_id 充当唯一标识符。
归组的 Runner 可以被多个 Runner Manager 复用来运行不同的作业。
极狐GitLab Runner 在启动时或保存配置时生成 system_id。system_id 会保存到与 config.toml 同一目录下的 .runner_system_id 文件中,并显示在作业日志和 Runner 管理页面中。
生成 system_id 标识符
为了生成 system_id,极狐GitLab Runner 会尝试从硬件标识符(例如某些 Linux 发行版中的 /etc/machine-id)推导出唯一的系统标识符。如果不成功,极狐GitLab Runner 会使用随机标识符来生成 system_id。
system_id 具有以下前缀之一:
- r_:极狐GitLab Runner 分配了随机标识符。
- s_:极狐GitLab Runner 从硬件标识符分配了唯一的系统标识符。
例如,在创建容器镜像时,务必考虑到这一点,以免将 system_id 硬编码到镜像中。如果 system_id 被硬编码,您就无法区分执行给定作业的主机。
删除 Runner 和 Runner Manager
要删除使用 Runner 注册令牌(已弃用)注册的 Runner 和 Runner Manager,请使用 gitlab-runner unregister 命令。
要删除使用 Runner 认证令牌创建的 Runner 和 Runner Manager,请使用 UI 或 API。使用 Runner 认证令牌创建的 Runner 是可复用的配置,可以在多台机器上复用。如果您使用 gitlab-runner unregister 命令,则只会删除 Runner Manager,而不会删除 Runner。
配置实例 Runner
在自动扩缩配置中使用实例 Runner(其中某个 Runner 充当“Runner Manager”)是一种高效且有效的入门方式。
托管 VM 或 Pod 的基础设施技术栈的计算容量取决于:
- 您在考虑工作负载和环境时记录的需求。
- 您用于托管 Runner 集群的技术栈。
在开始运行 CI/CD 工作负载并随时间分析性能后,您可能需要调整计算容量。
对于使用实例 Runner 和自动扩缩执行器的配置,您必须至少从两个 Runner Manager 开始。
您随时间可能需要的 Runner Manager 总数取决于:
- 托管 Runner Manager 的技术栈的计算资源。
- 您为每个 Runner Manager 选择配置的并发数。
- 每个管理器每小时、每天和每月执行的 CI/CD 作业所产生的负载。
例如,在 GitLab.com 上,我们使用 Docker Machine 执行器运行七个 Runner Manager。每个 CI/CD 作业都在一个 Google Cloud Platform (GCP) n1-standard-1 VM 中执行。通过此配置,我们每月处理数百万个作业。
监控 Runner
大规模运维 Runner 集群的一个关键步骤是设置并使用极狐GitLab 自带的 Runner 监控功能。
下表汇总了极狐GitLab Runner 指标。该列表不包含 Go 特有的进程指标。要在 Runner 上查看这些指标,请执行可用指标中所述的命令。
| 指标名称 | 描述 |
|---|---|
| gitlab_runner_api_request_attempts_total | 完成 API 请求时进行的 HTTP 尝试总次数,按 runner、runner_name、system_id、endpoint、status 和 method 分区。gitlab_runner_api_request_statuses_total 仅记录每个请求的最终响应。此计数器包含每次尝试,因此此处可以看到被重试的 429 和 5xx 响应。未获得 HTTP 响应的尝试(例如连接或 TLS 失败)的 status="error"。在 Runner 上下文之外发出的请求(register、verify、unregister、artifacts)的 endpoint 为规范化 API 路径,Runner 标签为空。 |
| gitlab_runner_api_request_retries_total | 完成 API 请求时进行的 HTTP 尝试总次数,按 path 和 method 分区。尽管名称如此,它统计的是包括第一次在内的所有尝试。建议使用 gitlab_runner_api_request_attempts_total,它还包含状态。 |
| gitlab_runner_api_request_statuses_total | API 请求总数,按 runner、runner_name、system_id、endpoint、status 和 method 分区。 |
| gitlab_runner_autoscaling_idle_target | 应用 IdleScaleFactor 和 IdleCountMin 后,自动扩缩器力求保持的可用机器数量。在预热期间,它是预热目标。 |
| gitlab_runner_autoscaling_machine_creation_duration_seconds | 机器创建时间的直方图,按 target_zone、target_region、target_project 和 target_machine_type 分区。 |
| gitlab_runner_autoscaling_machine_failed_creation_duration_seconds | 机器创建失败时间的直方图,标签与 gitlab_runner_autoscaling_machine_creation_duration_seconds 相同。 |
| gitlab_runner_autoscaling_machine_creation_phase_duration_seconds | 每个 Docker Machine 阶段的机器创建时间直方图。需要 FF_DOCKER_MACHINE_JSON_OUTPUT 功能标志。更多信息,请参阅[machine] 节。 |
| gitlab_runner_autoscaling_machine_states | 此提供商中每种状态的机器数量。 |
| gitlab_runner_autoscaling_max_growth_rate | 可以同时处于创建状态的机器最大数量(0 = 无限制)。在预热期间,它会提高到预热目标,直到首次机器创建失败,因此仪表板会在每次发布时看到阶跃,并在云提供商资源不足时回落。 |
| gitlab_runner_autoscaling_warmup | 当 Runner 处于预热状态时为 1,否则为 0。此指标及以下两个 gauge 仅对启用了预热的 Runner 报告。 |
| gitlab_runner_autoscaling_warmup_ready_seconds | 从预热开始到池达到就绪阈值所经过的秒数。在达到之前不存在。 |
| gitlab_runner_autoscaling_warmup_timed_out | 如果预热在池达到就绪阈值之前结束,则为 1,否则为 0。 |
| gitlab_runner_concurrent | concurrent 设置的值。 |
| gitlab_runner_errors_total | 捕获的错误数量。此指标是一个跟踪日志行的计数器。该指标包含 level 标签。可能的值是 warning 和 error。如果您计划包含此指标,那么在观察时请使用 rate() 或 increase()。换句话说,如果您注意到警告或错误的速率在增加,这可能表明存在需要进一步调查的问题。 |
| gitlab_runner_jobs | 显示正在执行的作业数量(标签中有不同的范围)。 |
| gitlab_runner_job_duration_seconds | 作业持续时间的直方图。 |
| gitlab_runner_job_queue_duration_seconds | 表示作业排队持续时间的直方图。 |
| gitlab_runner_acceptable_job_queuing_duration_exceeded_total | 统计作业超过配置的排队时间阈值的次数。 |
| gitlab_runner_job_stage_duration_seconds | 表示每个阶段作业持续时间的直方图。此指标是一个高基数指标。更多信息,请参阅高基数指标部分。 |
| gitlab_runner_jobs_total | 显示执行的作业总数。 |
| gitlab_runner_job_execution_mode_total | 显示按模式(steps 或 traditional)和执行器统计的执行作业总数。 |
| gitlab_runner_job_router_circuit_breaker_state | Job Router 断路器的状态(0 = 关闭,1 = 打开,2 = 半开)。 |
| gitlab_runner_job_router_circuit_breaker_trips_total | Job Router 断路器跳闸打开的次数。 |
| gitlab_runner_job_router_discovery_cache_events_total | Job Router 发现缓存查找次数,按 result(hit 或 miss)分区。 |
| gitlab_runner_job_router_fallbacks_total | 从 Job Router 回退到直接轮询极狐GitLab 的作业请求数量,按 reason(no_discovery、breaker_open、dial_failed、breaker_tripped 或 router_disabled)分区。 |
| gitlab_runner_job_router_get_job_duration_seconds | Runner 侧 Job Router GetJob 请求持续时间的直方图,按 runner、system_id 和 result(job、no_job 或 error)分区。 |
| gitlab_runner_job_router_get_job_requests_total | Runner 侧 Job Router GetJob 请求数量,按 runner、system_id 和 gRPC 状态 code(OK、ResourceExhausted 表示请求被限流、Unavailable 等)分区。 |
| gitlab_runner_limit | limit 设置的当前值。 |
| gitlab_runner_request_concurrency | 当前针对新作业的并发请求数。 |
| gitlab_runner_request_concurrency_exceeded_total | 超过配置的 request_concurrency 限制的请求数量。 |
| gitlab_runner_version_info | 一个常量值为 1的指标,由不同的构建统计字段标记。 |
| process_cpu_seconds_total | 用户和系统 CPU 总耗时(秒)。 |
| process_max_fds | 打开文件描述符的最大数量。 |
| process_open_fds | 打开文件描述符的数量。 |
| process_resident_memory_bytes | 常驻内存大小(字节)。 |
| process_start_time_seconds | 进程启动时间,以自 Unix 纪元起的秒数衡量。 |
| process_virtual_memory_bytes | 虚拟内存大小(字节)。 |
| process_virtual_memory_max_bytes | 可用虚拟内存的最大量(字节)。 |
在极狐GitLab Runner 19.4 及更高版本中,gitlab_runner_autoscaling_machine_creation_duration_seconds 和 gitlab_runner_autoscaling_machine_failed_creation_duration_seconds 具有 target_zone、target_region、 target_project 和 target_machine_type 标签。将这些直方图视为单个 序列的查询必须先进行聚合,例如 histogram_quantile(0.95, sum by (le) (rate(gitlab_runner_autoscaling_machine_creation_duration_seconds_bucket[5m])))。 无法读取 Docker Machine 状态的机器其标签值为空。
Grafana 仪表板配置提示
在这个公共代码仓库中,您可以找到我们用于在 GitLab.com 上运维 Runner 集群的 Grafana 仪表板的源代码。
我们为 GitLab.com 跟踪大量指标。作为大型云端 CI/CD 提供商,我们需要从许多不同的视角观察系统,以便调试问题。在大多数情况下,私有化部署的 Runner 集群不需要跟踪我们为 GitLab.com 跟踪的那么多指标。
仪表板生成流程
Grafana 只接受 JSON 格式,因此您必须将 jsonnet 文件转换为 JSON。
runbooks 代码仓库仅包含适用于 GitLab 基础设施的自动化脚本。要为您自己的环境生成这些仪表板:
- 使用 jsonnet 配置语言(.dashboard.jsonnet 文件)创建仪表板。
- 使用 jsonnet 库处理 jsonnet 文件以生成 JSON 输出。
- 将生成的 JSON 文件上传到 Grafana(使用 API 或 UI)。
可用的 Runner 仪表板
以下是您应该用来监控 Runner 集群的几个基本仪表板:
Runner 上启动的作业:
- 查看选定时间间隔内 Runner 集群上执行的作业总数概览。
- 查看使用趋势。您至少应每周分析一次此仪表板。
- 将此数据与作业持续时间等指标关联,以确定是否需要进行配置更改或容量升级,从而满足您的 CI/CD 作业性能 SLO。
作业持续时间:
- 分析 Runner 集群的性能和扩缩情况。
- 识别性能瓶颈和优化机会。
Runner 容量:
- 查看正在执行的作业数量除以 limit 或 concurrent 的值。
- 确定是否仍有容量执行更多作业。
- 根据利用率趋势规划容量升级。
其他仪表板包括:
- 主仪表板(main.dashboard.jsonnet):Runner 基础设施和 HAProxy 指标概览。
- 业务指标(business-stats.dashboard.jsonnet):作业统计、已完成作业分钟数和 Runner 饱和度。
- 自动扩缩算法(autoscaling-algorithm.dashboard.jsonnet):自动扩缩行为和机器状态的可视化。
- 排队概览(queuing-overview.dashboard.jsonnet):作业队列深度和等待时间。
- 请求并发(request-concurrency.dashboard.jsonnet):并发请求分析。
- 部署(deployment.dashboard.jsonnet):与部署相关的指标。
- 事件仪表板:用于排查自动扩缩、数据库、应用程序和 Runner Manager 问题的专用仪表板。
每个仪表板都在源 jsonnet 文件中包含描述和上下文,以说明正在显示哪些指标。
模板变量
仪表板使用 Grafana 模板变量,以便在不同上下文中创建可复用的仪表板模板:
- 环境:例如 production、staging、development。
- 阶段:例如 main、canary。
- 类型:例如 ci、verify。因用例而异。
- 分片:可选。用于分布式 Runner 部署。
实施这些仪表板的组织必须调整这些变量,以匹配其自身的环境结构。导入后在 Grafana 仪表板设置中更新这些变量。
支持的 Runner
这些仪表板适用于所有极狐GitLab Runner 执行器类型:
- Kubernetes
- Shell
- VM (Docker Machine)
- Windows
指标收集与执行器无关,并适用于所有 Runner 集群类型。
自定义仪表板
要针对您的环境修改仪表板:
-
编辑 dashboards/ci-runners/ 目录中的 .dashboard.jsonnet 文件。
-
使用 Grafonnet 库语法(基于 jsonnet 构建)。
-
使用 playground 测试更改:
shell./test-dashboard.sh dashboards/ci-runners/your-dashboard.dashboard.jsonnet -
使用 ./generate-dashboards.sh 重新生成并部署。
在 Kubernetes 上监控 Runner 的注意事项
对于托管在 OpenShift、EKS 或 GKE 等 Kubernetes 平台上的 Runner 集群,请使用不同的方法来设置 Grafana 仪表板。
在 Kubernetes 上,Runner CI/CD 作业执行 Pod 可能会频繁创建和删除。在这些情况下,您应计划监控 Runner Manager Pod,并可能需要实施以下内容:
- Gauge:显示来自不同来源的同一指标的聚合值。
- Counter:在应用 rate 或 increase 函数时重置计数器。
高基数指标
某些指标由于基数高,在摄取和存储时可能会占用大量资源。当指标包含具有许多可能值的标签时,就会出现高基数,从而导致大量唯一的时间序列数据点。
为优化性能,此类指标默认不启用,可以通过 FF_EXPORT_HIGH_CARDINALITY_METRICS 功能标志进行切换。
高基数指标列表
-
gitlab_runner_job_stage_duration_seconds:衡量各个作业阶段的持续时间(秒)。 此指标包含 stage 标签,该标签可以具有以下预定义值:
- resolve_secrets
- prepare_executor
- prepare_script
- get_sources
- clear_worktree
- restore_cache
- download_artifacts
- after_script
- step_script
- archive_cache
- archive_cache_on_failure
- upload_artifacts_on_success
- upload_artifacts_on_failure
- cleanup_file_variables
此外,此列表可能包含自定义的用户定义步骤,例如 step_run。
管理高基数指标
您可以使用 Prometheus relabel 配置来移除不必要的标签值或整个指标,从而控制和减少基数。
移除特定阶段的示例配置
以下配置会移除 stage 标签中值为 prepare_executor的任何指标:
yaml1scrape_configs: 2 - job_name: 'gitlab_runner_metrics' 3 static_configs: 4 - targets: ['localhost:9252'] 5 metric_relabel_configs: 6 - source_labels: [__name__, "stage"] 7 regex: "gitlab_runner_job_stage_duration_seconds;prepare_executor" 8 action: drop
仅保留相关阶段的示例
以下配置仅保留 step_script 阶段的指标,并完全丢弃其他指标:
yaml1scrape_configs: 2 - job_name: 'gitlab_runner_metrics' 3 static_configs: 4 - targets: ['localhost:9252'] 5 metric_relabel_configs: 6 - source_labels: [__name__, "stage"] 7 regex: "gitlab_runner_job_stage_duration_seconds;step_script" 8 action: keep