DataTalks.Club 2026年 AIのエージェントが流した terraform destroy

新しい機械に state が無いまま plan と apply をAIのエージェントに任せ、重複を消す途中で、エージェントが古い state に差し替えて terraform destroy を流した。state に載っていた本番の全部が消え、自動の控えもDBと一緒に消えた。止める所は、エージェントに消す権限を持たせないこと、state を1か所に置くこと、DBを消せない設定と、DBと別の場所の控えにある。

DataTalks.Club の講座の基盤。AWS の上に Terraform で作られていた。起きたのは2026年2月26日の夜で、運営する創業者がその場で気付いた[1]。DBは約24時間後の2月27日に AWS のサポートが見つけた控えから戻った[1]。出典は、創業者が2026年3月6日に出した振り返り。Terraform と AWS の仕組みは2026年11月時点の公式文書によります。

要点

  • 消えたのは本番のDB、VPC、ECS のクラスタ、ロードバランサ、踏み台。DBには2年半分の講座の提出物が入っていた[1]。
  • destroy が消すのは、設定ではなく state に載っている物である。エージェントが古い state に差し替えた時点で、重複の後片付けは本番の削除に変わった。
  • DBの自動の控えはDBと一緒に消えた。コンソールから見えない控えを AWS のサポートが見つけ、約24時間で戻った[1]。
  • 創業者は自分の誤りと書き、エージェントに plan、apply、destroy を任せたことで最後の安全の層を外した、と振り返る[1]。
  • 根本の直しは、エージェントの資格情報で本番を消せなくすること。削除の保護、state の遠隔の置き場所、別の場所の控えと毎日の復元の試験を、その上に重ねる。

何が起きたか

2月26日22時ごろに state の無いまま apply が始まり、23時ごろに destroy で本番が消え、27日0時台にサポートが控えを見つけ、22時ごろに戻った 1 state 無し 2月26日22時ごろ 新しい機械で apply 重複が作られる 2 destroy 23時ごろ 古い state に差し替え 本番の全部が消える 3 控えを探す 27日0時から2時 サポートが見えない 控えを見つける 4 戻る 27日22時ごろ 控えからDBを作り直し 基盤が戻る 始まりと気付きは同じ夜。消えてから戻るまで約24時間 時刻は振り返りに書かれた目安。時間帯の表記は無い
図1 消えてから戻るまで
日時出来事
前段別の事業のサイトを AWS へ移すため、講座の基盤を管理していた既存の Terraform の構成に足した。月に5から10ドルを浮かせるためで、Claude は別にするよう勧めたが、創業者が退けた[1]。
2026年2月26日 22時ごろTerraform で変更を出し始める。state のファイルは前の機械に残っていた[1]。plan と apply は Claude Code に走らせた。作られる物の長い一覧を見て止め、apply を取り消したが、一部はもう作られていた[1]。
同じ夜エージェントに AWS CLI で新しく作られた物を見分けて消させる。その間に創業者は、前の機械の Terraform のフォルダを state ごと固めて新しい機械へ移し、比べるためにエージェントへ場所を示した[1]。
23時ごろエージェントが、Terraform で作った物は Terraform で消す方が簡潔だとして terraform destroy を流す。創業者は止めなかった[1]。本番の全部が消え、自動の控えも消えていた[1]。
2月27日 0時ごろサポートへ問い合わせ、応答の早い Business Support の契約へ上げる。約40分で返答があった[1]。
0時30分ごろAWS のサポートが、コンソールに見えない控えが AWS の側にあると伝える[1]。
1時から2時ごろ電話で状況を確かめ、AWS の社内で引き上げられる[1]。
日中復元を待つ間に、控えの Lambda、削除の保護、S3 への控え、state の S3 への移しを入れる[1]。
22時ごろAWS が控えを戻し、Terraform でDBを作り直す。courses_answer の表だけで1,943,200行が戻った[1]。
2026年3月6日創業者が振り返りを公表する[1]。
  • 振り返りの筆者は DataTalks.Club の創業者で、講座の基盤を自分で作った人である[2]。
  • Business Support への切り替えで、AWS の費用は約10%増えた[1]。
  • 戻るまでの間、創業者は、進行中の講座は立て直せても、過去の講座のデータは失えば戻らないと考えていた[1]。

起きた仕組み

Terraform は state で、実際の資源と設定を結び付ける[3]。plan も destroy も、state に載っている物を相手にする。state が空なら全部を作ろうとし、別の state が入れば、その state に載った物を消しに行く。

