はじめに
業務で稼働しているTerraformのコードを手元にクローンして、「自分の検証用AWSアカウントで試しに動かしてみよう!」と思い立ったことはありませんか?
しかし、意気揚々と terraform init や terraform apply を実行すると、真っ赤なエラーメッセージが大量に出力されて心が折れそうになる……というのは、IaC(Infrastructure as Code)初学者が必ず通る道です。
本記事では、既存のTerraformコードを別の環境(検証アカウントなど)で流用して動かそうとした際に、必ずと言っていいほどハマる「3つの罠」とその解決策を解説します。
罠1:状態管理ファイル(tfstate)の権限エラー
最初に直面するのが terraform init 実行時の 403 Forbidden エラーです。
エラーの原因
Terraformは、構築したリソースの状態を terraform.tfstate というファイルで管理します。実運用されているコードの大半は、このファイルの保存先(バックエンド)として Amazon S3 (Amazon Simple Storage Service) を指定しています。
そのままコードを実行すると、「本来の環境(本番など)のAmazon S3バケット」に対して状態ファイルを読み書きしようとしますが、あなたの検証用アカウント(認証情報)にはそのバケットへのアクセス権限がないため、エラーで弾かれます。
解決策
検証環境用にバックエンドの設定を書き換えます。最も手軽なのは、一時的な検証であればローカル(自分のPC内)に保存する設定に変更することです。
【修正例】
# 修正前:本番環境のAmazon S3バケットを向いている
terraform {
backend "s3" {
bucket = "my-company-prod-tfstate-bucket"
key = "app.tfstate"
region = "ap-northeast-1"
}
}
# ------------------------------------------------
# 修正後:S3の設定をコメントアウトし、ローカル保存に変更する
terraform {
backend "local" {
path = "terraform.tfstate"
}
}設定を書き換えた後は、バックエンドの向き先を再設定するために terraform init -reconfigure コマンドを実行して初期化し直します。
※ローカルに保存した tfstate ファイルは、誤ってGit等のバージョン管理にコミットしないよう .gitignore の設定に注意してください。
罠2:Amazon S3 バケットの「グローバルユニーク」制約
無事に初期化が終わり、terraform apply を実行すると、次は BucketAlreadyExists というエラーに遭遇することがあります。
エラーの原因
Amazon S3 のバケット名は、世界中のすべてのAWSアカウントの中で一意(グローバルユニーク) でなければならないという強力なルールがあります。
既存のコードに bucket = "my-app-image-bucket" のような固定の文字列(ハードコード)が書かれている場合、その名前はすでに元の環境(本番環境など)で使用されているため、あなたの検証環境で同じ名前のバケットを作ることはできません。
解決策
検証環境用のコードを実行する際は、バケット名が既存の環境と被らないようにサフィックス(接尾辞)を追加するか、変数を使って動的に名前を変えられるように設計します。
【修正例】
# 修正前:名前が固定されているため重複エラーになる
resource "aws_s3_bucket" "app_images" {
bucket = "my-app-image-bucket"
}
# ------------------------------------------------
# 修正後:変数やサフィックスを使ってユニークな名前にする
resource "aws_s3_bucket" "app_images" {
# 例: "my-app-image-bucket-test-yamamoto" のように名前を回避する
bucket = "${var.base_bucket_name}-test-yamamoto"
}罠3:部分構築時のネットワーク依存関係エラー
「Amazon S3のエラーは直した。次は Application Load Balancer (ALB) だけを -target オプションでサクッと作って動作確認しよう!」と実行した際に、InvalidSubnet: VPC … has no internet gateway といったエラーが出ることがあります。
エラーの原因
Terraformは依存関係を自動で解決してくれますが、それは「必要なリソースがすべて一緒に構築される前提」での話です。
ALBや Amazon EC2 インスタンスなどのリソースは、単体では存在できません。土台となる Amazon Virtual Private Cloud (Amazon VPC) や、インターネットと通信するための インターネットゲートウェイ などのネットワークリソースが正しく設定されている必要があります。
元の環境ではすでに出来上がっているネットワーク環境も、あなたの真っ新な検証環境には存在しないため、ALBの作成がネットワーク要件を満たせずに失敗してしまいます。
解決策
一部のリソースだけを単独で構築するのではなく、依存関係にある基礎ネットワーク(Amazon VPC、サブネット、インターネットゲートウェイ、ルートテーブルなど)から順を追って構築します。
または、AWSマネジメントコンソール上から手動で前提となるネットワーク要件(インターネットゲートウェイの作成とAmazon VPCへのアタッチなど)をサクッと整えてしまうのも、一時的な検証作業においては有効な手段です。
まとめ
既存のTerraformコードを別の環境で動かす際は、以下の3点に注意しましょう。
- tfstateの保存先(Backend)を自分の環境に向ける
- Amazon S3 バケット名など、グローバルで一意となるリソース名が重複しないよう変更する
- 部分的な構築をする際も、土台となるネットワークの依存関係を見落とさない