基本機能
モジュール
Terraformのモジュールは、再利用可能なインフラストラクチャコンポーネントを作成するための仕組みです。このページでは、モジュールの概念、作成方法、使用方法について説明します。
最終更新: 2026/2/17
モジュール
Terraformのモジュールは、再利用可能なインフラストラクチャコンポーネントを作成するための仕組みです。このページでは、モジュールの概念、作成方法、使用方法について説明します。
モジュールとは
モジュールは、複数のリソースをまとめた再利用可能なコンポーネントです。関連するリソースをグループ化し、抽象化することで、コードの重複を削減し、保守性を向上させます。
モジュールの利点
- 再利用性: 同じ構成を複数の場所で使用できる
- 保守性: 変更を一箇所で行うだけで、すべての使用箇所に反映
- 抽象化: 複雑な実装を隠蔽し、シンプルなインターフェースを提供
- 標準化: 組織全体でベストプラクティスを共有
- テスト: モジュール単位でテストが可能
モジュールの種類
ルートモジュール
Terraformを実行するディレクトリのことをルートモジュールと呼びます。すべてのTerraform設定はルートモジュールから始まります。
.
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
子モジュール
他のモジュールから呼び出されるモジュールです。
.
├── main.tf
└── modules/
├── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── ec2/
├── main.tf
├── variables.tf
└── outputs.tf
モジュールの作成
基本的なモジュール構造
modules/vpc/
├── main.tf # リソースの定義
├── variables.tf # 入力変数の定義
├── outputs.tf # 出力値の定義
└── README.md # ドキュメント
実践例: VPCモジュール
modules/vpc/main.tf:
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = var.enable_dns_hostnames
enable_dns_support = var.enable_dns_support
tags = merge(
var.tags,
{
Name = var.vpc_name
}
)
}
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = merge(
var.tags,
{
Name = "${var.vpc_name}-public-${count.index + 1}"
Type = "Public"
}
)
}
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
tags = merge(
var.tags,
{
Name = "${var.vpc_name}-private-${count.index + 1}"
Type = "Private"
}
)
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(
var.tags,
{
Name = "${var.vpc_name}-igw"
}
)
}
modules/vpc/variables.tf:
variable "vpc_name" {
description = "Name of the VPC"
type = string
}
variable "vpc_cidr" {
description = "CIDR block for the VPC"
type = string
default = "10.0.0.0/16"
}
variable "public_subnet_cidrs" {
description = "CIDR blocks for public subnets"
type = list(string)
default = ["10.0.1.0/24", "10.0.2.0/24"]
}
variable "private_subnet_cidrs" {
description = "CIDR blocks for private subnets"
type = list(string)
default = ["10.0.11.0/24", "10.0.12.0/24"]
}
variable "availability_zones" {
description = "Availability zones"
type = list(string)
}
variable "enable_dns_hostnames" {
description = "Enable DNS hostnames in the VPC"
type = bool
default = true
}
variable "enable_dns_support" {
description = "Enable DNS support in the VPC"
type = bool
default = true
}
variable "tags" {
description = "Tags to apply to resources"
type = map(string)
default = {}
}
modules/vpc/outputs.tf:
output "vpc_id" {
description = "ID of the VPC"
value = aws_vpc.main.id
}
output "vpc_cidr" {
description = "CIDR block of the VPC"
value = aws_vpc.main.cidr_block
}
output "public_subnet_ids" {
description = "IDs of public subnets"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "IDs of private subnets"
value = aws_subnet.private[*].id
}
output "internet_gateway_id" {
description = "ID of the Internet Gateway"
value = aws_internet_gateway.main.id
}
モジュールの使用
ローカルモジュールの使用
# main.tf
module "vpc" {
source = "./modules/vpc"
vpc_name = "production-vpc"
vpc_cidr = "10.0.0.0/16"
public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnet_cidrs = ["10.0.11.0/24", "10.0.12.0/24"]
availability_zones = ["ap-northeast-1a", "ap-northeast-1c"]
tags = {
Environment = "Production"
ManagedBy = "Terraform"
}
}
# モジュールの出力を参照
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = module.vpc.public_subnet_ids[0]
tags = {
Name = "WebServer"
}
}
Terraform Registryのモジュールを使用
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = false
tags = {
Environment = "Production"
}
}
Gitリポジトリのモジュールを使用
module "vpc" {
source = "git::https://github.com/your-org/terraform-modules.git//vpc?ref=v1.0.0"
vpc_name = "production-vpc"
vpc_cidr = "10.0.0.0/16"
}
モジュールの初期化
モジュールを使用する場合、初期化が必要です。
terraform init
モジュールのソースを変更した場合:
terraform init -upgrade
モジュールの入力と出力
入力変数
モジュールへの入力は変数を通じて行います。
module "vpc" {
source = "./modules/vpc"
# 入力変数
vpc_name = "my-vpc"
vpc_cidr = "10.0.0.0/16"
}
出力値
モジュールからの出力はoutputブロックで定義します。
# モジュール内(modules/vpc/outputs.tf)
output "vpc_id" {
value = aws_vpc.main.id
}
# ルートモジュール(main.tf)
output "vpc_id" {
value = module.vpc.vpc_id
}
モジュール間でのデータの受け渡し
module "vpc" {
source = "./modules/vpc"
vpc_name = "production-vpc"
vpc_cidr = "10.0.0.0/16"
}
module "ec2" {
source = "./modules/ec2"
vpc_id = module.vpc.vpc_id
subnet_id = module.vpc.public_subnet_ids[0]
}
モジュールのバージョニング
セマンティックバージョニング
モジュールのバージョンは、セマンティックバージョニング(SemVer)に従うことが推奨されます。
- MAJOR: 互換性のない変更
- MINOR: 後方互換性のある機能追加
- PATCH: 後方互換性のあるバグ修正
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0" # 5.0.x の最新版を使用
}
バージョン制約
# 特定のバージョン
version = "5.0.0"
# バージョン範囲
version = ">= 5.0.0, < 6.0.0"
# ペシミスティック制約(推奨)
version = "~> 5.0" # 5.0.x の最新版
version = "~> 5.0.0" # 5.0.0 以上 5.1.0 未満
モジュールの構成パターン
単一責任の原則
各モジュールは1つの責任を持つべきです。
modules/
├── vpc/ # VPCの管理
├── ec2/ # EC2インスタンスの管理
├── rds/ # RDSの管理
└── s3/ # S3バケットの管理
階層的なモジュール構成
modules/
├── networking/
│ ├── vpc/
│ ├── subnet/
│ └── security-group/
├── compute/
│ ├── ec2/
│ └── autoscaling/
└── storage/
├── s3/
└── ebs/
コンポジションパターン
複数のモジュールを組み合わせて、より大きなシステムを構築します。
module "networking" {
source = "./modules/networking"
vpc_cidr = "10.0.0.0/16"
}
module "compute" {
source = "./modules/compute"
vpc_id = module.networking.vpc_id
subnet_id = module.networking.public_subnet_ids[0]
}
module "database" {
source = "./modules/database"
vpc_id = module.networking.vpc_id
subnet_ids = module.networking.private_subnet_ids
}
モジュールのテスト
Terraformのvalidateコマンド
cd modules/vpc
terraform init
terraform validate
Terraformのplanコマンド
terraform plan
自動テスト
Terratest(Go)やKitchen-Terraform(Ruby)などのツールを使用して、モジュールの自動テストを実行できます。
ベストプラクティス
1. 明確なインターフェースを定義
# 必須の変数には説明を追加
variable "vpc_name" {
description = "Name of the VPC"
type = string
}
# オプションの変数にはデフォルト値を設定
variable "enable_dns_hostnames" {
description = "Enable DNS hostnames in the VPC"
type = bool
default = true
}
2. 出力値を適切に定義
output "vpc_id" {
description = "ID of the VPC"
value = aws_vpc.main.id
}
3. READMEを作成
各モジュールにREADME.mdを作成し、使用方法を文書化します。
# VPC Module
## Usage
```hcl
module "vpc" {
source = "./modules/vpc"
vpc_name = "my-vpc"
vpc_cidr = "10.0.0.0/16"
}
Inputs
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| vpc_name | Name of the VPC | string | n/a | yes |
| vpc_cidr | CIDR block for the VPC | string | "10.0.0.0/16" | no |
Outputs
| Name | Description |
|---|---|
| vpc_id | ID of the VPC |
### 4. バージョン管理
モジュールをGitリポジトリで管理し、タグを使用してバージョンを管理します。
```bash
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
5. 変数の検証
variable "vpc_cidr" {
description = "CIDR block for the VPC"
type = string
validation {
condition = can(cidrhost(var.vpc_cidr, 0))
error_message = "The vpc_cidr must be a valid CIDR block."
}
}
6. 機密情報の扱い
variable "db_password" {
description = "Database password"
type = string
sensitive = true
}
output "db_endpoint" {
description = "Database endpoint"
value = aws_db_instance.main.endpoint
sensitive = true
}
Terraform Registry
モジュールの公開
- GitHubリポジトリを作成(命名規則:
terraform-<PROVIDER>-<NAME>) - モジュールを実装
- タグを作成(例: v1.0.0)
- Terraform Registryに登録
モジュールの検索
Terraform Registryで、公開されているモジュールを検索できます。
次のステップ
モジュールの基本を理解したら、ベストプラクティスについて学びましょう。