そんな状況に置かれたことはないだろうか。
╭ │ Error: Backend configuration changed │ │ A change in the backend configuration has been detected, which may require │ migrating existing state. │ │ If you wish to attempt automatic migration of the state, use "terraform init -migrate-state". │ If you wish to store the prior configuration, use "terraform init -reconfigure". ╰
この記事では、「Backend configuration changed」が発生する仕組みから、-migrate-stateと-reconfigureの正確な違い・判断基準、代表的なシナリオ別の実際の復旧手順を解説する。
この記事のポイント
・「Backend configuration changed」は.terraform/terraform.tfstateとの設定差分が原因
・本番インフラを管理中なら-migrate-stateが原則(stateを新backendへ移行する)
・-reconfigureはstateを移行せず再初期化するため、本番環境での乱用は危険
・シナリオ(ローカル→S3移行、バケット名変更等)ごとに正しい手順が異なる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜ「Backend configuration changed」が発生するのか
Terraformはterraform initを実行するたびに、そのときのbackend設定の内容を.terraform/terraform.tfstate というファイルに記録する。このファイルはルートモジュールの terraform.tfstate とは別物で、「Terraform自身の初期化状態」を保存するメタデータファイルだ。次回terraform initを実行すると、Terraformはこのメタデータファイルに記録された「前回のbackend設定」と、現在の設定ファイル(main.tfやbackend.tf)に書かれたbackend設定を突き合わせる。ここで差分を検出すると「Backend configuration changed」エラーを出し、処理を止める。
エラーが出るのは次のような変更を行ったとき、すべて同じ理由による。
・backendブロックをはじめて追加した(ローカルからS3などリモートbackendへの移行)
・backendブロックのbucket名、key、region、dynamodb_tableなどのパラメータを変更した
・backendの種類を変更した(例: S3からAzure Blob Storageへ)
・backendブロックを削除した(リモートからローカルbackendに戻した)
一言で言えば、「前回初期化したときのbackend設定と今の設定が食い違っている。stateの扱いをどうするか、明示的に指示してくれ」というTerraformからの警告だ。
-migrate-stateと-reconfigureの違い
エラーメッセージが提示する2つのオプションは、既存stateの扱い方が根本的に異なる。ここを正確に理解していないと、本番環境で思わぬstateの喪失や整合性崩壊を引き起こす。1. -migrate-state:既存stateを新しいbackendへ移行する
terraform init -migrate-state
例えば、ローカルの
terraform.tfstate にstateが入っている状態でS3 backendに切り替えた場合、-migrate-stateを実行するとTerraformが次の手順を自動で行う。・古いbackend(ローカルファイル)からstateを読み込む
・新しいbackend(S3バケットの指定パス)へstateをコピーする
・.terraform/terraform.tfstateを新しいbackend情報で更新する
・初期化を完了する
移行が成功した後は、ローカルの
terraform.tfstate はTerraformから管理されなくなる(ファイル自体は残る)。本番インフラを壊さずにbackend移行を完了できる安全な手順だ。2. -reconfigure:stateを移行せず強制再初期化する
terraform init -reconfigure
ここで誤解しやすい点がある。-reconfigureは既存stateを削除するわけではない。
・ローカルのterraform.tfstateがあれば、ファイルとしては残ったまま
・S3バケット内にstateがあれば、S3オブジェクトとしては残ったまま
ただし、Terraform自身は「このbackendにstateがある」という記憶をリセットする。次にterraform planを実行すると、Terraformは「既存リソースなし・stateは空」という前提で差分計算を行う。
この状態でterraform applyを実行すると、AWSやGCP上に実際に存在するリソースを「Terraform管理外の新規リソース」として認識し、既存の設定を上書きしようとするケースが発生する。本番環境での-reconfigure乱用が危険な理由はここにある。
3. どちらを選ぶかの判断基準
状況に応じた正しい選択は次の通りだ。・本番インフラがstateで管理されている → -migrate-state一択
・検証環境でstateを失っても問題ない → -reconfigureも選択肢に入る
・チームメンバーが既に新backendへmigrate済みで自分だけが再接続する → -reconfigure
・CIパイプラインで毎回クリーンな環境で初期化する → -reconfigure(stateはリモートに確実に存在する前提)
実際の現場では、「迷ったら-migrate-state」で間違いはほぼない。-migrate-stateは既存stateを保護しながら安全に移行するため、副作用が少ない。-reconfigureを選ぶのは「今のbackendにstateが存在しないことが確実な場合」に限るべきだ。
>> Terraform実践セミナーの詳細はこちら
実際の復旧手順
1. エラーが出たらまず変更内容を把握する
復旧作業の第一歩は、「何がどう変わったのか」を正確に把握することだ。焦ってオプションを実行する前に2点確認する。確認1: 前回初期化時のbackend設定を見る
# 前回のbackend設定を確認(.terraform/terraform.tfstate はJSON形式) cat .terraform/terraform.tfstate
{ "version": 3, "serial": 1, "lineage": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "backend": { "type": "s3", "config": { "bucket": "my-old-tfstate-bucket", "key": "prod/terraform.tfstate", "region": "ap-northeast-1" }, "hash": 12345678901234567 }, "modules": [] }
# backend設定が書かれているファイルを確認 grep -r "backend" *.tf
2. -migrate-stateで復旧する手順(推奨)
本番環境では基本的にこの手順を使う。# -migrate-stateでbackend変更と同時にstateを移行 terraform init -migrate-state
Initializing the backend... Do you want to copy existing state to the new backend? Pre-existing state was found while migrating the previous "s3" backend to the newly configured "s3" backend. No existing state was found in the newly configured "s3" backend. Do you want to copy this state to the new backend? Enter a value: yes Successfully configured the backend "s3"! Terraform will automatically use this backend unless the backend configuration changes.
# 移行完了後の確認(差分がなければ問題なし) terraform plan # No changes. Your infrastructure matches the configuration.
3. -reconfigureで復旧する手順(用途を限定)
-reconfigureを使う場面は限られる。「stateは既に新しいbackendに存在している」または「このbackendのstateは空で問題ない」という確信があるときだけ使用する。# -reconfigureでbackend設定をリセットして再初期化 terraform init -reconfigure
シナリオ別のエラーパターンと対処法
1. ローカルbackendからS3 backendへ移行したとき
最も多いパターン。チームでのTerraform運用を始めるにあたり、stateをS3に移行するケースだ。変更前(backendブロックなし=ローカルbackend):
# main.tf(変更前 - backendブロックなし) terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
# main.tf(変更後 - S3 backendを追加) terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } backend "s3" { bucket = "my-company-tfstate" key = "prod/terraform.tfstate" region = "ap-northeast-1" dynamodb_table = "terraform-state-lock" encrypt = true } }
# S3への移行後、ローカルstateファイルをバックアップして退避 cp terraform.tfstate terraform.tfstate.bak
2. S3 backendのbucket名やkeyを変更したとき
バケット名を変えた、key(stateのS3パス)を変更した、あるいはリージョンを変えたケースだ。このケースも基本は-migrate-stateを使う。古いバケット・パスのstateを新しいバケット・パスへコピーしてから初期化を完了させる。# バケット名変更後の初期化(古いバケットから新しいバケットへstateを移行) terraform init -migrate-state
# 古いバケットが既に削除済みの場合:手動でstateをコピーしてから-reconfigure aws s3 cp s3://old-tfstate-bucket/prod/terraform.tfstate \ s3://new-tfstate-bucket/prod/terraform.tfstate # S3へのコピー後に-reconfigureで再初期化(stateは既に正しい場所にある) terraform init -reconfigure
3. backendブロックを削除してローカルに戻すとき
チーム運用を解消してシングル管理に戻す、あるいはリモートbackendのコストを削減するケースだ。backendブロックを削除(またはコメントアウト)した後にterraform initを実行すると、同様のエラーが出る。この場合も-migrate-stateを使うことで、S3などのリモートbackendからローカルファイルへstateが引き戻される。# backendブロック削除後、リモートからローカルへstateを引き戻す terraform init -migrate-state
本記事のまとめ
| シナリオ | 使うオプション | 理由 |
|---|---|---|
| ローカル → S3 backendへ移行 | terraform init -migrate-state |
ローカルstateをS3へコピーして引き継ぐ |
| S3のbucket名・keyを変更 | terraform init -migrate-state |
旧S3パスから新S3パスへstateをコピー |
| backendブロックを削除してローカルへ戻す | terraform init -migrate-state |
リモートstateをローカルファイルへ引き戻す |
| 手動でstate移行済み・CIクリーン環境 | terraform init -reconfigure |
stateは既に正しい場所にある前提で再初期化 |
| 検証環境でstateを捨てて再構築 | terraform init -reconfigure |
stateを引き継がず初期化(destroy済みが前提) |
Terraformのbackend設計やstate管理は、チーム開発や複数環境構成を安全に運用するための根幹だ。エラーへの個別対処にとどまらず、backend設計の全体像を理解しておくと、次のbackend変更作業で迷わなくなる。
>> Terraform実践セミナーの詳細はこちら
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:TerraformでVPCピアリングをコード化する設計|requesterとaccepterの分離とルートテーブル更新の依存関係
- この記事の属するカテゴリ:Terraformへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます