跳转到主要内容
  • Snorkel AI 的 CI/CD 流水线为每个开放的拉取请求提供独立的 Lakebase Postgres 分支,这是生产数据的完整读写副本,可在不到一分钟内就绪,而此前需要 30 分钟以上甚至更久,因此他们一直无法为每个 PR 启用副本。
  • Lakebase 分支采用写时复制,因此在约 2.5 TB 的生产数据集上,100 个并发 PR 数据库只会为每个分支所改动的数据增加存储。分支过期(TTL)会在 PR 完成后自动清理每个分支,因此存储量始终接近生产数据大小加上活跃 PR 的改动量。
  • 私有连接和 Okta SSO 支持提供受治理且安全的环境

问题:基于生产数据进行测试不应耗时超过 30 分钟

Snorkel AI 为 AI 团队构建数据开发工具,其用户包括专家数据标注员和前沿模型提供商。在这个具体用例中,Snorkel 通过基于 Kubernetes 构建的 CI 流水线交付代码。每个开放的拉取请求以及临时提交都会获得自己的临时 Kubernetes 命名空间(“PR 命名空间”)。开发者将分支部署到该命名空间,并在合并前运行完整测试套件。

这些测试在针对真实数据运行时最为有用。Snorkel 的生产数据库是一个 Amazon Aurora PostgreSQL 集群。为每个 PR 命名空间提供该数据库的独立副本才是难点所在。恢复一个副本每个环境大约需要 20 分钟,当开发者全天不断提交 PR、合并队列每次运行都需要全新环境时,这太慢了。其他替代方案(共享预发布数据库、裁剪后的测试夹具或合成数据)会重新带来类生产测试本应解决的问题:测试相互干扰、模式过期,以及只有在真实数据形态下才会出现的缺陷。

成功标准

如果满足以下标准,Snorkel 就会认为 Lakebase 在 CI/CD 场景中是成功的:

  • 快速配置: 新的 PR 分支在 60 秒内就绪(p95)。
  • 规模: 峰值时约 100 个并发 PR 分支,每个分支都有独立的读写能力。
  • 兼容性: 现有应用和 CI 套件通过标准 Postgres 在 Lakebase 上运行,性能与 Aurora 相当,并支持大型 JSONB/LOB 列。
  • 数据新鲜度: 通过持续的 DMS 复制,main 分支与生产 Aurora 的差距保持在约 2 分钟以内。
  • 安全性: 生产数据始终位于私有网络中,绝不经过公共互联网;开发者使用 Okta SSO 登录,CI 流水线以服务主体身份进行身份验证。

为什么数据库分支适合 CI/CD

Lakebase 是 Databricks 的无服务器 Postgres 数据库。其存储与计算分离,并支持分支:你可以像创建 Git 分支一样,从任意时间点创建数据库的一个新的、隔离的、可写分支。

分支采用写时复制。创建分支是元数据操作,因此创建分支时不会复制任何数据。新分支与其父分支共享存储页,只有该分支修改的页才会作为新存储写入。对于 CI 而言,这意味着:

  • 创建分支只需几秒,而不是几分钟。 它不依赖于数据库的大小。
  • 存储量随每个分支所做的改动增长,而不是随数据库大小增长。 Snorkel 的每个 PR 分支在约 1 TB 的基础数据之上写入约 5 至 10 GB 的改动。
  • 计算资源按分支分配并可缩减至零。 每个分支都有自己的自动扩缩计算资源,在 CI 运行间隙可缩减至零。即使配置了 100 个分支,Snorkel 预计也只有约 20 至 30 个分支会同时处理流量,每个分支峰值时约每秒 5 次查询。

架构

image1.png

1. 在 main 分支上保留一份最新的生产数据副本。 Lakebase 是标准 Postgres,因此无需自定义工具即可作为 AWS DMS 的目标。Snorkel 将一个 DMS 任务指向其生产 Aurora 数据库,并将其复制到 Lakebase 项目的 main 分支:先进行全量加载,然后进行持续的变更数据捕获,使 main 与生产数据的差距保持在约 2 分钟以内。完整 LOB 模式会传输 10 至 20 MB 的 JSONB 值。该团队已经在运行 DMS,因此无需构建或维护新的复制流水线。main 分支是每个 PR 分支的起点,即“黄金副本”。

2. 在 PR 打开时创建分支。 当开发者打开 PR 时,CI 流水线会调用 Lakebase API 从 main 创建分支,为其设置过期时间,并将该分支的连接详细信息传递给 PR 命名空间。分支在不到一分钟内就绪。

3. 针对真实数据运行测试。 PR 命名空间中的应用通过标准 Postgres 连接到其分支。测试可以运行迁移、写入数据并更改模式,而不会影响生产环境、main 或任何其他 PR。

4. 在 PR 关闭或测试通过时删除分支,并以 TTL 作为兜底。 当 PR 被合并或关闭时,流水线会删除该分支。如果该清理步骤未运行,分支会在其 TTL 到期时自行过期。

安全性:私有网络以及面向人员和流水线的身份

两项安全要求排除了其他选项,因此值得单独用一节来说明。

私有连接。 生产数据通过私有网络而非公共互联网从 Aurora 传输到 Lakebase,再从 Lakebase 传输到 CI 集群。

