概要
この記事Claude Code + Terraformを活用してSession Managerを利用したEC2環境を構築内容を簡潔に説明します。
ClaudeCodeで開発するにあたって、CLAUDE.mdとMCPサーバーを使用する前提で進めたいと思います。
開発環境を用意したい方は下記記事を参考に進めて頂けたらと思います。
目次
やったこと
- 構成図の作成
- Terraformで開発
- 動作検証
手順
具体的な手順をステップバイステップで説明します。
ステップ1: 構成図の作成
Claudeに構成図を作ってもらいます。
構成図についてはアイコンなど用意せずに最低限内容が理解できるもので良いかと思われます。
ステップ2: Terraformで開発
構成図を使ってClaude Codeに開発してもらいましょう。
CLAUDE.mdで開発フローは定義しているので対象サービスの調査から開発まで基本一通り作業を実施してくれます。
作業を終えた後、以下のようにterraformディレクトリ内にファイルが作成されているはずです。
├── main.tf # AWSインフラ全体のエントリーポイント
├── output.tf # Terraform実行後に出力される値を定義
├── variables.tf # モジュールが受け取る変数の型・説明・デフォルト値を定義
├── terraform.tfvars # 変数の実際の値を定義
|
└── modules/ # AWSインフラの各コンポーネントを定義するモジュール
├── ec2/ # EC2インスタンスの定義
├── iam/ # IAMロールとポリシーの定義
├── ssm/ # SSMパラメータストアの定義
├── vpc/ # VPCとサブネットの定義
└── vpc_endpoints/ # VPCエンドポイントの定義
一通り作成された成果物の中身を一部抜粋して見ていきましょう。
main.tf
各モジュールの変数に対して値が定義されています。
また、EC2モジュールについてはdepends_onを定義して明示的な依存関係が設定されています。
- vpc_endpoints: VPCエンドポイントが存在しないとSSMエージェントが起動直後に通信できない
- ssm: Session Managerのドキュメント・ログ設定が整ってからEC2を起動する
Terraformは通常、参照関係から依存を自動解決しますが、ssm モジュールは直接の出力参照がないため depends_onで明示的に指定しています。
module "vpc" {
source = "./modules/vpc"
project = var.project
environment = var.environment
vpc_cidr = var.vpc_cidr
private_subnet_cidr = var.private_subnet_cidr
availability_zone = var.availability_zone
}
module "vpc_endpoints" {
source = "./modules/vpc_endpoints"
project = var.project
environment = var.environment
vpc_id = module.vpc.vpc_id
vpc_cidr_block = module.vpc.vpc_cidr_block
private_subnet_id = module.vpc.private_subnet_id
region = var.region
}
module "iam" {
source = "./modules/iam"
project = var.project
environment = var.environment
}
module "ssm" {
source = "./modules/ssm"
project = var.project
environment = var.environment
log_retention_days = var.log_retention_days
}
module "ec2" {
source = "./modules/ec2"
project = var.project
environment = var.environment
instance_type = var.instance_type
subnet_id = module.vpc.private_subnet_id
security_group_id = module.vpc_endpoints.ec2_security_group_id
iam_instance_profile_name = module.iam.instance_profile_name
depends_on = [module.vpc_endpoints, module.ssm]
}
vpc_endpoints/main.tf
SessionManagerをプライベートサブネットで使うために必要なセキュリティグループとVPCエンドポイントが定義されています。
| 名前 | 説明 |
|---|---|
| vpce-sg | ・インバウンド: VPC内からHTTPS(443)を許可 ・EC2からのリクエストを受け付けるためのルール |
| ec2-sg | ・アウトバウンド: VPC内へHTTPS(443)を許可 ・EC2からVPCエンドポイントへ通信するためのルール |
| 名前 | 説明 | 説明 |
|---|---|---|
| ssm | *.ssm | SSMエージェント ↔ SSMサービス間の通信 |
| ssmmessages | *.ssmmessages | Session Managerのセッション制御 |
| ec2messages | *.ec2messages | SSMエージェント ↔ EC2サービス間の通信 |
通信フロー
EC2 (ec2-sg)
│ HTTPS(443) アウトバウンド
▼
VPCエンドポイント (vpce-sg)
│ HTTPS(443) インバウンド
▼
AWS SSMサービス(インターネット不要)
VPCエンドポイントとSGを別モジュールで管理した場合は修正案を投げちゃいましょう。
resource "aws_security_group" "vpc_endpoint" {
name = "${var.environment}-${var.project}-vpce-sg"
description = "Security group for VPC endpoints"
vpc_id = var.vpc_id
tags = {
Name = "${var.environment}-${var.project}-vpce-sg"
Environment = var.environment
Project = var.project
ManagedBy = "Terraform"
}
}
resource "aws_vpc_security_group_ingress_rule" "vpc_endpoint_https" {
security_group_id = aws_security_group.vpc_endpoint.id
description = "Allow HTTPS from VPC"
from_port = 443
to_port = 443
ip_protocol = "tcp"
cidr_ipv4 = var.vpc_cidr_block
}
resource "aws_security_group" "ec2" {
name = "${var.environment}-${var.project}-ec2-sg"
description = "Security group for EC2 instances"
vpc_id = var.vpc_id
tags = {
Name = "${var.environment}-${var.project}-ec2-sg"
Environment = var.environment
Project = var.project
ManagedBy = "Terraform"
}
}
resource "aws_vpc_security_group_egress_rule" "ec2_https" {
security_group_id = aws_security_group.ec2.id
description = "Allow HTTPS to VPC endpoints"
from_port = 443
to_port = 443
ip_protocol = "tcp"
cidr_ipv4 = var.vpc_cidr_block
}
resource "aws_vpc_endpoint" "ssm" {
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ssm"
vpc_endpoint_type = "Interface"
subnet_ids = [var.private_subnet_id]
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
tags = {
Name = "${var.environment}-${var.project}-vpce-ssm"
Environment = var.environment
Project = var.project
ManagedBy = "Terraform"
}
}
resource "aws_vpc_endpoint" "ssmmessages" {
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ssmmessages"
vpc_endpoint_type = "Interface"
subnet_ids = [var.private_subnet_id]
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
tags = {
Name = "${var.environment}-${var.project}-vpce-ssmmessages"
Environment = var.environment
Project = var.project
ManagedBy = "Terraform"
}
}
resource "aws_vpc_endpoint" "ec2messages" {
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.ec2messages"
vpc_endpoint_type = "Interface"
subnet_ids = [var.private_subnet_id]
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
tags = {
Name = "${var.environment}-${var.project}-vpce-ec2messages"
Environment = var.environment
Project = var.project
ManagedBy = "Terraform"
}
}
resource "aws_vpc_endpoint" "logs" {
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.region}.logs"
vpc_endpoint_type = "Interface"
subnet_ids = [var.private_subnet_id]
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
tags = {
Name = "${var.environment}-${var.project}-vpce-logs"
Environment = var.environment
Project = var.project
ManagedBy = "Terraform"
}
}
その他成果物については特筆すべきことがなく仕様通り構築されていたので割愛します。
動作検証
では実際に構築してもらいましょう。
applyを実行してマネコン上で検証したいと思います。
インスタンスが出来ていることを確認できました。
SSMエージェントのステータスも「オンライン」であることを確認し、「接続」ボタンを押下することでコンソール画面が開くこと(接続成功)が確認できました。
まとめ
今回はClaude Code + Terraformを活用してSession Managerを利用したEC2環境を構築しました。
構成図の準備(インプット材料)から開発までClaude Codeを主軸に進めることでAI駆動開発のメリットを感じました。
参考





