Dewei Zhai

2026-07-27

我把数据平台从 Databricks 迁到单机 VM 后,月成本下降了 95%

一次个人数据平台迁移复盘:AI Agent 放大了探索式开发的成本风险,我如何用更小的运行面缩短反馈周期。

这是一篇技术复盘。为保护业务信息,文中省略了绝对成本、数据规模、 环境身份和具体资源配置。

过去一段时间,我把一个数据平台的日常运行面从 Databricks + ADF 迁到了 单机 VM。新的运行环境由 Airflow、DuckDB/Polars 和 DuckLake 组成, 数据文件继续保存在对象存储中。

迁移完成后,这个平台的月度运行成本下降了约 95%。

这个数字很醒目,真正促使我动手的原因发生在开发过程中。开始大量使用 AI Agent 后,我写代码和尝试新方案的速度明显提高,探索式工作在日常 开发中的比重也随之上升。原有平台的反馈速度和计费方式,逐渐跟不上新的 开发节奏。

问题:AI Agent 加快了试错,也放大了费用风险

数据开发天然需要反复尝试。工程师会抽取一批数据,调整转换逻辑,重跑 任务,检查边界情况,然后继续修改。AI Agent 参与以后,同样的循环可以 更快发生,甚至连续执行多轮。

这带来了一个很现实的问题:我很难仅靠提示词和代码评审,确保 Agent 每次都能正确估算扫描量、计算规格和重试次数。一次普通的数据探查可能 触发昂贵的 Databricks 计算;任务失败后,自动重试还会继续累积费用。 开发速度提高了,月度账单的不确定性也跟着上升。

与此同时,我查看了实际作业窗口和资源利用率。日常 ETL 的规模相对 稳定,一台配置合适的机器已经可以在要求的时间内完成。原平台提供的弹性 计算和多租户能力很强,但这条链路在当前阶段很少真正用到它们。

当时的运行路径大致如下:

ADF → Databricks / Unity Catalog → object storage

每个组件都有明确用途。落到一次日常修改上,开发者仍要跨过编排器、 计算平台、权限、镜像、代码仓库和流水线,才能知道代码在真实环境里能否 运行。

问题:CI/CD 把一次验证拉得太长

一处小改动经常要经历这样的过程:

修改代码 → 提交 → 等待 CI/CD → 部署远程环境 → 运行任务 → 查看日志

本地测试通过后,云端仍可能因为依赖包、服务身份、镜像版本或权限配置 失败。开发者需要修复问题,再走一遍相同流程。

代码生成速度提升以后,等待开始占据更多时间。AI Agent 可以在几分钟内 完成修改,人和 Agent 却要等远程流水线给出下一条有效信息。一个小时里 能够完成多少次真实验证,逐渐成为开发效率的主要限制。

这也解释了为什么单纯提高 CI 并发没有解决问题。流水线仍然承担了大量 探索阶段的验证工作,每一次试错都要经过完整的远程路径。

对策:把日常运行面收敛到一台 VM

我先根据历史作业数据确认单机能够承载平台的日常负载,然后将运行路径 调整为:

Airflow + DuckDB/Polars(VM)

DuckLake catalog:关系型元数据数据库 + 对象存储中的 Parquet

Airflow 负责编排,DuckDB/Polars 执行转换。DuckLake 将 catalog 和 snapshot 元数据保存在关系型数据库中,Parquet 数据继续保存在对象存储中。迁移调整了计算、 调度和开发反馈所在的位置,没有把数据绑在 VM 的本地磁盘上。

运行环境由 Docker Compose 描述。本地开发和 VM 使用相同的容器定义、 依赖和服务关系。工程师与 AI Agent 都可以直接读取 Compose、Dockerfile、 requirements、DAG 和测试,判断代码最终会在哪个环境中运行。

这一步缩短了大量排错路径。依赖缺失可以在本地复现,镜像变化可以直接 验证,任务日志也集中在我能够直接检查的运行面里。真实数据验证仍然在受控 环境中进行,宿主机、网络和 RBAC 继续由基础设施代码管理。

对策:让探索和正式交付使用不同节奏

我保留了 PR、CI、review 和人工授权部署,用它们保证正式交付的审计链。 同时增加了一条受控的快速验证路径:

本地 Compose 验证

共享验证环境运行真实输入

修复并重复

PR / CI / review

授权部署

快速路径只能操作应用和任务,无法修改宿主机、网络或权限边界。它与正式 交付复用同一套容器和部署逻辑,避免两条路径长期演变成两套环境。

这样一来,探索阶段可以快速获得真实反馈,正式交付仍然保留可追溯记录。 AI Agent 的价值也更容易兑现:它完成一次修改后,很快就能看到运行结果, 继续修正下一处问题。

效果:成本可预测,反馈周期也缩短了

迁移后,这个平台的月度运行成本下降约 95%。原先随计算时间波动 的主要支出,变成了一台 VM 的固定容量成本。Agent 多做几次数据探查或 验证,也不会突然启动一组高规格集群。

工程上的变化同样直接:

  • 本地环境能够复现更多运行问题;
  • 一次修改无需先穿过完整 CI/CD 才能获得真实反馈;
  • 依赖、镜像、任务和日志集中在一个可检查的运行面;
  • AI Agent 可以执行更多验证,费用上限依然清楚。

这次迁移也减少了排错时的猜测。过去看到一个云端失败,我需要依次确认 代码、镜像、身份、权限和平台状态。现在多数问题可以从容器定义、任务日志 和部署记录中直接定位。

这套方案有明确边界

单机 VM 是一个故障域。我把 Parquet 文件留在对象存储中,为 catalog 和运行元数据建立备份,并确保容器和配置可以从版本化工件重建。任务尽量 保持幂等,以便故障后安全重跑。

这些措施支持恢复,无法提供零中断服务。业务开始要求极低 RTO/RPO、持续 可用或更高并发时,就需要增加实例、故障切换和相应的运行演练。

扩展路径也保留了下来。数据使用开放格式,计算环境已经容器化。作业窗口、 资源利用率或并发量持续接近单机上限时,可以先升级 VM,再拆分 worker, 随后进入多 VM 或 Kubernetes。每一步都由实际运行数据触发。

最后

这次迁移给我的判断标准很具体:先看作业窗口、资源利用率、并发需求、 恢复目标和团队维护能力,再决定平台需要多少能力。

对这个数据平台当前的工作负载而言,单机 VM 提供了足够的计算容量,也给 探索式开发设置了清楚的成本上限。我使用 AI Agent 的速度越快,这个上限 越有价值。

月成本下降 95% 是迁移最容易被看到的结果。更长久的影响,是我重新获得了 一个短而清楚的开发循环:修改、运行、看到结果,然后继续前进。


想聊聊?和我的助理辩一辩,或者给我留个言