PR

Terraform vs CloudFormation徹底比較:AWSインフラで両方使った結論【2026年版】

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点は共通の鉄則だ。ツール選択よりも運用設計が先。これが自分が障害から学んだ結論だ。


関連記事

参考リンク

コメント

タイトルとURLをコピーしました