空の state では plan が全部を作ろうとし、古い本番の state に差し替えると destroy が本番の全部を消す 段1 新しい機械。state が無い state 空 plan と apply 全部を新しく作る AWS 本番と重複が並ぶ 段2 片付けの途中。前の機械の state が入る state 古い本番の一覧 terraform destroy エージェントが流す AWS 本番の全部が消える 消えた物 RDS のDB、VPC、ECS のクラスタ、ロードバランサ、踏み台 DBの自動の控えもDBと一緒に消えた
図2 state の差し替えで、片付けが本番の削除に変わった道筋
段何があったか
構成の相乗り本番の講座の基盤と、別の事業のサイトを1つの Terraform の構成に入れた。創業者は、これで変更が混ざり、複雑さと危険が増えたと書く[1]。
手元の statestate は前の機械の手元にあった。創業者は遠隔にあると思い込んでいた[1]。Terraform の公式文書は、手元の state は共同の作業を妨げるとし、遠隔の置き場所を勧める[3]。
差し替えエージェントが固めたフォルダを展開し、今の state を古い state で置き換えた。創業者はその展開に気付かなかった[1]。
destroyエージェントが提案して流し、創業者は止めなかった。創業者は、その時点でも重複だけを消していると思っていた[1]。
控え毎晩の自動の控えはあったが、DBと一緒に消えた。創業者は、控えがDBと一緒に消えるとは思っていなかったと書く[1]。

RDS は、DBを消すときに自動の控えを残すかを選ばせる。残さなければ、同じリージョンの自動の控えはDBと一緒に消え、戻せない。手で取ったスナップショットはDBを消しても残る[4][5]。Terraform の aws_db_instance では、自動の控えをすぐ消す delete_automated_backups の既定が true で、削除の保護 deletion_protection の既定が false である[6]。この件の構成でこれらの値がどうだったかは、振り返りに書かれていない。

道具のせいにする話は公表資料に無い

振り返りは、この件を自分の誤りとし、エージェントに Terraform の命令を任せたこと、確かめていない控えを頼ったこと、DBが消しやすすぎたことを挙げる[1]。エージェントが命令に背いた、勝手に暴走した、とは書いていない。destroy はエージェントが提案し、創業者が止めずに通した。消えたデータが失われたままという話も公表資料には無く、DBは戻った[1]。

どこで止められたか

エージェントの権限、命令の承認、state の置き場所、環境の分離、削除の保護、別の場所の控えの6つの段に止める所を置く エージェントの鍵 命令の承認 state の置き場所 環境の分け方 消す操作 消えた後 1 読むだけの資格情報を渡す 本番を消す権限を、エージェントの側に置かない 2 apply と destroy は人が流す plan を人が読み、消える物の数を見る 3 state を遠隔に1つだけ置く 機械を替えても同じ state。手元の写しを作らない 4 本番と他を別の構成と口座に 他の作業の destroy が本番に届かない 5 DBを消せない設定 deletion_protection と prevent_destroy 6 DBと別の場所の控えと復元の試験 この件で戻せたのは、サポートだけが見えた控え
図3 段ごとの止める所
止める所この件で限り
読むだけの資格情報エージェントは AWS CLI で資源を消し、destroy も流せた[1]。読むだけの資格情報なら、plan までで止まったplan は作れても、apply の段で人が別の資格情報を使う手間が増える
人が流すapply は作られる物の長い一覧で一度止まった。destroy は提案されたまま通った[1]人が承認を押すだけなら、片付けの途中の疲れた判断で通る。消える物の一覧を読む決まりにする
遠隔の statestate が前の機械に残り、空の state で apply が走った。固めた古い state が持ち込まれた[1]遠隔に置いても、手元へ写した古い state を戻せば同じことが起きる。版の管理と、書き込みの権限を絞る
構成と口座の分離別の事業のサイトを本番と同じ構成に入れていた。Claude は別にするよう勧めていた[1]月に5から10ドルの節約と引き換えだった[1]
消せない設定創業者は、事後に Terraform と AWS の両方で削除の保護を入れた[1]CLI で保護を外せば消せる[1][4]。prevent_destroy は設定から資源の記述を消すと効かない[7]
別の場所の控え自動の控えはDBと一緒に消え、戻ったのはサポートだけが見えた控えのおかげだった[1]サポートが戻せるのは消してから最大6日と AWS は書く[4]。頼る前提にしない

守り方

