一次AI误删生产数据库的完整复盘与教训: 备份不够,确保恢复路径

作者在使用Claude Code AI agent协助Terraform迁移网站时,因未正确管理Terraform状态文件,导致agent执行terraform destroy意外删除了生产数据库及所有自动快照。

事件时间线

2月26日,星期四

  • ~晚上10:00:开始使用 Terraform 部署网站更改,但我忘记使用状态文件,因为它在我旧电脑上。
  • ~晚上11:00:一个 Terraform 自动批准命令意外地摧毁了所有生产基础设施,包括 Amazon RDS。我后来发现所有快照也被删除了,于是创建了一个 AWS 支持工单。

2月27日,星期五

  • ~凌晨12:00:升级到 AWS Business 支持以获得更快的响应时间。
  • ~凌晨12:30:AWS 支持确认他们那边有一个快照。
  • ~凌晨1:00-2:00:与 AWS 支持进行了电话沟通,问题被升级到他们的内部团队进行恢复。
  • 白天:实施了预防措施,包括设置备份 Lambda 函数、启用删除保护、创建 S3 备份,以及将 Terraform 状态迁移到 S3。
  • ~晚上10:00:数据库完全恢复,仅 courses_answer 表就包含了 1,943,200 行数据。平台重新上线。

灾难是如何发生的

复用现有的 Terraform 配置

我已经有 Terraform 在管理另一个项目的生产基础设施——一个用于 DataTalks.Club Zoomcamps 的课程管理平台。我没有为 AI Shipping Labs 创建单独的配置,而是将其添加到现有配置中以节省少量费用。

Claude 试图劝我不要这样做,说我应该分开管理,但我想省一点钱,因为我的设置是将所有内容都放在一个 VPC 内,所有资源都在私有网络中,并有一个堡垒机来托管机器。

节省的费用并不多,大概每个月 5-10 美元,但我想,何必再要一个 VPC,于是告诉它把所有东西都放在那里。这增加了复杂性和风险,因为这个网站的变更现在与其他基础设施的变更混在了一起。

第一个警告信号

我没有手动审查计划,而是让 Claude Code 运行 terraform plan,然后运行 terraform apply。第一个异常迹象是我看到一长串资源正在被创建。这毫无道理:基础设施明明已经存在。我们并不是在构建一个新环境。

我停止了 Claude 并问道:"为什么我们要创建这么多资源?" 代理的回答既直接又可怕:Terraform 认为什么都不存在。

但为什么呢?我最近换了一台新电脑,并且没有迁移 Terraform。当我运行 terraform plan 时,它认为不存在任何现有基础设施,我们是从零开始。

我迅速取消了 terraform apply,但一些资源已经被创建。

通过 AWS CLI 分析和删除重复资源

下一步是评估已创建的内容。我指示 Claude 使用 AWS CLI 分析环境,并识别哪些资源是新创建的,哪些是生产环境的一部分。我想只删除新创建的重复资源,保持现有基础设施不变。

助手报告说它已经使用 AWS CLI 识别了重复资源,并正在删除它们。这听起来没问题。

在进行这次清理的同时,我去找了旧电脑,归档了 Terraform 文件夹(包括状态文件),并将其传输到新机器上。我以为清理也已经完成了,于是将 Terraform 归档文件指向了代理,以便它可以用它来将新创建的资源与已归档的资源进行比较。

使用 terraform destroy 删除

代理一直在删除文件,到某个时候,它输出:"我无法做到。我将执行 terraform destroy。由于这些资源是通过 Terraform 创建的,通过 Terraform 销毁它们会比通过 AWS CLI 更干净、更简单。"

这看起来合乎逻辑:如果 Terraform 创建了资源,那么 Terraform 应该移除它们。所以我没有阻止代理运行 terraform destroy。销毁命令完成了。在那一刻,我仍然相信我们只是在清理新创建的资源。

然后我检查了 DataTalks.Club Zoomcamps 的课程管理平台,发现它宕机了。我想:"这是什么情况?" 然后打开了 AWS 控制台进行调查。

数据库、VPC、ECS 集群、负载均衡器和堡垒机都不见了。整个生产基础设施被摧毁了。

当我问 Claude 数据库在哪里时,回答很直接:它已被删除。

实际发生了什么

实际情况是,我没有注意到 Claude 解压了我的 Terraform 归档文件。它用包含 DataTalks.Club 课程管理平台所有信息的旧状态文件替换了我当前的状态文件。

当 Claude 运行 terraform destroy 时,它摧毁的不仅是临时重复项,而是课程平台背后的真正基础设施,而不是它创建的状态文件。

寻找解决方案

1. 寻找备份

在发现生产基础设施消失后,我开始寻找备份。按理说应该有每日备份。

当时大约是晚上 11 点,我知道每晚凌晨 2 点会创建一个快照。我进入 RDS 控制台查看可用的快照,但没有看到任何快照。我再次检查了控制台,仍然一无所获。

接下来,我打开了 RDS 事件部分,看到备份确实在凌晨 2 点如预期般创建了。事件被列出,但点击后没有任何反应,快照无法访问。

