Terraform を使用したコードとしてのインフラストラクチャ: 手動から自動化されたクラウド管理へ
Infrafraction as Code (IaC) を使用している組織は、インフラストラクチャを手動で管理している組織に比べて環境のプロビジョニングが 90% 速くなり、構成関連の停止が 60% 少なくなります。 Terraform は主要な IaC ツールとして台頭しており、3,000 を超えるプロバイダーがあらゆる主要なクラウド プラットフォームと SaaS サービスをサポートしています。
このガイドでは、最初のリソース定義から運用グレードのマルチ環境展開まで、Web アプリケーション、ERP システム、および e コマース プラットフォームでの Terraform の実践的な使用法について説明します。
重要なポイント
- Terraform により、バージョン管理を通じてインフラストラクチャの変更がレビュー可能、テスト可能、元に戻せるようになります
- リモート状態管理により、複数のエンジニアがインフラストラクチャを変更する場合の競合を防止します
- モジュールは再利用可能なパターンをカプセル化し、構成を数百行から数パラメータに削減します
- Terraform Cloud または CI/CD の統合により、安全な変更を実現するための適用前計画の規律が強化されます
SMB に Terraform を使用する理由
手動インフラストラクチャの問題
IaC がなければ、インフラストラクチャの知識は次の場所に存在します。
- 誰も文書化していない AWS コンソールのクリックパス
- SSH コマンドは数か月前に実行されましたが、誰も覚えていません
- サーバー上で直接編集された設定ファイル
- あるエンジニアの「ネットワークがどのように機能するか」に関するメンタル モデル
Terraform を使用すると、インフラストラクチャは Git 内に存在します。すべての変更はプルリクエストです。すべての展開は再現可能です。すべてのエンジニアは全体像を理解できます。
コアコンセプト
| コンセプト | 説明 |
|---|---|
| プロバイダー | クラウドプラットフォーム(AWS、GCP、Azure、Cloudflare)と連携するプラグイン |
| リソース | 単一のインフラストラクチャ コンポーネント (EC2 インスタンス、RDS データベース、S3 バケット) |
| データソース | 既存のインフラストラクチャへの読み取り専用の参照 |
| 変数 | 再利用可能な構成の入力パラメータ |
| 出力 | Terraform 構成からエクスポートされた値 |
| 状態 | Terraform が管理するものとその現在の属性の記録 |
| モジュール | 定義されたインターフェースを持つ再利用可能なリソースのグループ |
最初の Terraform 構成
Web アプリケーション用の AWS VPC と EC2
# providers.tf
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "ecosire-terraform-state"
key = "production/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
provider "aws" {
region = var.aws_region
}
# variables.tf
variable "aws_region" {
type = string
default = "us-east-1"
}
variable "environment" {
type = string
default = "production"
}
variable "instance_type" {
type = string
default = "t3.large"
}
# main.tf
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
Environment = var.environment
ManagedBy = "terraform"
}
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-${count.index + 1}"
}
}
resource "aws_instance" "app" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
subnet_id = aws_subnet.public[0].id
vpc_security_group_ids = [aws_security_group.app.id]
key_name = aws_key_pair.deploy.key_name
root_block_device {
volume_size = 50
volume_type = "gp3"
encrypted = true
}
tags = {
Name = "${var.environment}-app"
Environment = var.environment
}
}
resource "aws_db_instance" "postgres" {
identifier = "${var.environment}-db"
engine = "postgres"
engine_version = "17"
instance_class = "db.t3.medium"
allocated_storage = 50
max_allocated_storage = 200
storage_encrypted = true
db_name = "ecosire"
username = "app"
password = var.db_password
vpc_security_group_ids = [aws_security_group.db.id]
db_subnet_group_name = aws_db_subnet_group.main.name
backup_retention_period = 7
backup_window = "03:00-04:00"
maintenance_window = "sun:04:00-sun:05:00"
skip_final_snapshot = false
final_snapshot_identifier = "${var.environment}-db-final"
tags = {
Environment = var.environment
}
}
再利用可能なインフラストラクチャ用のモジュール
Web アプリケーション モジュールの作成
# modules/web-app/main.tf
variable "name" {
type = string
}
variable "environment" {
type = string
}
variable "instance_type" {
type = string
default = "t3.medium"
}
variable "vpc_id" {
type = string
}
variable "subnet_ids" {
type = list(string)
}
resource "aws_lb" "app" {
name = "${var.name}-${var.environment}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = var.subnet_ids
}
resource "aws_lb_target_group" "app" {
name = "${var.name}-${var.environment}-tg"
port = 3000
protocol = "HTTP"
vpc_id = var.vpc_id
health_check {
path = "/health"
healthy_threshold = 2
unhealthy_threshold = 3
interval = 30
}
}
resource "aws_autoscaling_group" "app" {
name = "${var.name}-${var.environment}-asg"
min_size = 2
max_size = 10
desired_capacity = 2
vpc_zone_identifier = var.subnet_ids
target_group_arns = [aws_lb_target_group.app.arn]
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
tag {
key = "Name"
value = "${var.name}-${var.environment}"
propagate_at_launch = true
}
}
output "alb_dns_name" {
value = aws_lb.app.dns_name
}
モジュールの使用
# environments/production/main.tf
module "web" {
source = "../../modules/web-app"
name = "ecosire-web"
environment = "production"
instance_type = "t3.large"
vpc_id = module.network.vpc_id
subnet_ids = module.network.public_subnet_ids
}
module "api" {
source = "../../modules/web-app"
name = "ecosire-api"
environment = "production"
instance_type = "t3.large"
vpc_id = module.network.vpc_id
subnet_ids = module.network.public_subnet_ids
}
状態管理
S3 によるリモート状態
# Bootstrap: create the state bucket and DynamoDB table manually or with a separate config
resource "aws_s3_bucket" "terraform_state" {
bucket = "ecosire-terraform-state"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
DynamoDB を介した状態ロックにより、2 人のエンジニアが terraform apply を同時に実行することがなくなり、状態が破損する可能性があります。
状態ファイルのセキュリティ
Terraform 状態ファイルには、データベース パスワード、API キー、リソース ID などの機密情報が含まれています。保護してください:
- 保存時の暗号化: S3 バケットのバージョン管理 + サーバー側の暗号化
- 転送中の暗号化: 状態アクセスの場合のみ HTTPS
- アクセスを制限: 状態を読み取り/書き込みできるユーザーを制限する IAM ポリシー
- Git には決してコミットしないでください: 状態ファイルをバージョン管理に含めてはなりません
- バージョニングを有効にする: S3 バージョニングにより、破損した状態から回復できます
CI/CD の統合
GitHub アクション Terraform パイプライン
name: Terraform
on:
pull_request:
paths: ['infrastructure/**']
push:
branches: [main]
paths: ['infrastructure/**']
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
working-directory: infrastructure/environments/production
- name: Terraform Plan
run: terraform plan -out=tfplan
working-directory: infrastructure/environments/production
- name: Comment PR with plan
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const plan = require('fs').readFileSync('infrastructure/environments/production/tfplan.txt', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Terraform Plan\n\`\`\`\n${plan}\n\`\`\``
});
apply:
needs: plan
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform Apply
run: terraform apply -auto-approve
working-directory: infrastructure/environments/production
マルチ環境戦略
| 環境 | 目的 | インスタンスのサイズ | コスト目標 |
|---|---|---|---|
| 開発 | 機能テスト | t3.micro / t3.small | <$100/月 |
| ステージング | 実稼働前検証 | ミラーの生産(小型) | 生産量の ~30% |
| 制作 | ライブ交通状況 | 荷物に適したサイズ | 最適化された |
Terraform ワークスペースまたは環境ごとに別のディレクトリを使用します。
infrastructure/
modules/
web-app/
database/
network/
environments/
development/
main.tf
terraform.tfvars
staging/
main.tf
terraform.tfvars
production/
main.tf
terraform.tfvars
よくある質問
Terraform と Pulumi --- どちらを選択すべきですか?
宣言型構成を好む運用エンジニアがチームに含まれている場合は、Terraform を使用します。チームが開発者中心で、TypeScript または Python でインフラストラクチャを記述することを好む場合は、Pulumi。 Terraform には、より大きなエコシステムとより多くのコミュニティ モジュールがあります。 Pulumi は初期学習曲線が急になりますが、複雑なロジックに対してより柔軟です。
既存のインフラストラクチャを Terraform にインポートするにはどうすればよいですか?
terraform import を使用して、既存のリソースを Terraform 管理下に置きます。例: terraform import aws_instance.app i-1234567890abcdef0。インポート後、一致する構成を書き込みます。 Terraform 1.5 以降では、一括インポート用の構成ファイル内のインポート ブロックがサポートされています。
Terraform でシークレットをどのように処理すればよいですか?
シークレットを Terraform ファイルに決してコミットしないでください。 terraform.tfvars (Git から除外)、環境変数 (TF_VAR_db_password)、またはシークレット マネージャー (AWS Secrets Manager、HashiCorp Vault) を使用します。機密変数を sensitive = true でマークして、プラン出力に表示されないようにします。
Terraform の管理コストはいくらですか?
Terraform 自体は無料でオープンソースです。 Terraform Cloud には、リモート状態および計画/適用を備えた最大 5 ユーザーの無料利用枠があります。主なコストは、学習曲線 (経験豊富なエンジニアの場合 20 ~ 40 時間) と継続的なメンテナンス (月あたり 2 ~ 4 時間) です。これは、手動のインフラストラクチャ管理で節約された時間によって相殺されます。
次に何が起こるか
Terraform は、自動化されたインフラストラクチャの基盤を提供します。これを、自動展開のために CI/CD パイプライン、運用の可視化のために 監視、復元力のために 災害復旧 と組み合わせます。
インフラストラクチャ自動化コンサルティングについては ECOSIRE にお問い合わせ、完全なロードマップについては 中小企業向け DevOps ガイド をご覧ください。
ECOSIRE によって発行 -- 企業のクラウド インフラストラクチャの自動化を支援します。
執筆者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
関連記事
会計自動化: 2026 年に手動簿記を廃止
2026 年には、銀行フィードの自動化、レシートのスキャン、請求書の照合、AP/AR の自動化、月末締めの高速化により簿記を自動化します。
ビジネス向け AI エージェント: 決定版ガイド (2026)
ビジネス向け AI エージェントの包括的なガイド: AI エージェントの仕組み、ユースケース、実装ロードマップ、コスト分析、ガバナンス、2026 年の将来のトレンド。
AI エージェント vs RPA: どちらの自動化テクノロジーがあなたのビジネスに適していますか?
LLM を利用した AI エージェントと従来の RPA ボットの詳細な比較 - 機能、コスト、ユースケース、適切なアプローチを選択するための意思決定マトリックス。