この記事は、フューチャー Advent Calendar 2025 の18日目の記事です。
1. はじめに : なぜこの話を書くのか
こんにちは。HIGの福島です。
私は今年11月にキャリア入社し、これまで一貫してインフラエンジニアとして業務に携わってきました。
前職では複数のIaCツールを利用しており、中でもAWS CDKを使う機会が比較的多い環境でした。
現在参画しているプロジェクトでは、IaCツールとしてTerraformを利用しています。
日々タスクを進める中で、ふと次のような疑問を持ちました。
AWS CDKとTerraform、それぞれどんなユースケースに適しているのだろうか?
正直なところ私自身、「どのツールをどう使い分けるべきか」を深く考える場面はこれまでそう多くなく、基本的にはプロジェクトで選定されたツールを使う、というスタンスで業務に取り組んできました。
本記事は、「Terraformが良い / CDKが良い」と結論を出すことが目的ではありません。
この機会に各ツールの特徴をあらためて整理し、ユースケースごとの考え方を言語化してみたい
という思いから執筆しております。
※IaCツールは世の中に数多くありますが、今回は上記の経緯からTerraformとAWS CDKに絞って取り上げたいと思います。
2. 比較してみよう。TerraformとAWS CDK
どんなユースケースでどちらを使うのか。
それを考えるため、まずは両者を比較してみましょう。
Terraformの概要
TerraformはHashiCorp社(2025年3月にIBM社が買収)が開発するIaCツールで、AWS、Azure、GoogleCloudなどのクラウドサービスや各種SaaSを独自の宣言的なコード(HCL)で管理します。
裏側では、各クラウドプラットフォームのAPIを直接操作することで構築を行っています。
(例えば構築対象がAWSの場合、AWSが提供するAPIを呼び出すことでCreateやUpdateなどの操作を行っています)
HCL→APIの変換ロジックは各クラウドプラットフォーム・各サービス単位で作成されており、その開発元はHashiCorp + OSSコミュニティです。
AWS CDKの概要
AWS CDKは、AWS公式が提供しており、TypeScriptやPythonなどのプログラミング言語でAWSリソースを定義する、いわばクラウドベンダーネイティブなIaCツールです。
内部的にはCloudFormationテンプレートを生成しており、CloudFormationの実行により構築を行っています。
特徴の比較
それぞれの特徴を表でまとめると、以下のようになります。
| Terraform(for AWS) | AWS CDK | |
|---|---|---|
| 構築対象 | 各種クラウド、SaaS | AWS |
| 構築主体 | AWS API(Terraformが直接操作) | AWS CloudFormation(AWSマネージド) |
| 状態管理 | TerraformのStateファイル | CloudFormation Stack |
| 新AWSサービス対応タイミング | 変換ロジックが開発され次第 | CloudFormationに対応され次第 |
| 記述方法 | 宣言的(HCL) | 宣言的+命令的(TypeScript/Python 等) |
| 構築の条件分岐・ループ | 制限あり | 自由(言語機能そのまま) |
| 暗黙の補完 | しない(設定値は原則すべて明示的に記述する) | する(細かい設定はベストプラクティスに沿って補完される) |
上記の比較から、いくつか具体例を挙げましょう。
①対応サービスについて
実際に利用可能なサービスにはどれくらいの差があるのでしょうか。
Terraform AWS Providerは2025年時点で1,581個のリソースを公式にサポートしています。(厳密にいうとリソース単位のカウントではなくAPI単位のカウント)
これはAWSの多数のAPIをTerraformのリソースとして扱えるように実装されていることを示しています。(Terraform Registryより)
上記のページを見る限り、よほどニッチなサービスならともかく、ほとんどのシステム開発で利用する可能性のあるサービスはカバーしているように見えます。
AWS CDKは、1,502個のResourceTypes操作(AWS::EC2::Instance Createのような粒度)を公式にサポートしています。(AWS - CloudFormationリソース仕様より)
これはTerraformでいうAPI単位でのリソース量カウントに相当する値です。
両者を比較すると、TerraformとAWS CDKはほぼ同じ量のリソース操作をサポートしていると言えます。
②対応クラウドプラットフォームについて
AWS CDKはAWS専用のIaCツールであり、AWSサービスを前提とした設計やベストプラクティスに強く最適化されています。
そのため、構築対象が明確にAWSに限定されている場合や、AWSの進化を最大限に取り込みたい場合に向いています。
一方、TerraformはAWSだけでなくAzureやGoogle Cloudといった主要クラウドをはじめ、各種SaaSやオンプレミス環境まで扱うことができます。(HashiCorp - What is Terraform?より)
そのため、将来的にクラウドを跨ぐ可能性があるシステムや、複数のクラウド・サービスを組み合わせて構成される基盤においては、Terraformの特性が活きやすいと言えます。
また、「今はAWSオンリーだが、将来的な選択肢は残しておきたい」、「特定クラウドへの依存度を上げすぎたくない」といった場合にも、Terraformを選択しておくことで、構成管理の考え方や運用フローを大きく変えずに対応できる余地が生まれます。
③SaaS対応について
Terraformの特徴の一つに、クラウドリソースだけでなく、各種SaaSも同じIaCの仕組みで管理できるという点があります。
Terraformは、Providerという仕組みを通じて、GitHub、Datadog、PagerDuty、Auth0など、HTTP APIを持つ外部サービスをリソースとして扱うことができます。
これにより、インフラだけでなく、CI/CD、監視、通知、認証といった運用基盤全体をコードで管理することが可能になります。
例えば、AWS上のインフラ構築と同時に、GitHubのリポジトリ設定やDatadogの監視定義をTerraformで管理するといった構成も、同じツール・同じワークフローで実現できます。
これにより、設定の属人化を防ぎやすくなり、変更履歴の追跡や再現性の確保といった面でもメリットがあります。
TerraformでDatadogのモニターを管理する方法を試してみた
GitHubをコードで管理! Terraformを導入して安全な管理を実現しました
AWS CDK(およびその基盤であるCloudFormation)は、AWSが公式に管理するリソースのみを対象としているため、AWS外のSaaSを同じ粒度・体験で管理することは難しいのが実情です。
そのため、AWSリソースはCDK、SaaS設定は手作業や別ツール、といった形で管理が分かれるケースも少なくありません。
こうした点から、インフラだけでなく運用に関わる周辺サービスまで含めてIaC化したい場合には、Terraformが向いていると言えます。
④記述方法について
続けて、コードの記述方法を比較しましょう。
TerraformはHCLを用い、リソースのあるべき状態を宣言します。
処理の順序やAPIの呼び出し手順はTerraform側が判断し、ユーザーは構成そのものに集中できる設計になっています。
resource "aws_s3_bucket" "example" {
bucket = "example-bucket"
}
一方、AWS CDKはTypeScriptやPythonなどの一般的なプログラミング言語を使ってインフラを定義します。
ユーザーは、リソースのあるべき状態を宣言しつつ、構築順序や構築条件などを、条件分岐やループなどを用いてロジックとして組み立て命令することができます。
例えば、環境によって作成するS3バケットを切り替えたい場合、
次のように自然な条件分岐を書くことができます。
if (env === 'prod') {
new s3.Bucket(this, 'ProdBucket', {
bucketName: 'prod-example-bucket',
versioned: true,
});
} else {
new s3.Bucket(this, 'DevBucket', {
bucketName: 'dev-example-bucket',
});
}
また、設定値の配列をもとに、複数のリソースをループで生成することも可能です。
const bucketNames = ['images', 'logs', 'backup'];
for (const name of bucketNames) {
new s3.Bucket(this, `${name}Bucket`, {
bucketName: `example-${name}-bucket`,
});
}
Terraformにもcountやfor_each、条件演算子といった仕組みは存在しますが、これらは制御構文ではなく構成補助のため、条件が増えたり分岐がネストしたりするとコードが複雑化しがちです。※module設計やlocalsの活用によって複雑な構成を整理することは可能。
例えば、環境・リージョン・機能の組み合わせが多く構成パターンが指数的に増えるようなケース、既存リソースの状態に応じて構成を分岐したりリソースを再利用したりするケースなどは、CDKが向いていると言えます。
⑤暗黙の補完について
Terraformは、基本的にユーザーが指定した内容のみを忠実に構築するツールです。
そのため、設定値は原則としてすべて明示的に記述します。
例えば、Lambdaで何らかのコードを動かしたいときは以下のような定義をします。
resource "aws_iam_role" "lambda" {
name = "example-lambda-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Effect = "Allow",
Principal = { Service = "lambda.amazonaws.com" },
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy_attachment" "basic" {
role = aws_iam_role.lambda.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_cloudwatch_log_group" "lambda" {
name = "/aws/lambda/example-fn"
retention_in_days = 30
}
resource "aws_lambda_function" "fn" {
function_name = "example-fn"
role = aws_iam_role.lambda.arn
runtime = "nodejs18.x"
handler = "index.handler"
filename = "lambda.zip"
source_code_hash = filebase64sha256("lambda.zip")
timeout = 10
depends_on = [aws_iam_role_policy_attachment.basic]
}
一方、AWS CDK(正確にはその基盤であるCloudFormation)では、
AWS側が推奨するデフォルト設定や暗黙的な依存関係をある程度補完する仕組みがあります。
そのため、Lambdaを動かしたい場合は関数定義中心で記述することができます。
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Duration, Stack } from 'aws-cdk-lib';
export class MyStack extends Stack {
constructor(scope: any, id: string) {
super(scope, id);
const fn = new lambda.Function(this, 'Fn', {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
timeout: Duration.seconds(10),
});
// IAMロールやポリシーなどは書かなくても自動構築・アタッチされる
}
}
Terraformは、すべての設定値を明示的に記述するため、「意図しない挙動を防げる」「構成がブラックボックス化しない」というメリットがあります。
一方、AWS CDKは、すべての設定値を明示的に記述するという選択肢以外に、「すべてを細かく指定しない」という選択肢が存在するメリットがあります。
後者を選択した場合、リソース構築やリソース間依存関係の解決、設定値のデフォルト値補完が、AWSのベストプラクティスに沿い自動で行われます。
例えば、「まずは安全で標準的な構成を素早く作りたい」、「AWSの推奨にできるだけ乗りたい」といったユースケースではAWS CDKが向いていると言え、すべてを明示的に制御したい場合はどちらを選んでも良いと言えます。
4. まとめ
前章までの評価を踏まえ、比較観点を簡易的にまとめると次のようになります。
| 観点 | Terraform(for AWS) | AWS CDK |
|---|---|---|
| クラウド前提 | マルチクラウド志向 | AWS前提 |
| SaaS対応 | 対応 | AWS外SaaSは非対応 |
| 構築パターン | シンプル・固定 | 複雑・可変 |
| 環境差分 | 少ない / 定型 | 多い / 条件分岐あり |
| フェーズ | 本番・長期運用向き | PoC・検証・初期構築・本番・長期運用向き |
| 設計スタイル | 明示的・厳密 | 明示的・厳密 or AWSに委ねる |
IaCツールは目的ではなく手段です。
ユースケースに応じて柔軟に選択肢を持つことが、結果的にシステム全体の価値を高めることにつながるのではないでしょうか。
- 価値提供スピード
- 開発・運用コスト
- 将来の不確実性
これらのトレードオフを踏まえた上で、「このプロジェクトでは何を最優先するのか」を考えることが重要です。
本記事が、「なぜこのツールを使うのか」を改めて考えるきっかけとなり、
IaCツール選定を“前提”ではなく“意思決定”として捉える一助になれば幸いです。
