OSSのIaC比較:OpenTofu vs Terraform vs Pulumi でインフラをコードで管理する
オープンソースラボ編集部 ・ 2026年6月14日
OSSのIaC比較:OpenTofu vs Terraform vs Pulumi でインフラをコードで管理する
HashiCorp Terraform(BSL変更後・一部有料)・AWS CDK(AWS専用)に対して、OpenTofu(Terraform完全互換OSSフォーク・MPLv2)・Pulumi(Python/TypeScript/Go/C#でIaC)・Crossplane(Kubernetes CRDでクラウドリソース管理)はOSSのInfrastructure as Codeツールです。
IaCが解決する問題
- 再現性: 同じHCL/コードから同じインフラを何度でも構築できる
- ドリフト検出: インフラの手動変更を検出して「コードと現実のズレ」を可視化
- 変更履歴: gitでインフラ変更をトラッキング・PRレビュー・ロールバック
- マルチクラウド: AWS・GCP・Azureのリソースを1つのツールで管理
- チームコラボ: Terraform Cloudのリモートstate管理なしで複数人で安全に運用
主要ツールの概要
OpenTofu
2023年にHashiCorpがTerraformのライセンスをMPLv2からBSLに変更したことへの対抗として、Linux Foundation傘下でコミュニティがフォークしたOSSです。GitHubスター24k+。Terraform 1.6と完全互換であり、.tfファイルをそのまま使えます。state・プロバイダー・モジュールはTerraformと共用できます。商用利用制限なし・コミュニティ主導・MPLv2ライセンスが特徴。
# OpenTofuのインストール(Linux/Mac)
brew install opentofu
# またはシェルスクリプト
curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh | sh
# Windowsはchocolateyで
choco install opentofu
# バージョン確認
tofu --version
# main.tf - AWS VPCとEC2インスタンスをOpenTofuで管理
terraform {
required_version = ">= 1.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# Terraform Cloud互換のリモートstate(S3を使う場合)
backend "s3" {
bucket = "my-tfstate-bucket"
key = "prod/vpc/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "tfstate-lock"
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
ManagedBy = "opentofu"
Environment = var.environment
Project = var.project_name
}
}
}
# VPCとサブネット
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = { Name = "${var.project_name}-vpc" }
}
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index}.0/24"
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = { Name = "${var.project_name}-public-${count.index + 1}" }
}
# ECSクラスター(Next.jsアプリのコンテナ実行環境)
resource "aws_ecs_cluster" "main" {
name = "${var.project_name}-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
}
# Supabaseのアプリ設定をSSMパラメータストアで管理
resource "aws_ssm_parameter" "supabase_url" {
name = "/${var.project_name}/supabase/url"
type = "SecureString"
value = var.supabase_url
}
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main.id
}
output "ecs_cluster_arn" {
description = "ECSクラスターのARN"
value = aws_ecs_cluster.main.arn
}
# OpenTofuの基本的なワークフロー
cd infra/
# 初期化(プロバイダーとモジュールをダウンロード)
tofu init
# 変更のプレビュー(what-if)
tofu plan -out=tfplan
# 変更を実際に適用
tofu apply tfplan
# 現在のインフラ状態を確認
tofu show
# インフラを破棄(開発環境の削除)
tofu destroy -target=aws_ecs_cluster.main
# ドリフト検出(コードとクラウドのズレを確認)
tofu plan -refresh-only
# modules/nextjs-app/main.tf - 再利用可能なモジュール
# Next.jsアプリをECS Fargateにデプロイするモジュール
variable "app_name" { type = string }
variable "image_uri" { type = string }
variable "cpu" { default = 256 }
variable "memory" { default = 512 }
variable "container_port" { default = 3000 }
resource "aws_ecs_task_definition" "app" {
family = var.app_name
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = var.cpu
memory = var.memory
execution_role_arn = aws_iam_role.ecs_task_execution.arn
container_definitions = jsonencode([
{
name = var.app_name
image = var.image_uri
essential = true
portMappings = [
{ containerPort = var.container_port, protocol = "tcp" }
]
environment = [
{ name = "NODE_ENV", value = "production" },
]
secrets = [
{ name = "SUPABASE_URL", valueFrom = "/app/supabase/url" },
{ name = "SUPABASE_KEY", valueFrom = "/app/supabase/key" },
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = "/ecs/${var.app_name}"
"awslogs-region" = "ap-northeast-1"
"awslogs-stream-prefix" = "ecs"
}
}
}
])
}
Pulumi
2017年に公開されたOSSのInfrastructure as Codeツールです。GitHubスター22k+。HCLではなくPython・TypeScript・Go・C#などの汎用言語でインフラを記述できます。既存のプログラミングスキルをそのまま活かせ、ループ・条件分岐・関数・クラスでインフラを抽象化できます。Terraform/OpenTofuのプロバイダーをそのまま使えるPulumiTFプロバイダーブリッジもあります。
# Pulumi Python でGCPのCloud Runにアプリをデプロイ
# pip install pulumi pulumi-gcp
import pulumi
import pulumi_gcp as gcp
config = pulumi.Config()
project = config.require("project")
region = config.get("region") or "asia-northeast1"
# Cloud Run サービス
cloud_run_service = gcp.cloudrun.Service(
"nextjs-app",
location=region,
template=gcp.cloudrun.ServiceTemplateArgs(
metadata=gcp.cloudrun.ServiceTemplateMetadataArgs(
annotations={
"autoscaling.knative.dev/maxScale": "10",
"autoscaling.knative.dev/minScale": "1",
}
),
spec=gcp.cloudrun.ServiceTemplateSpecArgs(
containers=[
gcp.cloudrun.ServiceTemplateSpecContainerArgs(
image=f"gcr.io/{project}/nextjs-app:latest",
resources=gcp.cloudrun.ServiceTemplateSpecContainerResourcesArgs(
limits={"cpu": "1000m", "memory": "512Mi"},
),
envs=[
gcp.cloudrun.ServiceTemplateSpecContainerEnvArgs(
name="NODE_ENV",
value="production",
),
gcp.cloudrun.ServiceTemplateSpecContainerEnvArgs(
name="SUPABASE_URL",
value_from=gcp.cloudrun.ServiceTemplateSpecContainerEnvValueFromArgs(
secret_key_ref=gcp.cloudrun.ServiceTemplateSpecContainerEnvValueFromSecretKeyRefArgs(
name="supabase-url",
key="latest",
)
),
),
],
)
]
),
),
traffics=[gcp.cloudrun.ServiceTrafficArgs(percent=100, latest_revision=True)],
)
# 全員がアクセスできる公開IAMポリシー
gcp.cloudrun.IamMember(
"allow-all",
location=region,
service=cloud_run_service.name,
role="roles/run.invoker",
member="allUsers",
)
pulumi.export("url", cloud_run_service.statuses[0].url)
// Pulumi TypeScript でVercel風にNext.jsをCloudflare Pagesにデプロイ
import * as pulumi from "@pulumi/pulumi";
import * as cloudflare from "@pulumi/cloudflare";
const config = new pulumi.Config();
const accountId = config.require("cloudflareAccountId");
// Cloudflare Pagesプロジェクト
const pagesProject = new cloudflare.PagesProject("opensourcelab", {
accountId,
name: "opensourcelab",
productionBranch: "main",
buildConfig: {
buildCommand: "npm run build",
destinationDir: ".next",
rootDir: "/",
},
source: {
type: "github",
config: {
owner: "myorg",
repoName: "opensourcelab",
productionBranch: "main",
prCommentsEnabled: true,
deploymentsEnabled: true,
},
},
deploymentConfigs: {
production: {
environmentVariables: {
NODE_ENV: "production",
NEXT_PUBLIC_SUPABASE_URL: config.requireSecret("supabaseUrl"),
},
},
},
});
export const pagesUrl = pagesProject.subdomain;
機能比較表
| 比較項目 | OpenTofu | Terraform | Pulumi |
|---|---|---|---|
| ライセンス | MPLv2 | BSL(商用制限) | Apache 2.0 |
| 言語 | HCL | HCL | Python/TS/Go/C# |
| Terraform互換 | ✅(完全) | — | △(ブリッジ) |
| マルチクラウド | ✅ | ✅ | ✅ |
| ループ・条件分岐 | HCL限定 | HCL限定 | 完全 |
| GitHub Stars | 24k+ | 43k+ | 22k+ |
IaCで管理するインフラのコンテナをDevOpsカテゴリ/categories/devopsのPortainer・Rancher・k9sで運用管理できます。IaCのCI/CDパイプラインにDevOpsカテゴリ/categories/devopsのGitHub Actionsを組み合わせて変更をPR単位でレビューします。
FAQ
Q. TerraformのコードをOpenTofuに移行するには何が必要ですか?
A. 多くの場合、コードの変更ゼロで移行できます。手順: ①terraformコマンドをtofuに置き換える②terraform.tfstateは共通フォーマットのためそのまま使える③既存のTerraformプロバイダー(AWS・GCP・Azure等)はOpenTofuでもそのまま動く④terraform.required_providersのsourceは変更不要。注意点: BSLのHashiCorp商用プロバイダー(HCP Vault・HCP Consul等)の一部はOpenTofuで利用不可の場合がある。移行リスクが最小なのはHCLのままtofuコマンドで動かすOpenTofu、プログラミング言語でインフラを書きたいならPulumiという選択肢です。
Q. OpenTofuとTerraform Cloudのstate管理の互換性はありますか?
A. Terraform Cloud: OpenTofuはTerraform Cloudのリモートstateには非対応です(Terraform Cloudの商用サービスのため)。代替: ①S3+DynamoDB(AWS標準構成・最も一般的)②GCS(GCP環境)③Azure Blob Storage④Spacelift・Env0・Terrateam(Terraform Cloudと互換のOSSバックエンド)⑤OpenTofu Registryのトフォーム: backend "s3"でリモートstateを管理するのが最もシンプルです。OSSのTerraform Cloudクローン「Atlantis」もOpenTofuと互換性があります。
Q. PulumiとTerraformの学習コストはどのくらい違いますか?
A. HCLを知っているチーム: TerraformよりOpenTofuの方が圧倒的に移行が楽(同じコードで動く)。Pythonエンジニアが多いチーム: PulumiのPythonがHCLより直感的。for文・if文・クラス継承でDRYなインフラコードが書ける。TypeScriptチーム(Next.jsメイン): PulumiのTypeScriptで型安全なインフラコードが書ける。学習曲線: HCL(OpenTofu/Terraform)は2〜3日で基礎習得。Pulumiは対象言語を知っていれば1〜2日で習得。IaCをゼロから始めるならPulumiのPythonがプログラマにとって最も自然です。
Q. モノレポでOpenTofuのstateを環境別(dev/staging/prod)に分けるには?
A. ディレクトリ構造でワークスペースを分けるのが最もシンプルです。
infra/
environments/
dev/
main.tf # devの設定をimport
backend.tf # S3 state: infra/dev/terraform.tfstate
staging/
main.tf
backend.tf # S3 state: infra/staging/terraform.tfstate
prod/
main.tf
backend.tf # S3 state: infra/prod/terraform.tfstate
modules/
vpc/
ecs/
rds/
各環境ディレクトリでtofu init→tofu plan→tofu apply。モジュールを使ってdev・prodでパラメータだけ変える構成が再現性が高く推奨です。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| Terraform移行・HCL継続・OSS化 | OpenTofu |
| Python/TypeScript/Goでインフラをコード化 | Pulumi |
| Kubernetes上でクラウドリソースをCRD管理 | Crossplane |