当时我不确定备份是被删除了还是只是不可见。

2. 联系 AWS 支持

大约午夜时分,我提交了一个关于数据库被删除和备份丢失的支持工单。我联系了我的 AWS 联系人,但没指望这么晚能得到回复。

没有收到回复后,我注意到 Business 支持对生产事件提供一小时的响应时间,于是我进行了升级,这使我的云成本增加了大约 10%。

然后我创建了另一个包含所有必要细节的工单。支持人员在大约 40 分钟内回复了我。

3. AWS 支持发现了什么

AWS 支持确认我的数据库和所有快照确实都被删除了,这是我始料未及的。API 请求明确指示 AWS 删除所有内容。

他们在他们那边找到了一个我在控制台中看不到的快照。在我指出这一点后,他们建议进行电话沟通。

3. 与 AWS 通话

我们加入了一个电话会议,一起审查了情况。

他们尝试了在他们那端进行恢复。一段时间后,支持工程师说他需要内部上报。我们一直保持通话,等待他们调查。

在生产环境已经宕机的情况下,我开始用 Terraform 重建基础设施的其他部分。这进行得相对较快。我还利用这个机会简化了一些事情,例如将多个负载均衡器合并为一个。

我创建了一个新的空数据库实例,为可能的恢复做好准备。

通话持续了大约 40 到 60 分钟。最终,他们说需要更多时间,一旦有明确进展就会跟进。

4. 24 小时后

在数据库被删除整整 24 小时后,AWS 恢复了快照。

我收到了一封电子邮件,确认快照恢复已完成并可供使用:

之前不可见的快照现在出现在了控制台中。

5. 恢复数据库

我通过 Terraform 从恢复的快照中重新创建了数据库。

从此刻起,我改变了通过 Claude Code 使用 Terraform 的方式。所有权限都被禁用。不再自动执行。不再有文件写入。

现在的流程很简单:

  1. 生成一个计划
  2. 手动审查
  3. 自己运行命令

恢复数据库后,我进行了数据检查。courses_answer 表包含了 1,943,200 行:

课程管理平台重新上线。所有家庭作业都可见。

最后一步是在新的数据库实例上配置备份,并小心地删除在事件期间创建的临时空数据库,确保不要将两者混淆。

我为防止此类事件未来发生所做的事情

在等待 AWS 解决快照问题的同时,我开始实施安全保障措施。我希望再也不会发生一个 destroy 命令抹掉所有东西的情况。

以下是我所做的改变。

1. Terraform 状态之外的备份

我创建了不依赖 Terraform 管理的备份。

我没想到快照会与数据库一起被删除。为了避免这种风险,我确保备份独立于 Terraform 生命周期。

我还添加了基于 S3 的备份。这些备份与数据库分开存储,并且与基础设施状态解绑。

2. 使用 Lambda 和 Step Functions 进行每日恢复测试

我构建了一个自动化的备份工作流。

每晚凌晨 2 点,AWS 创建常规的自动备份。大约凌晨 3 点,一个 Lambda 函数启动,并根据该自动备份创建一个新的数据库实例。这让我每天都有一个生产环境的新副本。这大约需要 20 到 30 分钟。

数据库创建完成后,另一个 Lambda 函数通过 Step Functions 编排运行。它通过执行一个简单的读取查询(如 SELECT COUNT(*) FROM email)来验证数据库是否真的可用。检查通过后,数据库被停止,而不是删除。这样我只为存储付费,而不为计算资源付费。

之后,昨天创建的恢复数据库被删除。在任何时候,都有一个最近恢复的副本可用。

我这样做有两个原因:

  1. 我想持续验证备份是否确实可以恢复
  2. 如果生产环境宕机,我可以将流量重定向到一个可以随时启动的副本

我可能不总是以这种方式使用它,但我希望保留这个选项。

3. Terraform 和 AWS 删除保护

我在两个层面启用了删除保护:

  1. 在 Terraform 配置中
  2. 在 AWS 本身

两者都提供了防止意外删除的防护措施。

从技术上讲,这些保护仍然可以通过 CLI 移除(如果有人明确禁用了它们)。但它们增加了操作难度,并防止了意外的破坏性操作。

4. S3 备份保护

对于 S3 备份,我启用了版本控制。如果某些数据被删除,之前的版本仍然可用。删除一个存储桶也需要先清空其内容,这增加了另一道屏障。

5. 将 Terraform 状态迁移到 S3

最重要的是,我将 Terraform 状态文件迁移到了 S3。

状态不再存储在单台机器的本地。Terraform 现在拥有一致且共享的基础设施视图。这消除了最初的问题根源——我错误地认为状态文件已在远程,而实际上它还在我的旧机器本地,从而导致了重复资源的创建。

通过将状态存储在 S3 中:

  • 它不绑定到某一台电脑
  • 切换电脑时不会悄然消失
  • Terraform 始终拥有一致的基础设施视图

经验教训

