39
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【続編】Claude Code × Terraform実践!エラー修正を自動化して30分でAWSデプロイした話

Last updated at Posted at 2025-12-22

はじめに

SapeetでSWEをやっている林です。

前回の記事「Claude Codeで爆速開発!S3→BigQueryデータ転送システムを1時間で設計した話」では、データ同期システムのアーキテクチャと設計について紹介しました。

今回は、その続編として、Claude Codeを使ってTerraformのインフラコードを生成し、実際にAWS環境にデプロイするまでの過程を共有します。その過程で得た知識やつまづいたポイントも併せて解説していきます。

この記事で学べること

  1. 生成されたTerraformコードをAWSにデプロイするまでの実践フロー
  2. 実際に遭遇した3つの問題とClaude Codeによる自動修正
    • Terraformのディレクトリ構成の理解(root main.tfの役割)
    • AWS認証設定の落とし穴(backend.tf vs provider block)
    • terraform plan構文エラーの自動修正テクニック

AWS事前設定

以下は事前に生成したsetup-guide.mdに従って設定済みであることを前提とします:

  • Terraform Backend用リソース
    • S3バケット(stateファイル保存用、バージョニング・暗号化有効)
    • DynamoDBテーブル(stateロック用)
  • GCP認証情報
    • BigQueryサービスアカウント作成済み
    • サービスアカウントキーをAWS Systems Manager Parameter Storeに保存済み

プロジェクト構成

terraform/
├── main.tf                    # ← ここが重要!
├── variables.tf
├── outputs.tf
├── modules/
│   ├── vpc/
│   ├── ecs/
│   ├── s3/
│   ├── iam/
│   ├── ecr/
│   ├── cloudwatch/
│   └── eventbridge/
└── environments/
    ├── dev/
    │   ├── main.tf           # ← rootモジュールを呼び出すだけ
    │   ├── backend.tf
    │   ├── variables.tf
    │   └── terraform.tfvars
    └── prod/
        └── ...

Claude Codeでインフラ構築する全体フロー

前回の記事で、Claude Codeに要件を伝え、Terraformコードの生成タスクをtask-breakdown.mdとして作成してもらいました。
今回は、そのタスクを実際に実行してもらうところからスタートします。

Step 1: task-breakdown.mdに基づいた段階的実装

Claude Codeに「task-breakdown.mdのタスクを順次実行してください」と依頼すると、自動的に以下のステップを進めてくれました:

生成されたタスク一覧:

1. プロジェクト構造の作成
2. VPCモジュールの実装
3. IAMモジュールの実装
4. S3モジュールの実装
5. ECRモジュールの実装
6. CloudWatchモジュールの実装
7. ECSモジュールの実装
8. EventBridgeモジュールの実装
9. ルートモジュールの作成
10. Dev環境の設定

5分で、全モジュールのコードが生成されました。

task-breakdown.mdは、Claude Codeが自動生成するタスク管理ファイルです。大きなタスクを小さなステップに分割し、進捗を追跡できます。各ステップが完了すると、自動的にチェックマークが付きます。

Step 2: Backend設定とterraform init

まず、S3バケットとDynamoDBテーブルを手動で作成し、backend設定を行いました:

# environments/dev/backend.tf
terraform {
  backend "s3" {
    bucket         = "simple-data-sync-terraform-state-${timestamp}"
    key            = "dev/terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "simple-data-sync-terraform-lock"
    profile        = "your-aws-profile"  # AWSプロファイル
  }
}
$ cd terraform/environments/dev
$ terraform init

結果: 初回initは成功!stateファイルがS3に保存されました。

Step 3: Claude Codeに terraform plan 実行を依頼

さあ、Backend設定も完了したので、Claude Codeに以下のプロンプトを投げました:

terraform/environments/devの方にinitしたので、planを実行し、エラーをなくすようにお願いします。

すると、Claude Codeが terraform plan を実行し、以下の3つのエラーを検出しました:

エラー1: AWS認証エラー

❌ Error: No valid credential sources found

エラー2: EventBridgeの構文エラー

❌ Error: Unsupported argument
  on ../../modules/eventbridge/main.tf line 43:
  43:     maximum_event_age = 3600

エラー3: S3ライフサイクルの警告

⚠️  Warning: Invalid Attribute Combination
No attribute specified when one (and only one) of
[rule[0].filter, rule[0].prefix] is required

Step 4: Claude Codeによる自動エラー修正

ここでClaude Codeの真価を発揮!

上記のプロンプト(「planを実行し、エラーをなくすようにお願いします」)を投げただけで、エラーがなくなるまで自動的に修正し続けてくれました

Claude Codeの対応:

  1. terraform plan を実行
  2. エラーを検出・分析
  3. 該当ファイルを自動的に読み込み
  4. 修正を適用
  5. terraform validate で検証
  6. 再度 terraform plan を実行
  7. エラーがあれば 2 に戻る

このサイクルを自動的に3回繰り返し、約10分ですべてのエラーを解決しました。

Step 5: terraform apply でデプロイ完了

$ terraform plan
Plan: 45 to add, 0 to change, 0 to destroy.

$ terraform apply
Apply complete! Resources: 45 added, 0 changed, 0 destroyed.

成功!15分でAWSインフラのデプロイが完了しました。

デプロイされたリソース:

  • VPC(サブネット、セキュリティグループ)
  • IAMロール 3つ(ECS Task、Task Execution、EventBridge)
  • S3バケット(暗号化、バージョニング有効)
  • ECRリポジトリ
  • ECSクラスターとタスク定義
  • EventBridgeスケジュールルール
  • CloudWatchロググループとメトリクスアラーム

所要時間: Backend設定5分 + エラー修正10分 + デプロイ15分 = 約30分

遭遇した問題と解決方法

上記のStep 3で遭遇した問題について、詳しく解説します。

問題1: Terraform root main.tfの役割を理解する

最初に遭遇したのは、Terraformのディレクトリ構成に関する誤解でした。

誤解していたこと

当初、私はTerraformのディレクトリ構成について以下のように誤解していました:

❌ 間違った理解
environments/dev/main.tf に全モジュールを直接呼び出す
environments/prod/main.tf に全モジュールを直接呼び出す
→ 各環境で同じモジュール呼び出しコードを重複して書く

正しい構成パターン

実際には、以下のような構成が推奨されます:

terraform/main.tf(rootモジュール)

# すべてのモジュールをここで組み合わせる
provider "aws" {
  region  = var.aws_region
  profile = var.aws_profile

  default_tags {
    tags = merge(
      {
        Project     = var.project_name
        Environment = var.environment
        ManagedBy   = "Terraform"
      },
      var.tags
    )
  }
}

module "vpc" {
  source = "./modules/vpc"
  # VPC設定
}

module "ecs" {
  source = "./modules/ecs"
  # VPCモジュールの出力を使用
  vpc_id = module.vpc.vpc_id
  # ...
}

# 他のモジュールも同様に定義

environments/dev/main.tf(環境固有の設定)

# rootモジュール全体を1回呼び出すだけ
module "data_sync" {
  source = "../../"  # rootモジュールを参照

  # 環境固有の変数を渡す
  project_name = var.project_name
  environment  = "dev"
  aws_region   = var.aws_region
  aws_profile  = var.aws_profile

  # dev環境固有の設定
  ecs_task_cpu    = 512
  ecs_task_memory = 1024
  enable_nat_gateway = false
  # ...
}

この構成のメリット

DRY原則の遵守: モジュール間の依存関係を一箇所(root main.tf)で管理
保守性の向上: モジュール構成の変更が各環境に自動的に反映される
環境間の一貫性: 同じインフラ構成を異なるパラメータで再利用

問題2: AWS認証設定の落とし穴(backend.tf vs provider)

これは最も混乱したポイントでした。backend.tf にプロファイルを設定していたのに認証エラーが発生したのです。

遭遇した問題

backend.tf にAWSプロファイルを設定していたのに、terraform plan で認証エラーが発生しました。

# environments/dev/backend.tf
terraform {
  backend "s3" {
    bucket  = "my-terraform-state"
    key     = "dev/terraform.tfstate"
    region  = "ap-northeast-1"
    profile = "your-aws-profile"  # ← これは設定済み
  }
}
$ terraform init
✅ Success! # backend設定は正常に動作

$ terraform plan
❌ Error: No valid credential sources found

原因の理解

Terraformには2種類の認証設定が存在します:

用途 設定場所 使用されるタイミング
Backend認証 backend "s3" block terraform init でstate管理用S3にアクセスする時
Provider認証 provider "aws" block terraform plan/apply でAWSリソースを操作する時

つまり、backend.tfのprofileはstateファイルの保存先へのアクセスにのみ使用され、実際のリソース操作には使われないのです。

解決策

rootモジュールのprovider blockにもプロファイル設定を追加します。

Step 1: 変数を定義

# terraform/variables.tf
variable "aws_profile" {
  description = "AWS CLI profile to use for authentication"
  type        = string
  default     = null
}

Step 2: Provider blockに追加

# terraform/main.tf
provider "aws" {
  region  = var.aws_region
  profile = var.aws_profile  # ← これを追加

  default_tags {
    tags = merge(
      {
        Project     = var.project_name
        Environment = var.environment
        ManagedBy   = "Terraform"
      },
      var.tags
    )
  }
}

Step 3: 環境ごとにプロファイルを設定

# environments/dev/variables.tf
variable "aws_profile" {
  description = "AWS CLI profile to use for authentication"
  type        = string
  default     = "your-aws-profile"
}

