
ブロック
| ブロック名 | 説明 |
|---|---|
| terraform | Terraform のバージョン指定 プロバイダーのバージョン制約 リモートバックエンド(terraform.tfstate) |
| provider | クラウドプロバイダーの設定 aws / google / azurerm |
| resource | Terraform が管理するリソースを定義 |
| locals | ローカル変数(式の再利用・可読性向上) |
| module | モジュールの呼び出し ルートモジュール ⇒ 子モジュール |
| variable | モジュールの入力変数 ルートモジュール ⇒ 子モジュール |
| output | モジュールの出力変数 子モジュール ⇒ ルートモジュール |
| import | Terraform 管理外の既存リソースを Terraform 管理下に取り込む |
| data | Terraform管理外のリソース情報を参照する |
terraform ブロック
terraform {
# Terraform バージョン指定
required_version = ">= 1.5.0"
# プロバイダーのバージョン制約
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.5"
}
}
# リモートバックエンド(terraform.tfstate の保存先)
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "prod/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
provider ブロック
# AWS プロバイダー
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
Environment = "production"
ManagedBy = "Terraform"
}
}
}
# エイリアスを使用した複数リージョン設定
provider "aws" {
alias = "tokyo"
region = "ap-northeast-1"
}
provider "aws" {
alias = "osaka"
region = "ap-northeast-3"
}
resourceブロック
# EC2 インスタンス
resource "aws_instance" "web_server" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
tags = {
Name = "web-server-01"
}
}
# S3 バケット
resource "aws_s3_bucket" "data_bucket" {
bucket = "my-data-bucket-20241220"
tags = {
Name = "DataBucket"
Environment = "production"
}
}
# VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "main-vpc"
}
}
# 他のリソースを参照
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id # VPC リソースの参照
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a"
tags = {
Name = "public-subnet-1a"
}
}
localsブロック
locals {
# 単純な変数
environment = "production"
region = "ap-northeast-1"
# 複雑な式の再利用
common_tags = {
Environment = local.environment
ManagedBy = "Terraform"
Project = "MyApp"
}
# 条件式
instance_type = local.environment == "production" ? "t3.large" : "t3.micro"
# リスト・マップの操作
availability_zones = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
subnet_cidrs = {
public_1a = "10.0.1.0/24"
public_1c = "10.0.2.0/24"
private_1a = "10.0.11.0/24"
private_1c = "10.0.12.0/24"
}
# 文字列結合
bucket_name = "${var.project_name}-${local.environment}-data"
}
# locals を使用したリソース定義
resource "aws_instance" "app" {
instance_type = local.instance_type
tags = local.common_tags
}
module ブロック
# 子モジュールの呼び出し
module "vpc" {
source = "./modules/vpc" # ローカルモジュール
# 入力変数
vpc_cidr = "10.0.0.0/16"
environment = "production"
availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]
}
# Terraform Registry のモジュール使用
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "3.15.0"
bucket = "my-application-bucket"
acl = "private"
versioning = {
enabled = true
}
}
# Git リポジトリのモジュール使用
module "network" {
source = "git::https://github.com/myorg/terraform-modules.git//network?ref=v1.0.0"
vpc_name = "production-vpc"
cidr = "10.0.0.0/16"
}
# モジュールの出力を参照
resource "aws_instance" "web" {
subnet_id = module.vpc.public_subnet_ids[0] # モジュールの出力を使用
tags = {
Name = "web-server"
}
}
variableブロック
# 基本的な変数定義
variable "environment" {
description = "環境名(dev, stg, prod)"
type = string
default = "dev"
}
# 型指定付き変数
variable "instance_count" {
description = "起動する EC2 インスタンス数"
type = number
default = 1
}
variable "enable_monitoring" {
description = "CloudWatch 監視の有効化"
type = bool
default = false
}
# リスト型
variable "availability_zones" {
description = "使用するアベイラビリティゾーン"
type = list(string)
default = ["ap-northeast-1a", "ap-northeast-1c"]
}
# マップ型
variable "instance_types" {
description = "環境別のインスタンスタイプ"
type = map(string)
default = {
dev = "t3.micro"
stg = "t3.small"
prod = "t3.large"
}
}
# オブジェクト型
variable "database_config" {
description = "データベース設定"
type = object({
engine = string
engine_version = string
instance_class = string
storage_gb = number
})
default = {
engine = "postgres"
engine_version = "15.3"
instance_class = "db.t3.micro"
storage_gb = 20
}
}
# バリデーション付き変数
variable "region" {
description = "AWS リージョン"
type = string
validation {
condition = can(regex("^ap-northeast-[1-3]$", var.region))
error_message = "リージョンは ap-northeast-1, 2, 3 のいずれかを指定してください"
}
}
# センシティブ変数
variable "db_password" {
description = "データベースパスワード"
type = string
sensitive = true # ログに出力されない
}
output ブロック
# 基本的な出力
output "vpc_id" {
description = "VPC の ID"
value = aws_vpc.main.id
}
# 複数の値を出力
output "subnet_ids" {
description = "サブネット ID のリスト"
value = aws_subnet.public[*].id
}
# オブジェクトとして出力
output "instance_info" {
description = "EC2 インスタンス情報"
value = {
id = aws_instance.web.id
public_ip = aws_instance.web.public_ip
private_ip = aws_instance.web.private_ip
}
}
# センシティブな出力
output "db_password" {
description = "データベースパスワード"
value = aws_db_instance.main.password
sensitive = true # terraform output で表示されない
}
# 条件付き出力
output "load_balancer_dns" {
description = "ロードバランサーの DNS 名"
value = var.create_lb ? aws_lb.main[0].dns_name : null
}
# モジュール内での出力定義(子モジュール)
# modules/vpc/outputs.tf
output "vpc_id" {
description = "作成された VPC の ID"
value = aws_vpc.this.id
}
output "public_subnet_ids" {
description = "パブリックサブネットの ID リスト"
value = aws_subnet.public[*].id
}
importブロック
# 既存の EC2 インスタンスを Terraform 管理下に取り込む
import {
to = aws_instance.existing_server
id = "i-1234567890abcdef0"
}
resource "aws_instance" "existing_server" {
# リソース定義は terraform plan で確認後に記述
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
tags = {
Name = "existing-server"
}
}
# S3 バケットのインポート
import {
to = aws_s3_bucket.existing_bucket
id = "my-existing-bucket-name"
}
resource "aws_s3_bucket" "existing_bucket" {
bucket = "my-existing-bucket-name"
}
# VPC のインポート
import {
to = aws_vpc.imported_vpc
id = "vpc-0123456789abcdef0"
}
resource "aws_vpc" "imported_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "imported-vpc"
}
}
dataブロック
# 最新の Amazon Linux 2 AMI を取得
data "aws_ami" "amazon_linux_2" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# 既存の VPC 情報を取得
data "aws_vpc" "existing" {
filter {
name = "tag:Name"
values = ["production-vpc"]
}
}
# アベイラビリティゾーンの一覧を取得
data "aws_availability_zones" "available" {
state = "available"
}
# 現在の AWS アカウント ID を取得
data "aws_caller_identity" "current" {}
# 現在のリージョンを取得
data "aws_region" "current" {}
# Secrets Manager からシークレット取得
data "aws_secretsmanager_secret" "db_password" {
name = "production/database/password"
}
data "aws_secretsmanager_secret_version" "db_password" {
secret_id = data.aws_secretsmanager_secret.db_password.id
}
# data ブロックの値を使用
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2.id
instance_type = "t3.micro"
availability_zone = data.aws_availability_zones.available.names[0]
tags = {
Name = "web-server"
AccountId = data.aws_caller_identity.current.account_id
Region = data.aws_region.current.name
}
}
# 複数のサブネットを取得
data "aws_subnets" "private" {
filter {
name = "vpc-id"
values = [data.aws_vpc.existing.id]
}
filter {
name = "tag:Type"
values = ["private"]
}
}
output "private_subnet_ids" {
value = data.aws_subnets.private.ids
}
変数のスコープ
| スコープ | 定義 | 適用範囲 |
|---|---|---|
| グローバルスコープ | terraform ブロック内で定義 | プロジェクト全体 |
| ルートモジュールスコープ | locals、variableで定義 | 同一ディレクトリ内 |
| モジュールスコープ | module ブロック内で渡された変数 | 各モジュール内 |
モジュール(引数と出力の受け渡し)
サンプルコードのディレクトリ構造
project-root/
|
+- environments/
| |
| +- prd/
| |
| +- main.tf # ルートモジュール
| +- variables.tf # ルートモジュールの入力変数
| +- outputs.tf # ルートモジュールの出力変数
|
+- modules/
|
+- s3/
|
+- main.tf # 子モジュールのリソース定義
+- variables.tf # 子モジュールの入力変数
+- outputs.tf # 子モジュールの出力変数

