観測された事象と影響範囲
CI/CDパイプラインが突然失敗する。
ローカルでの `terraform init` は成功するのに、リモートではtfstateが見つからないと怒られる。
差分は無いはずなのに、なぜかバックエンドの設定が反映されていない。
S3に保存されるはずのtfstateが、ローカルに生成され続けている。
あなたはドキュメントを読み返し、コードのタイポを探し、何時間もスクリーンとにらめっこする羽目になります。
まさか、ごく一般的な `terraform.tfvars` というファイル名が、すべての原因だとは夢にも思わずに。
対象のイシュー詳細
backend-configがterraform.tfvarsというファイル名の場合、サイレントに無視される
Original: backend-config silently ignored if the config file named terraform.tfvars
terraform.tfvarsというファイル名が、バックエンド設定を意図せず上書きし、無視させてしまう問題。
観測されたエラー構造
# main.tf
terraform {
# Default backend, expecting override from a .tfvars file
backend "local" {
path = "default.tfstate"
}
}
# terraform.tfvars (This filename is the root of the problem)
# This S3 backend configuration, intended to be passed via -backend-config,
# will be silently ignored by Terraform during initialization.
bucket = "my-production-tf-state"
key = "network/s3/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
原因の技術的深掘り
この現象は、Terraformのファイル読み込みと設定評価の順序に起因する構造的欠陥です。
Terraformは `init` コマンド実行時、バックエンド設定を他のどの設定よりも先に初期化しようとします。
しかし、`terraform.tfvars` というファイル名は、Terraformにとって「ルートモジュールの変数を自動的に読み込む」ための予約語です。
結果として、`-backend-config=terraform.tfvars` を指定すると、Terraformはこれをバックエンド専用の設定ファイルとしてではなく、通常の変数ファイルとして解釈しようと試みます。
ですが、バックエンドブロック内では変数の参照が許可されていません。
この矛盾した状態に陥ったTerraformは、エラーを吐くことなく、単純に `terraform.tfvars` の内容を無視し、`main.tf` に記述されたデフォルトのバックエンド(この場合は `local`)を使い続けるのです。
エラーも警告も出ないため、開発者は問題の特定が極めて困難になります。
これは単なるバグではなく、ツールのコアな挙動に根差した深刻な落とし穴と言えるでしょう。
技術検証と解決策(ワークアラウンド)
この問題への直接的な解決策は、驚くほどシンプルです。
バックエンド設定ファイルに `terraform.tfvars` という予約された名前を使うのをやめることです。
`backend.tfvars` や `s3.config` のように、役割が明確で予約語と衝突しないファイル名に変更するだけで、Terraformは設定を正しく解釈するようになります。
しかし、このような些細な、だが致命的な落とし穴は、インフラ構築のあらゆる局面に潜んでいます。
ツールのバージョンアップで突如挙動が変わることもあれば、ドキュメントの片隅にしか書かれていない仕様に足をすくわれることもあります。
独自ドメインの取得、DNS設定、CI/CDとの連携、サーバーのプロビジョニング…
本来のサービス開発に集中したいのに、インフラの基盤準備という巨大なタスクがあなたの時間を奪っていくのです。
本当に重要なのは、これらの「罠」を一つ一つ回避することではなく、そもそも「罠」の存在しない安定した道を走ることではないでしょうか。
あなたの貴重な時間を、プロダクトの価値創造にこそ使うべきです。
$ mv terraform.tfvars s3_backend.tfvars
$ terraform init -backend-config="s3_backend.tfvars"
# s3_backend.tfvars (A safe, non-reserved filename)
# This S3 backend configuration will now be correctly applied.
bucket = "my-production-tf-state"
key = "network/s3/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true