Step 4: rootモジュールに渡す

# environments/dev/main.tf
module "data_sync" {
  source = "../../"

  aws_region  = var.aws_region
  aws_profile = var.aws_profile  # ← これを追加
  # ...
}

認証方法の整理

参考までに、AWS Provider の認証方法の優先順位は以下の通りです:

  1. Provider block内の access_key / secret_key(非推奨)
  2. Provider block内の profile(✅ 推奨)
  3. 環境変数 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
  4. 環境変数 AWS_PROFILE
  5. デフォルトプロファイル (~/.aws/credentials[default])

本番環境ではIAMロールの使用が推奨されますが、開発環境ではプロファイルを明示的に指定する方が管理しやすいです。

問題3: terraform plan で発生した構文エラー

Claude Codeが生成したコードでも、いくつかの構文エラーが発生しました。しかし、これらは全てClaude Codeによる自動修正で解決できました。

エラー例1: EventBridgeのパラメータ名誤り

Error: Unsupported argument
  on ../../modules/eventbridge/main.tf line 43:
  43:     maximum_event_age = 3600
An argument named "maximum_event_age" is not expected here.

修正内容

# terraform/modules/eventbridge/main.tf
retry_policy {
-  maximum_event_age       = 3600
+  maximum_event_age_in_seconds = 3600
   maximum_retry_attempts  = 2
}

AWS EventBridgeのリトライポリシーでは、maximum_event_age ではなく maximum_event_age_in_seconds が正しいパラメータ名でした。

Claude Codeによる自動修正の流れ

上記のエラーに対して、私がやったことはシンプルな1行のプロンプトだけです:

terraform/environments/devの方にinitしたので、planを実行し、エラーをなくすようにお願いします。

これだけで、Claude Codeが自動的に:

  1. terraform plan を実行
  2. エラー原因を分析
  3. 該当ファイルを読み込み
  4. 正しい修正を適用
  5. terraform validate で検証
  6. 再度 terraform plan を実行(エラーがあれば2に戻る)

このサイクルを自動的に繰り返し、すべてのエラーを解決してくれました。

ポイント: エラーメッセージを手動でコピペする必要はなく、「エラーをなくすまで修正してください」と目標を伝えるだけで、Claude Codeが自律的に問題解決してくれます。

Claude Code活用のポイント

今回の実践で分かった、Claude Codeを効率的に使うコツをまとめます:

推奨

  • 目標を明確に伝える: 「エラーをなくすまで修正してください」と指示することで、Claudeが自律的に問題解決サイクルを回してくれる
  • Claudeにコマンド実行を任せる: terraform planの実行もClaudeに任せることで、エラー検出→修正→再検証を自動化できる
  • TodoListで進捗を確認: 複数のエラーがある場合、どのエラーを修正中かが可視化される
  • 検証はClaudeに任せる: terraform validateterraform planの実行もClaude Codeが自動で行ってくれる
  • ガードレールの設定: .claude/rulesterraform applyの自動実行を防止するルールを定義し、誤削除やコスト超過を防ぐ(参考

非推奨

  • エラーメッセージを手動でコピペする(Claudeに直接コマンド実行させる方が効率的)
  • 途中で人間が介入しすぎる(Claude Codeの自律的な問題解決を信頼する)
  • 曖昧な指示を出す(「エラーを修正して」ではなく「planが成功するまで修正して」と具体的に)

効果的なワークフロー

前回の記事(コード生成依頼)から今回の記事(デプロイ)までの全体フローです:

まとめ

今回、Claude Codeが生成したTerraformコードを実際にAWSにデプロイし、約30分で完了することができました。

得られた知見

  1. Terraformのディレクトリ構成: root main.tfでモジュールを一元管理し、環境ごとに変数を渡すパターン
  2. AWS認証の2層構造: backend.tf(state保存)とprovider block(リソース操作)は別物
  3. Claude Codeの自律的な問題解決能力: 「エラーをなくすまで修正してください」という目標を伝えるだけで、コマンド実行→エラー検出→修正→再検証のサイクルを自動的に回してくれる

人間が判断すべきポイント

Claude Codeは非常に強力ですが、以下の点は必ず人間が確認・判断する必要があります:

  • セキュリティ設定の妥当性(IAMポリシー、セキュリティグループ)
  • コスト最適化の判断(NAT Gateway vs VPC Endpoints など)
  • 環境固有の要件(リージョン、命名規則、タグ戦略)
  • コンプライアンス要件(データ暗号化、ログ保持期間など)

Next Action

次回は、このTerraformで構築したインフラ上で動作するデータ同期アプリケーション(Python + boto3 + BigQuery Client)の実装と疎通確認について紹介する予定です。

参考リンク

39
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?