ルートモジュール
environments/prd/main.tf
# S3 モジュールの呼び出し
module "s3_bucket" {
source = "../../modules/s3"
# 子モジュールへ引数を渡す
bucket_name = var.bucket_name
environment = var.environment
enable_versioning = var.enable_versioning
}
environments/prd/variables.tf
# ルートモジュール - 入力変数
variable "bucket_name" {
description = "S3 バケット名"
type = string
default = "my-app-data-bucket"
}
variable "environment" {
description = "環境名"
type = string
default = "prd"
}
variable "enable_versioning" {
description = "バージョニングを有効にするか"
type = bool
default = true
}
environments/prd/outputs.tf
# ルートモジュール - 出力変数
# 子モジュールからの出力を受け取る
output "bucket_id" {
description = "S3 バケット ID"
value = module.s3_bucket.bucket_id
}
output "bucket_arn" {
description = "S3 バケット ARN"
value = module.s3_bucket.bucket_arn
}
output "bucket_domain_name" {
description = "S3 バケットのドメイン名"
value = module.s3_bucket.bucket_domain_name
}
子モジュール
modules/s3/main.tf
# 子モジュール - S3 バケットの作成
resource "aws_s3_bucket" "this" {
bucket = "${var.bucket_name}-${var.environment}"
tags = {
Name = "${var.bucket_name}-${var.environment}"
Environment = var.environment
}
}
# バージョニング設定
resource "aws_s3_bucket_versioning" "this" {
bucket = aws_s3_bucket.this.id
versioning_configuration {
status = var.enable_versioning ? "Enabled" : "Suspended"
}
}
# パブリックアクセスブロック
resource "aws_s3_bucket_public_access_block" "this" {
bucket = aws_s3_bucket.this.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
modules/s3/variables.tf
# 子モジュール - 入力変数
# ルートモジュールから値を受け取る
variable "bucket_name" {
description = "S3 バケットのベース名"
type = string
}
variable "environment" {
description = "環境名(dev, stg, prd)"
type = string
}
variable "enable_versioning" {
description = "バージョニングを有効にするか"
type = bool
default = false
}
modules/s3/outputs.tf
# 子モジュール - 出力変数
# ルートモジュールに値を返す
output "bucket_id" {
description = "S3 バケットの ID"
value = aws_s3_bucket.this.id
}
output "bucket_arn" {
description = "S3 バケットの ARN"
value = aws_s3_bucket.this.arn
}
output "bucket_domain_name" {
description = "S3 バケットのドメイン名"
value = aws_s3_bucket.this.bucket_domain_name
}