Terraform テンプレート - 大規模向け¶
大規模向けでは、modules/ と environments/ を分け、環境差分と再利用部品を切り離す前提で考える。
ディレクトリ構造¶
terraform/
├── modules/
│ ├── network/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── compute/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── security/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── storage/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── backend.tf
│ │ ├── providers.tf
│ │ ├── versions.tf
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── terraform.tfvars
│ │ └── outputs.tf
│ ├── stg/
│ └── prod/
└── README.md
この構成の意図¶
modules/: 再利用部品を置くenvironments/: 環境差分を閉じ込めるbackend.tf: state 保存先を環境別に分けるversions.tf: Terraform / Provider バージョンを固定するterraform.tfvars: 環境固有値を入れる
このページで載せる対象¶
modules/networkmodules/securitymodules/computemodules/storageenvironments/dev
modules/network/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"
}
resource "aws_subnet" "private_a" {
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_cidr
availability_zone = "${var.aws_region}a"
tags = {
Name = "${var.project_name}-private-a"
}
}
modules/network/variables.tf¶
variable "aws_region" {
type = string
}
variable "project_name" {
type = string
}
variable "vpc_cidr_block" {
type = string
}
variable "public_subnet_cidr" {
type = string
}
variable "private_subnet_cidr" {
type = string
}
modules/network/outputs.tf¶
output "vpc_id" {
value = aws_vpc.main.id
}
output "public_subnet_id" {
value = aws_subnet.public_a.id
}
output "private_subnet_id" {
value = aws_subnet.private_a.id
}
modules/security/main.tf¶
resource "aws_security_group" "web" {
name = "${var.project_name}-web-sg"
description = "Allow HTTP and HTTPS"
vpc_id = var.vpc_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"]
}
tags = {
Name = "${var.project_name}-web-sg"
}
}
modules/security/variables.tf¶
variable "project_name" {
type = string
}
variable "vpc_id" {
type = string
}
modules/security/outputs.tf¶
output "web_sg_id" {
value = aws_security_group.web.id
}
modules/compute/main.tf¶
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 = var.subnet_id
vpc_security_group_ids = [var.security_group_id]
tags = {
Name = "${var.project_name}-web"
}
}
modules/compute/variables.tf¶
variable "project_name" {
type = string
}
variable "ami_id" {
type = string
}
variable "instance_type" {
type = string
}
variable "subnet_id" {
type = string
}
variable "security_group_id" {
type = string
}
modules/compute/outputs.tf¶
output "instance_id" {
value = aws_instance.web.id
}
output "iam_role_name" {
value = aws_iam_role.ec2_role.name
}
modules/storage/main.tf¶
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"
}
}
modules/storage/variables.tf¶
variable "project_name" {
type = string
}
variable "bucket_name" {
type = string
}
modules/storage/outputs.tf¶
output "bucket_name" {
value = aws_s3_bucket.logs.bucket
}
environments/dev/backend.tf¶
terraform {
backend "s3" {
bucket = "sample-dev-terraform-state"
key = "network/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
use_lockfile = true
}
}
environments/dev/providers.tf¶
provider "aws" {
region = var.aws_region
}
environments/dev/versions.tf¶
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
environments/dev/variables.tf¶
variable "aws_region" {
type = string
}
variable "project_name" {
type = string
}
variable "vpc_cidr_block" {
type = string
}
variable "public_subnet_cidr" {
type = string
}
variable "private_subnet_cidr" {
type = string
}
variable "ami_id" {
type = string
}
variable "instance_type" {
type = string
}
variable "bucket_name" {
type = string
}
environments/dev/main.tf¶
module "network" {
source = "../../modules/network"
aws_region = var.aws_region
project_name = var.project_name
vpc_cidr_block = var.vpc_cidr_block
public_subnet_cidr = var.public_subnet_cidr
private_subnet_cidr = var.private_subnet_cidr
}
module "security" {
source = "../../modules/security"
project_name = var.project_name
vpc_id = module.network.vpc_id
}
module "compute" {
source = "../../modules/compute"
project_name = var.project_name
ami_id = var.ami_id
instance_type = var.instance_type
subnet_id = module.network.public_subnet_id
security_group_id = module.security.web_sg_id
}
module "storage" {
source = "../../modules/storage"
project_name = var.project_name
bucket_name = var.bucket_name
}
environments/dev/outputs.tf¶
output "vpc_id" {
value = module.network.vpc_id
}
output "public_subnet_id" {
value = module.network.public_subnet_id
}
output "private_subnet_id" {
value = module.network.private_subnet_id
}
output "web_sg_id" {
value = module.security.web_sg_id
}
output "instance_id" {
value = module.compute.instance_id
}
output "iam_role_name" {
value = module.compute.iam_role_name
}
output "bucket_name" {
value = module.storage.bucket_name
}
environments/dev/terraform.tfvars¶
aws_region = "ap-northeast-1"
project_name = "sample-dev"
vpc_cidr_block = "10.0.0.0/16"
public_subnet_cidr = "10.0.1.0/24"
private_subnet_cidr = "10.0.11.0/24"
ami_id = "ami-xxxxxxxxxxxxxxxxx"
instance_type = "t3.micro"
bucket_name = "sample-dev-logs-bucket-20260802"
このテンプレートで AWS 上にできるもの¶
[dev environment]
├─ [VPC]
│ ├─ [Public Subnet]
│ └─ [Private Subnet]
├─ [Security Group]
├─ [EC2]
├─ [IAM Role]
└─ [S3 Bucket]
補足:
dev環境専用の state を S3 backend で管理する- module ごとに責務を分けて再利用できる
stgprodも同じ構造で増やしやすい
大規模向けで意識したいこと¶
- state はリモート管理する
- module の責務を広げすぎない
- 環境差分は tfvars に寄せる
- 命名規則、タグ、変数ルールを揃える
メモ¶
- 大規模向けでは「コード断片」より「分け方」のほうが重要になる
- module 化しすぎて読みにくくならないように注意したい