Terraformで構築するAWSインフラ自動化とIaC運用設計
〜社内検証用インフラ構築プロジェクトの実践記録と技術詳細〜
1. 概要
本記事では、Terraformを用いてAWS上のインフラ(VPC、EC2、Security Group、IAM、S3 backendなど)を自動構築した社内検証用インフラ構築プロジェクトの実践内容を整理する。
Terraformの構成ファイル設計、State管理方針、エラー対策、PRレビュー運用、そしてチーム運用の知見をまとめた技術ドキュメントである。
想定読者
IaC設計やState管理の運用ベストプラクティスを探している方
チームでTerraformを導入・レビュー運用したい方
2. Terraformとは
TerraformはHashiCorp社が提供する宣言的インフラ構築ツールであり、クラウドやオンプレ環境をコードで定義・再現することを目的とする。
AWSをはじめ、Azure・GCP・IBM Cloudなどマルチクラウドに対応しており、「構成を宣言する」ことで自動的にリソース差分を検知・適用する。
Terraformの強み:
・宣言的管理(最終的な状態を記述し差分を自動調整)
・plan→apply の事前・事後差分確認
・State による構成再現性
・マルチクラウドを単一言語で統合
特に、GitHubフローに基づくPull Requestレビューと相性の良い点が実務上重要である。
基本構文例
resource "aws_instance" "app" {
ami = var.ami_id
instance_type = "t3.micro"
tags = {
Name = "example-app"
}
}
Terraformはterraform planで差分を確認し、terraform applyでAWSに反映する。
この「plan→apply」のプロセスが、インフラ変更の安全性を担保する根幹である。
3. プロジェクト概要
背景
本プロジェクトでは、社内でNomad / Consul / Vaultを用いた検証環境をAWS上に再現し、再現性の高いTerraformテンプレートを確立することを目指した。
目的
・Terraformを用いたAWS基盤自動構築の標準化
・GitHubフローに基づくPRレビューを通じた構成意図の共有
4. ディレクトリ構成と各ファイルの役割
Terraform構成を分離・抽象化するため、次のような標準構成を採用。
.
├── main.tf
├── provider.tf
├── variables.tf
├── locals.tf
├── outputs.tf
├── backend.tf (※必要時のみ有効化)
└── modules/
└── infra/
├── vpc.tf
├── subnet.tf
├── route_table.tf
├── vpc_endpoint.tf
├── ec2.tf
├── sg.tf
├── iam.tf
├── locals.tf
└── outputs.tf
各ファイルの機能と留意点
| ファイル名 | 機能 | 推奨記述内容 |
|---|---|---|
| main.tf | モジュール呼び出し | 各moduleの引数を整理し、依存を明確化 |
| provider.tf | Provider設定 | region, profile, versionを固定化 |
| variables.tf | 変数定義 | 環境ごとの入力値を型・説明付きで管理 |
| locals.tf | 固定値・共通タグ | project名、AMI ID、タグ命名規則を集中管理 |
| outputs.tf | 出力リソース定義 | SG ID, EC2 ID等を出力し、他moduleで再利用 |
| backend.tf | State保存設定 | S3またはlocal backendを明示化 |
| modules/ | 共通部品群 | VPC/EC2/SG等を再利用可能に設計 |
Terraformでは「可読性と再利用性の両立」が重要である。
すべての.tfファイルにdescriptionコメントを付与することで、後続レビュー時の理解負荷を下げた。
5. AWSリソース構築詳細
5.1 VPC設定
新規作成時
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "${local.project_name}-vpc"
}
}
既存VPC参照時
variable "vpc_id" {
type = string
description = "Existing VPC ID"
}
data "aws_vpc" "selected" {
id = var.vpc_id
}
5.2 Security Group (SG)
Nomad/Consul/Vault通信に必要なポート群を明示的に許可。
resource "aws_security_group" "nomad_sg" {
name = "nomad-sg"
description = "Allow Nomad and Consul communication"
vpc_id = data.aws_vpc.selected.id
ingress {
from_port = 4646
to_port = 4648
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}
ingress {
from_port = 8300
to_port = 8302
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
SG設計は最小権限原則に基づき、用途ごとに個別化した。
5.3 EC2構築
resource "aws_instance" "demo" {
ami = local.ami_id
instance_type = "t3.micro"
subnet_id = var.subnet_id
key_name = var.key_name
root_block_device {
volume_type = "gp3"
volume_size = local.volume_size
}
iam_instance_profile = aws_iam_instance_profile.ssm_profile.name
vpc_security_group_ids = [aws_security_group.nomad_sg.id]
tags = merge(local.default_tags, {
Name = "${local.project_name}-demo"
})
}
5.4 IAM設定
EC2へSSMアクセスを可能にするIAMロール。
resource "aws_iam_role" "ssm_role" {
name = "demo-ssm-role"
assume_role_policy = data.aws_iam_policy_document.ssm_assume.json
}
data "aws_iam_policy_document" "ssm_assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
6. backend構成とState管理戦略
TerraformはStateファイル(terraform.tfstate)にAWSの現状を保存する。
その管理方針として2つの手法を使い分けた。
S3 backend
terraform {
backend "s3" {
bucket = "terraform-state-example"
key = "env/dev/terraform.tfstate"
region = "ap-northeast-1"
}
}
チーム共有時はS3 backendで一元管理
権限設定はGetObject/PutObjectを最小限付与
local backend個人検証時は以下で簡易運用:
terraform init -backend=false
個人Stateで安全な検証
PR前にStateを削除し競合を回避
| backend 種別 | 利用場面 | メリット | 注意点 |
|---|---|---|---|
| S3 backend | チーム共有環境 | State一元管理・ロック可能 | IAM設計が前提 |
| local backend | 個人検証・PR前の検証 | 即時・安全に変更試験 | Stateが個人に閉じるため共有不可 |
→ StateはTerraformの中核であるため、運用フェーズ別に使い分けることが重要
7. よく発生したエラーとその対処法
| エラー内容 | 原因 | 対処法 |
|---|---|---|
| ExpiredToken | IAMセッション期限切れ | aws sts get-session-token再発行 |
| Missing required argument "vpc_id" | main.tfで未指定 | vpc_id = var.vpc_idを明示 |
| Error refreshing state | backend不整合 | terraform init -backend=false再初期化 |
| InvalidClientTokenId | profile設定誤り | ~/.aws/credentialsを修正 |
| AccessDenied for S3 | ポリシー不足 | IAMにs3:GetObject, s3:PutObject付与 |
8. plan / apply の比較と運用ルール
plan出力例
terraform plan
+ create aws_instance.demo
+ create aws_security_group.nomad_sg
Plan: 2 to add, 0 to change, 0 to destroy
apply結果例
terraform apply -auto-approve
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
運用指針
plan結果はPRに添付して共有
applyはmainブランチmerge後のみ実施
差分を見てレビューする“plan駆動レビュー”を推奨
9. locals / variables / outputs のベストプラクティス
設計指針:
locals: 固定・共通値を管理するために使用
locals例
locals {
project_name = "aws-lab"
ami_id = "ami-xxxxxxxxxxxx"
volume_size = 30
default_tags = { Project = "demo", Owner = "InfraTeam" }
}
variables: 環境依存値を管理するために使用
variables例
variable "vpc_id" {
description = "Existing VPC ID"
type = string
}
outputs: module間連携のために使用
outputs例
output "ec2_id" {
value = aws_instance.demo.id
}
| 種別 | 役割 | 例 |
|---|---|---|
| locals | 環境に依存しない固定値・命名規則を集中管理 | AMI ID、タグ、volume size |
| variables | 利用時に変更される入力値 | VPC ID、Subnet、KeyPair |
| outputs | module間で再利用される識別子 | EC2 ID、SG ID など |
10. 開発・レビューのマイルストーン
| フェーズ | 内容 | 主な成果 |
|---|---|---|
| 1 | Terraform init成功 | Provider設定確立 |
| 2 | backend整備 | S3→local移行 |
| 3 | EC2構築完了 | SGポート整理 |
| 4 | PRレビュー対応 | VPC引数化・locals統一 |
| 5 | CI/CD検討 | plan自動化構想 |
各フェーズでplan結果とPRコメントを紐づけ、履歴を可視化。
コードではなく「決定の経緯」を記録する経験をした。
11. 運用ベストプラクティスまとめ
① plan結果の共有を標準化
→ PRコメントでplan差分を可視化
② State競合回避
→ 個人検証はlocal backend、共有環境はS3
③ タグ統一命名
→ Project / Owner / Envを全リソースに付与
④ 環境変数管理
→ AWS CLI profileで明示
⑤ .gitignore設定
→ .terraform/ と terraform.tfstate* を除外
12. 参考文献
Terraform公式ドキュメント
AWS Provider Registry
HashiCorp Learn: AWS Infrastructure Automation
AWS Architecture Blog: IaC運用のベストプラクティス
Qiita: Terraformとは何か
Qiita: TerraformでState管理を理解する
13. まとめ
TerraformによるAWSインフラ自動構築は、単にコードを書く行為ではなく再現性・説明性・運用文化を生む設計行為である。
本稿で示した構成・運用・レビュー手法を通じ、次の3点を再確認した。
・IaCは「構成の見える化」や「設計の標準化」だけでなく、「設計意図の共有」にも最適である
・State運用がTerraformの要である
・PRレビューはplan出力と共にするのが最適
Terraformは、エンジニア間の「同じ構成を同じ言葉で語る」ための共通言語として、IaCが当たり前になる中で、1エンジニアとして今後とも関わっていきたい。