変数とモジュール
ストーリー
「staging環境とproduction環境で、ほぼ同じインフラを 作りたいとする。コードをコピペするか?」
木村先輩が質問した。
「コピペは......DRY原則に反しますよね」
「その通り。変数とモジュールを使えば、 同じコードを再利用しつつ、環境ごとの差異だけを パラメータで切り替えられる。 これがTerraformでインフラを効率的に管理する鍵だ」
変数(Variables)
入力変数(variable)
hcl
# variables.tf
# 基本的な変数定義
variable "environment" {
description = "環境名 (staging / production)"
type = string
default = "staging"
}
variable "instance_type" {
description = "EC2インスタンスタイプ"
type = string
default = "t3.micro"
}
variable "instance_count" {
description = "EC2インスタンス数"
type = number
default = 1
}
variable "enable_monitoring" {
description = "詳細モニタリングを有効にするか"
type = bool
default = false
}
# バリデーション付き変数
variable "environment" {
description = "環境名"
type = string
validation {
condition = contains(["staging", "production"], var.environment)
error_message = "environment は staging または production を指定してください。"
}
}変数の型
| 型 | 例 | 説明 |
|---|---|---|
string | "hello" | 文字列 |
number | 42 | 数値 |
bool | true | 真偽値 |
list(string) | ["a", "b"] | 文字列のリスト |
map(string) | { key = "val" } | 文字列のマップ |
object({...}) | 複合型 | 構造化されたオブジェクト |
複合型の例
hcl
variable "vpc_config" {
description = "VPC設定"
type = object({
cidr_block = string
subnets = list(object({
cidr = string
az = string
}))
})
default = {
cidr_block = "10.0.0.0/16"
subnets = [
{ cidr = "10.0.1.0/24", az = "ap-northeast-1a" },
{ cidr = "10.0.2.0/24", az = "ap-northeast-1c" },
]
}
}変数の値を指定する方法
変数値の優先順位(上が最優先)
1. コマンドライン引数 terraform apply -var="environment=production"
2. terraform.tfvars environment = "production"
3. *.auto.tfvars 自動読み込み
4. 環境変数 TF_VAR_environment=production
5. default値 variable "environment" { default = "staging" }
terraform.tfvars
hcl
# terraform.tfvars(環境ごとに作成)
environment = "production"
instance_type = "t3.large"
instance_count = 3
enable_monitoring = truehcl
# staging.tfvars
environment = "staging"
instance_type = "t3.micro"
instance_count = 1
enable_monitoring = falsebash
# 環境ごとにファイルを指定して実行
terraform plan -var-file="staging.tfvars"
terraform plan -var-file="production.tfvars"ローカル変数(locals)
計算結果や繰り返し使う値を定義します。
hcl
locals {
# 共通タグ
common_tags = {
Environment = var.environment
Project = "my-project"
ManagedBy = "terraform"
}
# 計算値
name_prefix = "${var.project}-${var.environment}"
# 条件分岐
instance_type = var.environment == "production" ? "t3.large" : "t3.micro"
}
# 使用例
resource "aws_instance" "web" {
instance_type = local.instance_type
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-web"
})
}モジュール(Module)
モジュールとは
再利用可能なTerraformコードのパッケージです。
モジュールの構成
modules/
└── vpc/
├── main.tf ← リソース定義
├── variables.tf ← 入力変数
├── outputs.tf ← 出力値
└── README.md ← ドキュメント
environments/
├── staging/
│ └── main.tf ← モジュールを呼び出す
└── production/
└── main.tf ← 同じモジュールを異なるパラメータで呼び出す
モジュールの定義
hcl
# modules/vpc/variables.tf
variable "name" {
description = "VPC名"
type = string
}
variable "cidr_block" {
description = "VPC CIDR"
type = string
default = "10.0.0.0/16"
}
variable "public_subnets" {
description = "パブリックサブネットのCIDR"
type = list(string)
default = ["10.0.1.0/24", "10.0.2.0/24"]
}hcl
# modules/vpc/main.tf
resource "aws_vpc" "this" {
cidr_block = var.cidr_block
enable_dns_hostnames = true
tags = {
Name = var.name
}
}
resource "aws_subnet" "public" {
count = length(var.public_subnets)
vpc_id = aws_vpc.this.id
cidr_block = var.public_subnets[count.index]
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${var.name}-public-${count.index + 1}"
}
}
data "aws_availability_zones" "available" {
state = "available"
}hcl
# 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
}モジュールの呼び出し
hcl
# environments/staging/main.tf
module "vpc" {
source = "../../modules/vpc"
name = "staging-vpc"
cidr_block = "10.0.0.0/16"
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
}
# モジュールの出力を参照
resource "aws_instance" "web" {
subnet_id = module.vpc.public_subnet_ids[0]
}hcl
# environments/production/main.tf
module "vpc" {
source = "../../modules/vpc"
name = "production-vpc"
cidr_block = "10.1.0.0/16"
public_subnets = ["10.1.1.0/24", "10.1.2.0/24", "10.1.3.0/24"]
}Terraform Registry のモジュール
コミュニティが公開しているモジュールも利用できます。
hcl
# Terraform Registry の VPC モジュール
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
}count と for_each
count
同じリソースを複数作成します。
hcl
resource "aws_instance" "web" {
count = var.instance_count
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
tags = {
Name = "web-${count.index + 1}"
}
}for_each
マップやセットを使って複数リソースを作成します。
hcl
variable "subnets" {
default = {
public-a = { cidr = "10.0.1.0/24", az = "ap-northeast-1a" }
public-c = { cidr = "10.0.2.0/24", az = "ap-northeast-1c" }
}
}
resource "aws_subnet" "this" {
for_each = var.subnets
vpc_id = aws_vpc.main.id
cidr_block = each.value.cidr
availability_zone = each.value.az
tags = {
Name = each.key
}
}まとめ
| ポイント | 内容 |
|---|---|
| variable | 入力パラメータ、型指定とバリデーション可能 |
| locals | 計算値や繰り返し値の定義 |
| module | 再利用可能なTerraformコードパッケージ |
| count/for_each | リソースの複数作成 |
チェックリスト
- variable の定義と値の指定方法を理解した
- locals で計算値を定義できる
- モジュールの作成と呼び出し方を理解した
- count と for_each の使い分けを把握した
次のステップへ
次のセクションでは、Terraformの実行ワーク フロー(plan/apply/destroy)を詳しく学びます。
推定読了時間: 30分