はじめに

業務で稼働しているTerraformのコードを手元にクローンして、「自分の検証用AWSアカウントで試しに動かしてみよう!」と思い立ったことはありませんか?

しかし、意気揚々と terraform initterraform 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点に注意しましょう。

  1. tfstateの保存先(Backend)を自分の環境に向ける
  2. Amazon S3 バケット名など、グローバルで一意となるリソース名が重複しないよう変更する
  3. 部分的な構築をする際も、土台となるネットワークの依存関係を見落とさない