コンテンツにスキップ

Terraform テンプレート - 最小構成

最小構成は、1 ディレクトリで全体を把握しやすい学習・検証向けの形。

ディレクトリ構造

terraform/
├── providers.tf
├── variables.tf
├── main.tf
├── outputs.tf
└── terraform.tfvars

providers.tf

terraform {
  required_version = ">= 1.8.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

variables.tf

variable "aws_region" {
  type        = string
  description = "AWS region"
}

variable "project_name" {
  type        = string
  description = "Project name prefix"
}

variable "vpc_cidr_block" {
  type        = string
  description = "VPC CIDR block"
}

variable "public_subnet_cidr" {
  type        = string
  description = "Public subnet CIDR block"
}

variable "instance_type" {
  type        = string
  description = "EC2 instance type"
}

variable "ami_id" {
  type        = string
  description = "EC2 AMI ID"
}

variable "bucket_name" {
  type        = string
  description = "S3 bucket name"
}

main.tf

resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr_block

  tags = {
    Name = "${var.project_name}-vpc"
  }
}

resource "aws_subnet" "public_a" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnet_cidr
  map_public_ip_on_launch = true
  availability_zone       = "${var.aws_region}a"

  tags = {
    Name = "${var.project_name}-public-a"
  }
}

resource "aws_security_group" "web" {
  name        = "${var.project_name}-web-sg"
  description = "Allow HTTP and HTTPS"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

data "aws_iam_policy_document" "ec2_assume_role" {
  statement {
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }

    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "ec2_role" {
  name               = "${var.project_name}-ec2-role"
  assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}

resource "aws_instance" "web" {
  ami                    = var.ami_id
  instance_type          = var.instance_type
  subnet_id              = aws_subnet.public_a.id
  vpc_security_group_ids = [aws_security_group.web.id]

  tags = {
    Name = "${var.project_name}-web"
  }
}

resource "aws_s3_bucket" "logs" {
  bucket = var.bucket_name

  tags = {
    Name = "${var.project_name}-logs"
  }
}

resource "aws_s3_bucket_versioning" "logs" {
  bucket = aws_s3_bucket.logs.id

  versioning_configuration {
    status = "Enabled"
  }
}

outputs.tf

output "vpc_id" {
  value = aws_vpc.main.id
}

output "public_subnet_id" {
  value = aws_subnet.public_a.id
}

output "security_group_id" {
  value = aws_security_group.web.id
}

output "instance_id" {
  value = aws_instance.web.id
}

output "s3_bucket_name" {
  value = aws_s3_bucket.logs.bucket
}

output "iam_role_name" {
  value = aws_iam_role.ec2_role.name
}

terraform.tfvars

aws_region         = "ap-northeast-1"
project_name       = "sample"
vpc_cidr_block     = "10.0.0.0/16"
public_subnet_cidr = "10.0.1.0/24"
instance_type      = "t3.micro"
ami_id             = "ami-xxxxxxxxxxxxxxxxx"
bucket_name        = "sample-logs-bucket-20260802"

このテンプレートで AWS 上にできるもの

[VPC]
  └─ [Public Subnet]
       └─ [EC2]
            └─ [Security Group: 80/443 allow]

[IAM Role]

[S3 Bucket]
  └─ Versioning enabled

補足:

  • 1つの VPC
  • 1つの Public Subnet
  • HTTP / HTTPS を許可する Security Group
  • その Subnet 上の EC2
  • EC2 用の IAM Role
  • バージョニング有効な S3 Bucket

最小構成が向く場面

  • 学習用途
  • 単体検証
  • 一時的な検証環境
  • まず全体像を掴みたいとき

最小構成の注意点

  • リソースが増えると見通しが悪くなる
  • 環境差分管理が雑になりやすい
  • 後から module 化すると組み替えコストが出やすい

メモ

  • まず Terraform に慣れるには十分な構成
  • 実務で長期運用するなら、次に大規模向け構成へ寄せる前提で考えたい