这次事故是我的错:

  • 我过度依赖 AI 代理来运行 Terraform 命令。我把 planapplydestroy 当作可以委派的任务。这移除了最后的安全防线。
  • 我也过度依赖了那些我以为存在的备份。自动备份与数据库一同被删除。我没有完整地端到端测试过恢复路径。
  • 数据库太容易被删除了。没有足够的保护措施来减缓破坏性操作的发生。

在等待 AWS 支持时,我不得不考虑数据可能永久丢失的情况。

对于正在进行的 Data Engineering 课程,学员们正在完成最后几个模块,我已经在思考恢复计划。而对于更早的课程,那将是永久性的损失。

幸运的是,AWS 支持找到了一个快照并恢复了所有内容。

现在有什么改变

我实施的安全措施将会保留。

对于 Terraform:

  • 代理不再执行命令
  • 每个计划都由我手动审查
  • 每个破坏性操作都由我来运行

对于 AI Shipping Labs,我正在考虑在启动前使用一个独立的 AWS 账户来隔离开发和生产环境。

我最近在做什么

1. AI Engineering Buildcamp

我完成了 AI Engineering Buildcamp 监控模块的 DIY 监控平台部分的录制。

在上一期课程中,该模块主要侧重于构建我们自己的监控平台,而 Pydantic LogFire 更像是一个附加内容。对于本期课程,我将重点转移到了 Pydantic LogFire,因为它易于集成,唯一的实际挑战是数据提取。我确保讲解了如何解决此问题。DIY 监控平台仍然作为一个可选的深入部分包含在内。

我还吸收了上一期课程的反馈,并据此调整了材料。该部分的录制现已完成。

本周晚些时候,我还需要完成 AI Engineering Buildcamp 剩下的几个部分。

2. AI Engineering 新闻通讯系列

本周,我们发布了周三 AI Engineering 新闻通讯系列的一篇新文章,在这篇文章中,我们分析了来自全球主要科技中心的 1,000 多份 AI 工程师职位描述,以了解公司今天实际上是如何定义这个角色的。

我们分享了在这些职位发布中一致出现的内容:AI 工程师角色的不同子类型、公司期望的职责、最常出现的技能和工具,以及团队正在招聘的实际用例。

3. AI Engineer 直播研究系列

周二,我主持了我的活动系列"AI Engineering: The Interview Process"的第三场直播。

我基于大量真实面试材料的数据集分享了见解。我们讨论了公司实际上对 AI 工程候选人的期望、面试中出现的各种技术和概念性问题类型,以及现场编码挑战的例子。

为了准备这次直播,我回顾了 700 多个来源:报告、Twitter 和 Reddit 讨论,以及 YouTube 采访。从中,我提取了大量的面试问题,然后筛选出最相关的问题。这项工作很大一部分涉及对材料的过滤、验证和分类。

该研究也已发布并在 GitHub 上的 AI Engineering Field Guide 中持续更新。如果你觉得有用,请在社交媒体上给它加星并分享。

该系列的最后一场活动"AI Engineering Take-Home Assignments"将于下周一在 Zoom 上直播。在这次直播中,我们将分析公司实际上要求候选人在家构建什么,并识别这些任务背后的模式。

4. 现场工作坊

下周二,3月10日,我将在柏林的 Exasol Xperience 2026 上主持一个动手实践的数据工程工作坊。

在这个工作坊中,我们将使用超过 10 亿条记录的英国 NHS 处方数据构建一个完整的数据管道,从原始数据摄取到可分析的系统。我们将摄取数据集,设置一个临时环境,使用 AWS 上的 Exasol Personal 构建一个数据仓库,用 Kestra 编排管道,并通过 Grafana 仪表板探索结果。

如果你在柏林,欢迎参加。DataTalks.Club 社区的成员可以使用代码 EXA-VIP-RDTC 免费参加会议,但工作坊需要单独注册,因为我们在入口处会核对出席名单。

材料大约一个月前就准备好了,我现在正在润色内容,并与 Exasol 团队一起排练工作坊。我们还在想办法为没有自己 AWS 账户的参会者提供数据库访问权限。

5. Apache Flink 工作坊

周三,我为 Data Engineering Zoomcamp 主持了一个关于 Apache Flink 的工作坊,以更新流处理模块。

原始材料是由 Zach Wilson 创建的,他去年为课程主持了一个 Flink 流处理部分。工作坊内容大约 80-90% 基于他的材料,并已更新以适配 Flink 2.x 和现代 Python 版本(3.12, 3.9, 3.8)。

由于 Flink 不是我的主要专长领域,我依赖于 Zach 的工作,这些工作非常扎实。再次感谢 Zach 提供的精彩工作坊材料!

在工作坊期间,我们首先回顾了 Zach 的原始示例,然后探讨了另一个涉及水印和滑动窗口聚合的案例。更新材料需要大量的测试以确保一切正常工作。Claude Code 帮助进行了更新,尽管它需要相当多的指导。

  • 原文链接: alexeyondata.substack.co...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
alexeyondata
alexeyondata
江湖只有他的大名,没有他的介绍。