こうした疑問は、CDKTFを調べ始めたエンジニアが必ず直面する壁です。公式ドキュメントは基本的な使い方を説明していますが、GitHub ActionsへのCI組み込みやHCLとの設計使い分けまで踏み込んだ情報が少なく、導入検討が止まるケースが典型的です。
この記事では、Node.js 18以降・cdktf-cli 0.20系を想定環境として、CDK for Terraform(CDKTF)の仕組みから始め、TypeScriptによるAWSリソース定義、GitHub ActionsへのCI組み込み、HCLとの使い分け判断まで解説します。
この記事のポイント
・cdktf synthでTerraform JSONへ変換できる
・cdktf deployでCI/CDから自動適用が可能
・ロジックが複雑な構成にCDKTFは向く
・GitHub ActionsはNode.js+cdktf-cliで動く
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
CDK for Terraform(CDKTF)とは何か
CDK for Terraform(CDKTF)は、HashiCorpとAWSが共同開発したオープンソースのフレームワークです。TypeScript・Python・Go・Javaなどのプログラミング言語からTerraformの設定ファイル(JSON形式)を生成します。AWS CDKがCloudFormationのテンプレートを出力するのと同じ仕組みで、出力先がTerraform JSONになっています。通常のTerraformはHCL(HashiCorp Configuration Language)で記述しますが、CDKTFを使うとTypeScriptのクラスとしてリソースを定義できます。ループ・条件分岐・型チェックがそのまま利用でき、数十台以上のサーバー設定を繰り返し記述する手間がなくなります。
CDKTFの動作の流れ
・TypeScript(またはPython/Go等)でリソースを定義する
・
cdktf synth コマンドでTerraform JSON(cdktf.out/配下)を生成する・生成されたJSONを
terraform apply またはcdktf deployで適用するCDKTFは「コード→Terraform JSON変換器」であり、Terraform自体のステート管理・プロバイダーエコシステムはそのまま活用できます。既存のtfstateやS3バックエンドとも互換があります。
TypeScriptでAWSリソースを定義する基本手順
1. cdktf-cliのインストールとプロジェクト初期化
まずNode.js 18以降がインストールされていることを確認します。# Node.jsバージョン確認 node -v # 出力例(環境により異なります) # v20.17.0 # cdktf-cliをグローバルインストール npm install -g cdktf-cli@latest # バージョン確認 cdktf --version # 0.20.x
--local フラグで初期状態はローカルバックエンドを使用します。# TypeScriptテンプレートでプロジェクトを初期化(ローカルバックエンド) cdktf init --template=typescript --local # ディレクトリ構成(出力例、環境により異なります) # . # ├── cdktf.json ← プロバイダーとスタック設定 # ├── main.ts ← リソース定義の主ファイル # ├── package.json # └── tsconfig.json
cdktf.json にAWSプロバイダーを追記します。{ "language": "typescript", "app": "npx ts-node main.ts", "terraformProviders": [ "aws@~> 5.0" ], "terraformModules": [] }
cdktf get でTypeScript用のバインディングを生成します。# プロバイダーバインディングを生成(初回は数分かかります) cdktf get # 生成後の確認(出力例、環境により異なります) ls .gen/providers/aws/ # instance/ provider/ s3-bucket/ vpc/ ...
2. TypeScriptでEC2インスタンスを定義する
.gen/ 配下の型定義を使って main.ts を編集します。// main.ts import { App, TerraformStack, TerraformOutput } from "cdktf"; import { AwsProvider } from "./.gen/providers/aws/provider"; import { Instance } from "./.gen/providers/aws/instance"; class MyStack extends TerraformStack { constructor(scope: App, id: string) { super(scope, id); // AWSプロバイダーの設定 new AwsProvider(this, "aws", { region: "ap-northeast-1", }); // EC2インスタンスの定義 const instance = new Instance(this, "web-server", { ami: "ami-0d52744d6551d851e", // Amazon Linux 2023 instanceType: "t3.micro", tags: { Name: "cdktf-web-server", Env: "dev", }, }); // outputでパブリックIPを出力 new TerraformOutput(this, "public_ip", { value: instance.publicIp, }); } } const app = new App(); new MyStack(app, "my-stack"); app.synth();
forEach や map がそのまま使える点がCDKTFの強みです。同じ設定の複数台サーバーを作成する場合、HCLでは count や for_each の独自構文を覚える必要がありますが、CDKTFではTypeScriptの配列操作をそのまま利用できます。3. cdktf synthでTerraform JSONに変換する
# TypeScriptをコンパイルしてTerraform JSONを生成 cdktf synth # 生成されたファイルを確認(出力例、環境により異なります) ls cdktf.out/stacks/my-stack/ # cdk.tf.json # 中身の確認(プレーンなTerraform JSONフォーマット) cat cdktf.out/stacks/my-stack/cdk.tf.json | python3 -m json.tool | head -20
cdk.tf.json は標準的なTerraform JSONフォーマットです。terraform -chdir=cdktf.out/stacks/my-stack plan で内容を確認できます。cdktf deploy コマンドはsynth→applyを1ステップで実行します。CDKTFをGitHub ActionsのCIに組み込む実践
CDKTFをCI/CDに組み込む際の基本方針は「synthまでをCI側で実行し、生成されたJSONをTerraformのapplyパイプラインに渡す」です。これにより、既存のTerraform CI(tflint・planレビュー・ポリシーチェックなど)をそのまま流用できます。1. ワークフローファイルの基本構成
# .github/workflows/cdktf.yml name: CDKTF CI on: pull_request: branches: [main] push: branches: [main] jobs: cdktf-plan: name: CDKTF Synth and Terraform Plan runs-on: ubuntu-latest permissions: contents: read id-token: write # OIDC認証用 pull-requests: write # PRコメント書き込み用 steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" - name: Install cdktf-cli and dependencies run: | npm install -g cdktf-cli@latest npm ci - name: Generate provider bindings run: cdktf get - name: CDKTF Synth run: cdktf synth - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: "1.9.x" - name: Terraform Init and Plan working-directory: cdktf.out/stacks/my-stack run: | terraform init terraform plan -out=tfplan
2. PRにplanの差分をコメントする
PR上でplan結果を確認できるようにすると、レビュアーがインフラ変更の影響を把握しやすくなります。# (cdktf-planジョブのstepsに追加) - name: Terraform Plan Output id: plan working-directory: cdktf.out/stacks/my-stack run: | terraform show -no-color tfplan > plan_output.txt { echo "plan_output<
> "$GITHUB_OUTPUT" - name: Comment PR with Plan Result if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const plan = `${{ steps.plan.outputs.plan_output }}`; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `## Terraform Plan\n\`\`\`\n${plan}\n\`\`\`` });
3. mainブランチへのマージでapplyを実行する
applyはPRマージ後のpushイベントで実行します。GitHub Environments の承認フローを利用すると、担当者のOKが出るまでapplyジョブが待機します。cdktf-apply: name: CDKTF Apply runs-on: ubuntu-latest needs: cdktf-plan if: github.ref == 'refs/heads/main' && github.event_name == 'push' environment: production # GitHub Environmentsで承認者を設定 steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" - name: Install, Synth run: | npm install -g cdktf-cli@latest npm ci cdktf get cdktf synth - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: "1.9.x" - name: Terraform Apply working-directory: cdktf.out/stacks/my-stack run: | terraform init terraform apply -auto-approve
environment: production を設定するとGitHub Environmentsの保護ルールが適用され、指定した承認者がOKを出すまでapplyジョブが待機します。コードレビュー+インフラapply承認の2段構えで変更を管理できます。Terraformの基礎的なIaC設計を体系的に学ぶには、Terraform学習ガイド(terraform.linuxmaster.jp)も参考にしてください。
S3バックエンドでチーム共有のtfstateを管理する
cdktf init --local で作成したプロジェクトはtfstateがローカルに保存されるため、チーム開発には適しません。S3バックエンドへの切り替えは main.ts にバックエンド設定を追加するだけです。// main.ts(S3バックエンド設定を追加) import { App, TerraformStack, S3Backend } from "cdktf"; import { AwsProvider } from "./.gen/providers/aws/provider"; class MyStack extends TerraformStack { constructor(scope: App, id: string) { super(scope, id); // S3バックエンドの設定(コード内で宣言) new S3Backend(this, { bucket: "my-tfstate-bucket", key: "cdktf/my-stack/terraform.tfstate", region: "ap-northeast-1", encrypt: true, dynamodbTable: "terraform-lock", // ステートロック用 }); new AwsProvider(this, "aws", { region: "ap-northeast-1" }); // ... リソース定義は変わらない } }
cdktf synth を再実行すると、生成されたJSONにS3バックエンドの設定が含まれます。CIで terraform init を実行した際にS3から最新のtfstateが取得されるようになります。HCL直書きのTerraformとCDKTFの使い分け基準
CDKTFがすべてのケースでHCLより優れているわけではありません。チームのスキルセットとコードの複雑さで判断するのが実務的な指針です。| 判断軸 | HCL(Terraform)が向く | CDKTFが向く |
|---|---|---|
| チームスキル | インフラエンジニア中心 | アプリ開発者もインフラを書く |
| 構成の複雑さ | リソース数が少なくシンプル | 条件分岐・ループが多い |
| 型安全性 | tflintで補完 | TypeScriptの型システムで補完 |
| 既存資産 | HCLモジュールが豊富 | TypeScript・Python資産と共存したい |
| 学習コスト | HCL構文のみ覚えれば動く | Node.js・npmのセットアップも必要 |
よくあるエラーと対処法
「cdktf get」でバインディング生成が遅い、または途中で止まる
CDKTFのプロバイダーバインディング生成はネットワークとディスクI/Oに依存します。初回生成は数分かかることがあります。CI環境では生成結果をキャッシュすることで時間を短縮できます。# GitHub Actionsでのキャッシュ設定例 - name: Cache CDKTF provider bindings uses: actions/cache@v4 with: path: | node_modules/.gen .gen key: cdktf-${{ hashFiles('cdktf.json') }} restore-keys: | cdktf-
cdktf synthは成功するがterraform initでプロバイダーが見つからない
cdktf synth が成功しても、terraform init でTerraformプロバイダーのダウンロードが走ります。CI環境で毎回ダウンロードが発生して遅い場合は TF_PLUGIN_CACHE_DIR を設定するか、actions/cache で ~/.terraform.d/plugins をキャッシュしてください。# Terraformプロバイダーのキャッシュを有効化 - name: Cache Terraform providers uses: actions/cache@v4 with: path: ~/.terraform.d/plugins key: terraform-providers-${{ hashFiles('**/.terraform.lock.hcl') }}
TypeScriptのコンパイルエラーで型が合わない
CDKTFのバインディングは厳格な型定義を持つため、HCLでは許容されていた曖昧な値の設定でもTypeScriptの型チェックで弾かれます。たとえばCPUコア数に数値型が期待される場所に文字列"2" を渡すとコンパイルエラーになります。エラーメッセージが示す型定義(.gen/providers/ 配下の .d.ts ファイル)を確認し、型を合わせてください。複数スタックを定義しているときのデプロイ指定
複数のStackを定義している場合、cdktf deploy はデプロイ対象を明示する必要があります。# スタック名を明示してデプロイ cdktf deploy my-stack # 全スタックを依存関係の順にデプロイ cdktf deploy '*' # planのみ確認する場合 cdktf diff my-stack
本記事のまとめ
CDK for Terraform(CDKTF)の仕組みから実践まで解説しました。要点を整理します。| やりたいこと | コマンド・設定 |
|---|---|
| プロジェクト初期化 | cdktf init --template=typescript --local |
| プロバイダーバインディング生成 | cdktf get |
| Terraform JSONへ変換 | cdktf synth |
| インフラ変更の確認 | cdktf diff または terraform plan |
| インフラ適用 | cdktf deploy または terraform apply |
| S3バックエンド設定 | main.tsで S3Backend クラスを使用 |
| CI/CDへの組み込み | GitHub Actionsでsynth+terraform plan/apply |
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:PulumiとTerraformのstate競合を防ぐ|並走期間中のリソース所有権の分け方
- この記事の属するカテゴリ:Terraformへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます