Terraform vs CloudFormation徹底比較:AWSインフラで両方使った結論【2026年版】
AWSのIaCツールを「Terraformにすべきか、CloudFormationで行くべきか」で迷う時間は長ければ長いほど無駄だ。自分はその選択を3回間違え、そのたびに移行コストを払った。この記事はその失敗から逆算して書いている。
【Haruの実体験】tfstate管理を甘く見てチームが崩壊した話
AWS専業の自分がTerraformを本格採用したのは2021年頃だ。当時、5人チームで月額200万円規模のAWSインフラをTerraformで管理し始めた。最初の6ヶ月は快調だった。
崩壊の兆しは「tfstateファイルをローカルで管理していた」ことから始まった。メンバーが2人同時に terraform apply を実行し、stateファイルが競合。本番のECSサービスが意図しないロールバックを起こした。ダウンタイムは4時間。クライアントへの損害賠償交渉が1ヶ月続いた。
その後にS3+DynamoDBのリモートbackendに移行したが、今度は別の問題が出た。本番環境のセキュリティグループを手動で変更したメンバーがいて、次回の terraform apply でその変更が上書きされた。検知から復旧まで2時間、原因特定にさらに3時間かかった。
この2つの障害を経て、「Terraformは強力だが、チーム運用の設計を最初から正しくやらないと、手動オペレーションより危険になる」と確信した。一方でCloudFormationは、同じく使っていたが、そういう種類の事故は起きなかった。ただし別の不満があった——それも後述する。
1. 2026年時点の正直な比較
1.1 基本スペック
| 項目 | Terraform (OpenTofu含む) | CloudFormation |
|---|---|---|
| 開発元 | HashiCorp / OpenTofu | AWS |
| ライセンス | BSL 1.1(Terraform)/ MPL2.0(OpenTofu) | AWSサービス |
| 言語 | HCL | YAML / JSON |
| マルチクラウド | ◎(200以上のプロバイダー) | ✕(AWSのみ) |
| stateファイル | 要管理(S3+DynamoDB推奨) | AWS管理(不要) |
| ドリフト検知 | terraform plan で差分確認 |
CloudFormation Drift Detection |
| 無料プランの制約 | なし(OSS) | なし |
1.2 2026年最新の動向
TerraformのBSL問題とOpenTofu
2023年8月にHashiCorpがTerraformのライセンスをMPL2.0からBSL(Business Source License)1.1に変更した。商用サービスとしてTerraformを再配布・提供する場合に制限が生じる。この変更を受けて、CNCF傘下でOSSフォーク版の「OpenTofu」が2024年1月にGA。2026年6月時点でv1.8系が安定稼働しており、Terraformとの構文互換性も高い。
長期的にTerraformを使い続けるなら、今後の移行コストを見越してOpenTofuの採用を検討する価値がある。
CloudFormation IaC Generator(2024年GA)
既存のAWSリソースからCloudFormationテンプレートを自動生成する機能。従来は手書きが必要だった既存環境のIaC化が大幅に簡素化された。「手動で作ったAWS環境をCloudFormationに取り込む」作業が現実的になったのは大きい。
2. どちらを選ぶべきか:判断基準を明確にする
「どちらが優れているか」という問いに意味はない。「自分たちのユースケースにどちらが合っているか」が正しい問いだ。
AWSオンリーかつ組織のIAM管理が厳格な場合 → CloudFormation
CloudFormationはAWSアカウント内のIAMロールで完結する。外部のstateファイル管理インフラが不要で、aws cloudformation deploy 一発で完結する。
特にStackSetsを使ったマルチアカウント展開は、CloudFormationの方が圧倒的に管理しやすい。Terraformでマルチアカウントを扱うには、各アカウントのprovider設定やbackend設定を個別に管理する必要があり、規模が大きくなるほど複雑になる。
# CloudFormation: マルチアカウントへのStackSets展開例
AWSTemplateFormatVersion: '2010-09-09'
Resources:
SecurityBaseline:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-public-access-prohibited
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_ACCESS_PROHIBITED
マルチクラウドまたはAWS外のリソース管理が必要 → Terraform
AWSだけでなくGitHub・Datadog・Cloudflareなどのリソースを同一のIaCで管理したい場合、Terraformの200以上のプロバイダーは強力だ。
# Terraform: AWSとGitHubを同時管理する例
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
github = {
source = "integrations/github"
version = "~> 6.0"
}
}
}
resource "aws_iam_oidc_provider" "github_actions" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}
resource "github_actions_environment_secret" "aws_role_arn" {
repository = "my-repo"
environment = "production"
secret_name = "AWS_ROLE_ARN"
plaintext_value = aws_iam_role.github_actions.arn
}
3. Terraform運用の実践的な落とし穴と対策
3.1 tfstate競合問題の完全対策
自分が踏んだ障害の根本原因。S3+DynamoDBによるリモートbackendとstate lockingは必須だ。
# backend.tf(最初から設定することが鉄則)
terraform {
backend "s3" {
bucket = "my-terraform-state-prod"
key = "services/api/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
dynamodb_table を省略すると、複数人での同時実行でstateが壊れる。自分が踏んだのがこれだ。
3.2 ドリフト検知の定期実行
手動変更を検知するために、CI/CDで定期的に terraform plan を実行してdiffをSlackに通知する仕組みを作ると、「誰かが手動変更した」問題を早期発見できる。
# GitHub Actions: 毎朝9時にドリフト検知
name: Terraform Drift Detection
on:
schedule:
- cron: '0 0 * * 1-5' # 平日9時(JST)
jobs:
drift-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.8.0"
- name: Terraform Plan
run: terraform plan -detailed-exitcode 2>&1 | tee plan_output.txt
continue-on-error: true
- name: Notify Drift
if: failure()
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-d '{"text":"⚠️ Terraform drift detected in production!"}'
3.3 Terraformモジュールの設計原則
再利用可能なモジュールを書く際の実践的なルール:
# modules/ecs-service/main.tf
# 変数は必須・オプションを明確に分ける
variable "service_name" {
description = "ECSサービス名"
type = string
# defaultなし = 必須
}
variable "desired_count" {
description = "起動タスク数"
type = number
default = 2 # defaultあり = オプション
}
variable "enable_autoscaling" {
description = "Auto Scalingの有効化"
type = bool
default = false
}
4. CloudFormationの実践的な使い方
4.1 ChangeSetを使った安全なデプロイ
CloudFormationの最大の利点はAWSが状態を管理してくれること。ChangeSetで変更内容を事前確認してからデプロイする習慣が重要だ。
# ChangeSet作成 → レビュー → 実行の流れ
aws cloudformation create-change-set \
--stack-name prod-api \
--template-body file://template.yaml \
--change-set-name deploy-$(date +%Y%m%d-%H%M%S) \
--capabilities CAPABILITY_IAM
# 変更内容の確認
aws cloudformation describe-change-set \
--stack-name prod-api \
--change-set-name deploy-20260616-091523
# 問題なければ実行
aws cloudformation execute-change-set \
--stack-name prod-api \
--change-set-name deploy-20260616-091523
4.2 ドリフト検知
手動変更を検知するCloudFormation Drift Detectionは、Terraformの plan に相当する機能として使える。
# ドリフト検知の実行
aws cloudformation detect-stack-drift \
--stack-name prod-api
# 結果確認(完了まで数分かかる)
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id <id>
5. 実際のプロジェクトでの選択事例
自分が関わったプロジェクトで実際に下した選択と、その後の評価をまとめる。
| プロジェクト | 選択 | 理由 | 結果 |
|---|---|---|---|
| SaaS基盤(AWSのみ、5アカウント) | CloudFormation + StackSets | マルチアカウント管理のシンプルさ | ✅ 正解。移行コストゼロ |
| DevOps基盤(AWS+GitHub+Datadog) | Terraform | マルチプロバイダーが必須 | ✅ 正解。一元管理できた |
| スタートアップ(3人チーム) | Terraform(tfstate管理なし) | 手軽さ優先 | ❌ 失敗。state競合で障害 |
| エンタープライズ(100+リソース) | CloudFormation | 既存スタックのIaC化 | ✅ IaC Generatorで移行3日 |
まとめ:選択の基準を持つことが重要
Terraformが優れているか、CloudFormationが優れているかは問いが間違っている。
Terraformを選ぶべき状況:
– マルチクラウド(AWS以外も管理)
– GitHub・Datadog等の外部サービスも一緒に管理したい
– チームにHCLを書ける人がいる
– tfstateのリモート管理とlock設定を最初から正しく行える
CloudFormationを選ぶべき状況:
– AWSオンリー
– マルチアカウントをStackSetsで管理したい
– IAM管理をシンプルに保ちたい
– tfstate管理のオーバーヘッドを避けたい
どちらを選んでも、「最初からドリフト検知を仕込む」「手動変更を禁じるルールを作る」の2点は共通の鉄則だ。ツール選択よりも運用設計が先。これが自分が障害から学んだ結論だ。
関連記事
- AWS CDK実践ガイド:TypeScriptでインフラをコード化する現代的アプローチ
- IaCエンジニアのキャリア戦略:高単価フリーランスへの道
- AWS Lambda パフォーマンス最適化完全ガイド
- 副業から年収2000万フリーランスへ:段階的独立戦略

コメント