Ohhnews

分类导航

$ cd ..
Jetbrains Blog原文

TeamCity推出Warm Agents插件,解决构建代理等待延迟

#teamcity#warm agents#持续集成#云代理#插件

当只想让 PR 测试跑起来时,却要等待“正在等待启动代理”,这是一种特别恼人的体验。最让人难受的是,一个一分钟就能完成的快速构建在队列里等了十分钟,只为了那台缓慢的 Windows 云实例启动起来。

Warm Agents 插件就是我们应对这一延迟的答案。

借助该插件,TeamCity 会为指定的云镜像维持目标数量的空闲且已预启动的代理。一旦空闲代理数量低于你设定的目标,TeamCity 会立即预配一个新的代理——确保构建一到达就能启动。该插件适用于 TeamCity 支持的任何云提供商。

只有一件事需要提前做好预算。每个运行中的预热代理都会占用一个构建代理许可证,而且空闲的云实例仍会向你的云提供商产生费用。预热代理是用成本换取更低的延迟,因此请选择一个能反映你实际想换回多少排队时间的目标数量。

先决条件

  1. TeamCity 2024.12.3 或更高版本。
  2. 项目中已配置云配置文件和云镜像。
  3. 项目中已授予“管理项目的代理云配置文件”权限。
  4. Warm Agents 插件已安装并启用。

要开始使用该插件,请转到 管理 | 插件,点击 浏览插件仓库,并在 JetBrains Marketplace 列表中找到 Warm Agents。安装后启用它。

插件开始运行后,通过 REST API 调用来配置预热代理。本文演示如何使用 teamcity-cli 来完成这些操作,这是从终端管理服务器最方便的方式。如果你更想直接调用这些端点,请参阅我们的 REST API 快速入门指南以及仓库中的示例请求。

设置

要让某个云镜像始终保持十个空闲代理就绪,请运行:

$ bash
teamcity api '/app/<projectExternalID>/<cloudProfileID>/<cloudImageName>/warmAgents?target=10' -X PUT

要停止为某个镜像维持预热代理,请传入 target=0。

如果你的云镜像配置了运行代理总数的硬性上限,TeamCity 会遵守该上限,不过仍然可以将目标值设置为更高的值。

要验证配置,请调用:

$ bash
teamcity api '/app/<projectExternalId>/warmAgents?includeSubprojects=<true|false>'

或者,导航到 项目设置 | 集成 | Warm Agents:

[LOADING...]

TeamCity 会监控该镜像的空闲代理数量,并在数量低于目标时启动新实例。请注意,实例会分批启动,批次之间会有短暂延迟,因此较高的目标值可能需要一段时间才能补满。

要查找上面用到的 ID,请使用 teamcity-cli 或 REST API:

  • teamcity project list
  • teamcity project cloud profile list --project <projectExternalID>
  • teamcity project cloud image list --project --profile
    • 只使用名称:teamcity-linux-aws-a (lt-0cd4ecf32d77770a9) -> teamcity-linux-aws-a

或者,在你的服务器上打开云配置文件页面,从 URL 中读取 ID:在类似 my.teamcity.com/admin/editProject.html 的地址中查找 projectId=My_Project 和 profileId=amazon-123。

高级用法

对预热代理的需求很少保持平稳。让代理整夜保持预热可能会白白消耗资源却毫无回报,因此该功能就是为频繁调整目标值而构建的。TeamCity 会动态获取新的目标值,并通过启动更多或更少的代理来进行调整。更改目标值永远不会影响已经在运行的代理——当你缩减规模时,TeamCity 不会强制停止实例。云镜像的“空闲超时”配置仍然适用,不过 TeamCity 可能会重启一些刚刚下线的实例,以维持代理数量。

定时调度是显而易见的应用场景。配置一个带有定时触发器的构建,在夜间降低目标值,并在早晨恢复。使用 Kotlin DSL:

$ kotlin
// define parameters like warmAgents.token, warmAgents.projectId and so on...

steps {

    script {

        scriptContent = """

            #!/bin/bash

            # update the target to the parameter value

            curl --oauth2-bearer %warmAgents.token% -XPUT ${DslContext.serverUrl}/app/%warmAgents.projectId%/%warmAgents.profileId%/%warmAgents.imageName%/warmAgents?target=%warmAgents.target%

        """.trimIndent()

    }

}

将 warmAgents.token 存储为密码类型参数,以便该值在构建日志中保持掩码显示。

以及触发器:

$ kotlin
// schedule trigger to scale warm agents up to 2 each morning

schedule {

    branchFilter = "+:*"

    triggerBuild = always()

    withPendingChangesOnly = false

    schedulingPolicy = daily {

        hour = 8

    }

    buildParams {

        param("warmAgents.target", "2")

    }

}

再添加一个用于晚间的触发器,设置 target=0。完整示例请参见此仓库。

昼夜拆分是常见情形,但你的工作流可能需要不同的形态。要查看需求实际如何波动,该插件会暴露一小组指标:

$ bash
teamcity api '/app/projectMetrics?projectId=<projectExternalID>' | grep 'warmAgents'

在多节点设置中,添加 X-TeamCity-Node-Id-Cookie=<main-node-id> cookie,将请求固定到负责收集指标的主节点。

该插件会针对每个已配置的云镜像计算利用率和饱和度指标,展示代理的繁忙程度以及它们跟上队列的情况。指标以 Prometheus 格式输出,因此你可以随时间抓取它们,并查看需求何时达到峰值。这里有一份最小化的 Prometheus 配置示例。

告诉我们你的想法

我们很想了解该功能对你来说效果如何,以及你的使用场景是什么样的。欢迎在下方评论区或原始功能请求中分享你的反馈;如果你感兴趣,也可以看看我们的未来改进计划。