极狐 GitLab

规划并运维实例或群组 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 时可以并发运行的作业数量。
  • 限制: 设置一个 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。

toml
1concurrent = 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,那么该主机最多可以同时运行三个作业。

toml
1concurrent = 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 执行器#

使用 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_totalAPI 请求总数,按 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_concurrentconcurrent 设置的值。
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_stateJob Router 断路器的状态(0 = 关闭,1 = 打开,2 = 半开)。
gitlab_runner_job_router_circuit_breaker_trips_totalJob Router 断路器跳闸打开的次数。
gitlab_runner_job_router_discovery_cache_events_totalJob 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_secondsRunner 侧 Job Router GetJob 请求持续时间的直方图,按 runner、system_id 和 result(job、no_job 或 error)分区。
gitlab_runner_job_router_get_job_requests_totalRunner 侧 Job Router GetJob 请求数量,按 runner、system_id 和 gRPC 状态 code(OK、ResourceExhausted 表示请求被限流、Unavailable 等)分区。
gitlab_runner_limitlimit 设置的当前值。
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 基础设施的自动化脚本。要为您自己的环境生成这些仪表板:

  1. 使用 jsonnet 配置语言(.dashboard.jsonnet 文件)创建仪表板。
  2. 使用 jsonnet 库处理 jsonnet 文件以生成 JSON 输出。
  3. 将生成的 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 集群类型。

自定义仪表板#

要针对您的环境修改仪表板:

  1. 编辑 dashboards/ci-runners/ 目录中的 .dashboard.jsonnet 文件。

  2. 使用 Grafonnet 库语法(基于 jsonnet 构建)。

  3. 使用 playground 测试更改:

    shell
    ./test-dashboard.sh dashboards/ci-runners/your-dashboard.dashboard.jsonnet
  4. 使用 ./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的任何指标:

yaml
1scrape_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 阶段的指标,并完全丢弃其他指标:

yaml
1scrape_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