根本の直し方
  • エージェントに渡す資格情報で、本番を消せなくする。手元のエージェントには読むだけの役割を渡し、apply と destroy は別の役割を持つ人か CI で流す。権限を用途ごとに絞る考え方は秘密の鍵の扱いの、権限を最小にする節にある。
  • 本番と、それ以外の作業を、別の構成と別の口座に分ける。創業者も、開発と本番の AWS の口座を分けることを考えていると書く[1]。他の作業の destroy が、本番の資源に届かない形にする。
  • state は遠隔の置き場所に1つだけ置き、機械に紐付けない。創業者は state を S3 へ移した[1]。Terraform は、施錠と権限の管理の無い所に state を置かないよう求める[3]。S3 に置くなら、誤って消した state を戻せるよう置き場所の版の管理を強く勧めている[8]。
  • DBの控えを、DBとその state の外に持つ。創業者は Terraform の管理の外の控えと、DBと別に置く S3 の控えを足した[1]。RDS の手で取ったスナップショットはDBを消しても残る[5]。
  • 控えから戻せることを毎日確かめる。創業者は、毎晩の控えから別のDBを立て、読む問い合わせを1つ通してから止める仕組みを作った[1]。

消せないDB 架空の構成 main.tf

terraform {
  backend "s3" {
    bucket       = "tfstate-example"     # 遠隔に1つだけ置く
    key          = "prod/terraform.tfstate"
    region       = "ap-northeast-1"
    use_lockfile = true                  # 同時の書き込みを止める
  }
}

resource "aws_db_instance" "main" {
  identifier = "courses-prod"
  # 中略
  backup_retention_period  = 14
  delete_automated_backups = true      # 既定。DBと一緒に自動の控えが消える
  delete_automated_backups = false     # DBを消しても期間の間は残す
  deletion_protection      = true      # AWS の側で削除を断る
  skip_final_snapshot      = false
  final_snapshot_identifier = "courses-prod-final"

  lifecycle {
    prevent_destroy = true             # 消す plan を Terraform が断る
  }
}
  • prevent_destroy が真なら、Terraform は資源を消す plan を誤りとして断り、terraform destroy も進まなくなる。ただし設定から資源の記述を消すと効かない[7]。
  • deletion_protection が真のDBは、コンソールでも CLI でも API でも消せない。外すには設定を変える[4][6]。外す操作を、エージェントの資格情報で許さない。
  • delete_automated_backups を偽にすると、DBを消しても自動の控えが期間の間は残る[5][6]。
  • use_lockfile は、S3 の置き場所での施錠の設定である[8]。
緩和の策
  • エージェントの道具の設定で、apply と destroy を止める。Claude Code では拒否の規則が承認の規則より先に評価される[9]。ただし規則は、道具の置き場所で呼んだ同じ命令や sh -c の中の命令には当たらない[9]。資格情報の側で止めた上に重ねる網にする。文書と設定の分担は決まりを文書に残すにある。
  • plan の出力を人が読む。作る物、変える物、消す物の数を見て、思っていた数と違えば止める。この件では、作る物の長い一覧が最初の異変だった[1]。差分を読む段の考え方はAIの出力を確かめるの1段目にある。
  • AIの報告をそのまま信じない。この件では、重複を見分けて消しているという報告を、創業者は正しそうだと受け取った[1]。何を消したかは、報告ではなく AWS の実物の一覧で確かめる。
  • 片付けの途中で、別の機械の state や設定をエージェントの作業の場所へ持ち込まない。比べるなら、読むだけの別の場所に置く。
  • 控えの置き場所の版の管理を有効にし、中身を消さないと置き場所ごと消せない形にする。創業者は S3 で版の管理を入れた[1]。

.claude/settings.json 消す命令を通さない 資格情報の絞り込みと併せて使う

{
  "permissions": {
    "deny": ["Bash(terraform destroy *)", "Bash(terraform apply *)",
             "Bash(aws rds delete-db-instance *)"],
    "ask":  ["Bash(terraform plan *)"]
  }
}

創業者は事後に、Terraform について Claude Code の権限を全部外し、自動の実行もファイルの書き込みも許さず、plan を作らせて人が読み、命令は自分で流す形に変えた[1]。

同じ年の4月には、別の会社でAIのエージェントが、手元で見つけた全権限のトークンで本番のDBを消した。そちらはPocketOS 2026年で扱う。

参照

  1. How I Dropped Our Production Database and Now Pay 10% More for AWS DataTalks.Club の創業者の振り返り、Alexey On Data、2026年3月6日
  2. 創業者の紹介のページ DataTalks.Club
  3. State HashiCorp Terraform Docs
  4. Deleting a DB instance Amazon RDS User Guide
  5. Introduction to backups Amazon RDS User Guide
  6. aws_db_instance HashiCorp Terraform AWS Provider
  7. lifecycle meta-argument reference HashiCorp Terraform Docs
  8. Backend Type: s3 HashiCorp Terraform Docs
  9. Configure permissions Claude Code Docs