身份。 Snorkel 有两类数据库用户:交互式连接以调试 PR 环境的开发者,以及无需人工参与即可运行的 CI 流水线。Okta SSO 围绕交互式浏览器登录构建,因此我们按用户类型拆分设计:

  • 开发者: Okta 与 Databricks 账户联合,用户通过 SCIM 进行配置。开发者使用其常用的 Okta 身份登录。
  • CI 流水线: 每个 PR 命名空间以 Databricks 服务主体(按团队或按仓库限定范围)运行,同样通过 SCIM 进行配置。PR Pod 使用服务主体的凭据,通过 Databricks SDK 获取短期的 Lakebase OAuth 令牌,并在长时间测试运行期间刷新这些令牌。CI 中不存在长期有效的数据库密码。
  • 审计: Postgres 审计日志会记录每个查询的服务主体身份,因此每个查询都可以追溯到运行它的流水线。

为什么写时复制和分支过期能让 CI 保持快速且低成本

Lakebase 的两项功能使这一模式能够大规模运行:写时复制分支和分支过期(TTL)。

image3.png

写时复制让分支瞬间创建。 新分支不复制任何数据。它指向父分支已有的存储页,只有该分支修改过的页才会作为新存储写入。从约 1 TB 的生产副本创建分支所需的时间,与从 1 GB 数据库创建分支差不多:只需几秒,而不是完整恢复所需的约 20 分钟。每个 PR 命名空间都能立即获得自己独立的、可写的生产副本。

写时复制让分支成本低廉。 每个分支与 main 共享大部分数据,因此存储增长取决于每个分支所做的更改,而不是数据库的大小。对 Snorkel 来说,每个 PR 分支在共享基础之上大约增加 5 到 10 GB。计算资源按分支分配,并在空闲时缩容到零,因此只有正在运行测试的分支才会使用计算资源。

分支过期让长期成本保持低廉。 当分支生命周期较短时,写时复制的节省效果最大。分支会保留其创建时存在的数据版本。随着 DMS 持续用生产变更更新 main,长期存在的分支会一直持有那些较旧的页,因此其使用的存储会随时间增长。为每个 CI 分支设置 TTL,意味着每个分支在其 PR 完成后会自动删除。这使存储量接近生产基础数据的大小加上活跃 PR 的更改量。

同样的模式也适用于 AI 代理

PR 命名空间并不是唯一需要生产数据一次性副本的工作负载。编写 SQL、运行迁移或更改数据的 AI 代理也需要一个安全的试验场所,而写时复制分支正好提供了这样的场所。

每个代理任务一个分支。 每次代理运行都会获得 main 的一个独立分支。代理可以读取真实数据、写入数据,甚至更改模式,而不会影响生产环境或任何其他代理的工作。无论数据库多大,创建分支都只需几秒,因此为每个任务创建一个分支是切实可行的。

多个代理并行运行。 存储只会随每个分支更改的页而增长,并且每个分支的计算资源在空闲时会缩容到零。并行运行数十个代理的成本大约相当于它们所做的更改量,而不是数据库的数十个副本。

审查更改,或将其丢弃。 团队可以在将任何内容应用到生产环境之前,检查代理在其分支上所做的更改。如果结果不正确,他们可以删除该分支,无需回滚任何内容。

TTL 会清理代理留下的分支。 代理可能会创建大量短生命周期分支。为每个分支设置过期时间会自动删除被遗弃的分支,就像 TTL 清理 CI 分支一样。

为代理提供限定范围的身份。 与 CI 流水线一样,代理可以以服务主体身份运行,并使用短期 OAuth 令牌,因此代理运行的每个查询都可以在审计日志中追溯。

结果

  • 配置时间: 之前超过 30 分钟,使用 Lakebase 后不到 60 秒 [VERIFY p95 measured]
  • 规模: 设计目标是在约 2.5 TB 的生产数据集上支持约 100 个并发 PR 分支
  • 兼容性: CI 套件在 Lakebase 上运行,与 Aurora 相比“没有重大兼容性问题”/性能相当
  • 采用情况: 推广到各团队的 60 到 70 名开发者
  • 开发者评价: “以前我们必须物理复制数据,这些复制任务要花费数小时,并且经常在各种 CI 平台(github actions、circle ci 等)上遇到网络和其他瓶颈。我们在寻找一种解决方案,在数据离开我们的 VPC 时也能满足我们的安全和合规要求”

在 CI/CD 中使用 Lakebase 分支的最佳实践

  1. 每个 PR 一个分支,从持续同步的 main 分支创建。
  2. 始终设置 TTL。 将过期视为必需项,而非可选项。使其与 PR 或测试运行通常持续的时间相匹配。
  3. 创建新分支,而不是保留旧分支。 如果 PR 需要更新的数据,请从 main 创建新分支。这只需几秒钟。
  4. 让计算资源缩容到零。 大多数已配置的分支在任何给定时刻都处于空闲状态。
  5. 为流水线使用服务主体和短期 OAuth 令牌, 人员则使用 SSO。
  6. 监控每个分支的存储使用情况 以便及早发现长期存在的分支。

准备好为每个拉取请求提供其专属的类生产数据库了吗? 开始使用 Lakebase 并阅读分支文档,在 CI 流水线中设置分支过期。

相关标签:

技术

在收件箱中获取最新文章

订阅我们的博客,最新文章将直接发送到您的收件箱。

注册

查看所有博客 slice-start id="_gatsby-scripts-1" slice-end id="_gatsby-scripts-1"