在之前的文章中,我介绍了如何使用 GitHub Webhooks 在 ClickHouse 中构建一个包含所有 GitHub Actions 数据的表。我们为 ClickHouse 组织这样做,以提供关于工作流作业内部队列的重要指标。
仅仅拥有这些数据而不加以利用将是对宝石数据的巨大浪费,因此几个月前,这些数据被用于实现一个 lambda 函数,以根据需要快速扩容和缩容我们的 worker。这提高了我们作业启动的响应速度,对计划测试的增加做出反应,并在工作负载较低时节省了计算资源。让我们讨论一下我们是如何实现这一点的!
想法
我们的数据库中包含了工作流作业创建、启动或完成的所有事件。考虑一下之前文章中的这个查询,它返回了自托管 GitHub Runner 的当前 ClickHouse 队列大小。
SELECT last_status, count() AS queue, labels FROM ( SELECT argMax(status, updated_at) AS last_status, labels, id, html_url FROM default.workflow_jobs WHERE has(labels, 'self-hosted') AND (started_at > (now() - toIntervalHour(3))) GROUP BY ALL HAVING last_status != 'completed' ) GROUP BY ALL ORDER BY labels ASC, last_status ASC
了解这一点使我们能够主动扩展 runner 以满足需求,或缩减以释放不必要的资源。
新的期望容量是根据当前 runner 的数量以及正在进行和排队的作业数量计算得出的。如果存在不足,我们将按比例增加容量(通常为不足量 / 5)。对于不必要的储备,我们快速缩减组(储备量 / 2)。
旧系统
在 AWS 中触发扩容/缩容的官方推荐方法是将 CloudWatch 警报分配给 Auto-Scaling Groups (ASG)。因此,每当警报处于警报状态时,ASG 都会添加或删除一些实例。
我们过去使用 GitHub runner API 监控每个 ASG 中有多少实例处于繁忙状态。如果超过 97% 的 runner 繁忙持续 5 分钟,则会添加另一个 runner。对于缩容,规则是低于 70%。
该系统过去非常被动和迟钝。要预热拥有 50 多个 runner 的组,需要几个小时。
改进和统计
切换到新系统后,我们既实现了更快的作业启动,又节省了作业完成后计算时间。您可以在图表中看到它对 runner 的影响
旧系统
新系统
我们可以看到在新系统中,“繁忙”和“活跃 Runner”之间的相关性更高,表明已配置的 worker 得到了更充分的利用。此处使用的代码都在我们的存储库中提供。希望其他人也能做出类似的改进和节省!