目次
- 初心者から実務者向けの包括的解説
- 1. 本質と課題解決
- 2. アーキテクチャと主要コンセプト
- 3. 対応言語
- 4. CDK のセットアップと基本操作
- 5. Construct の設計パターン
- 6. CDK Pipelines(CI/CD の自動化)
- 7. テスト
- 8. 重要な機能・パターン
- 9. Asset(ローカルファイルの管理)
- 10. Custom Resource
- 11. CDK for Terraform(CDKTF)
- 12. CDK for Kubernetes(cdk8s)
- 13. CDK v2 と v1 の違い
- 14. CDK と他ツールの比較
- 15. 主要ユースケース(10+)
- 16. 他の類似ツールとの比較
- 17. ベストプラクティス
- 18. クライアントとエコシステム
- 19. トラブルシューティング
- 20. 2025-2026 最新動向
- 21. 学習リソース
- 22. よく使うパターン集
- 23. 導入ロードマップ
- 24. 実装チェックリスト
- 25. よくあるエラーと対処法(補足)
- 26. 参考文献
- まとめ
AWS CDK 完全ガイド 2026
初心者から実務者向けの包括的解説
AWS CDK は、TypeScript・Python・Java・Go などの汎用プログラミング言語で AWS インフラを定義し、CloudFormation テンプレートを自動生成するオープンソースの IaC フレームワークです。プログラミングの表現力で複雑なインフラを DRY に記述できるのが特徴です。
ドキュメントの目的
本ガイドは以下を対象としています。
- 初心者向け: CDK とは何か、なぜ必要かを学びたい方
- 開発者向け: CDK でマルチ環境 Stack を構築したい方
- インフラ向け: Pipeline、Custom Resource、Aspect を活用したい方
- 意思決定者向け: CDK vs CloudFormation vs Terraform 選定判断
2026 年の CDK エコシステム
- CDK v2 標準化(v1 は 2023/6 サポート終了)
- CDK Mixins 安定化:aws-cdk-lib v2.233.0+ で安定リリース
- EKS v2 本番対応:Kubernetes v1.28 対応、production-ready API
- CLI --revert-drift:ドリフト修復を単一コマンドで実行(v2.1099.0+)
- Construct Hub 拡張:5000+ 件のコミュニティ Construct
- CDK for Kubernetes(cdk8s v2.x):Kubernetes マニフェスト生成、任意のクラスタ対応
- CDK for Terraform(CDKTF):Terraform HCL 生成、マルチクラウド対応
- AWS Solutions Constructs:業界別のベストプラクティス Construct
- cdk-nag・pdk:セキュリティ・ポリシー検証の主流化
- Q Developer 統合:自然言語 → CDK Stack の自動生成
1. 本質と課題解決
AWS CDK は 「プログラミング言語の表現力をインフラコードに組み込む」 ツールです。
CDK が解決する課題
| 課題 | CloudFormation(直書き) | Terraform | CDK |
|---|---|---|---|
| DRY 原則の実装 | ❌ 繰り返しが冗長 | △ HCL ループ可能 | ✅ 完全なプログラム言語 |
| 型安全性・IDE 補完 | ❌ YAML・JSON | △ HCL | ✅ TypeScript・Python |
| 複数環境(dev/stg/prod) | ❌ ファイル分割必須 | △ tfvars | ✅ 1 つのコードベース |
| 社内標準の共有 | ❌ 難しい | △ Module | ✅ npm パッケージ化 |
| テスト容易性 | △ cfn-lint | △ terraform test | ✅ Jest・Assertion 完備 |
| AWS サービス新対応速度 | ◎ 同期 | △ 遅れる | ✅ L1 で即対応 |
| クラウド統一(マルチクラウド) | ❌ AWS のみ | ✅ 統一 | ❌ AWS 専用 |
このサービスを選ぶ理由
なぜ CDK でないといけないのか?
- プログラミング言語の表現力: ループ・条件分岐・変数・関数・モジュール化で複雑なインフラを DRY に記述
- 型安全性・IDE 補完: TypeScript/Python の型情報により、誤りをデプロイ前に検出
- 高レベルの抽象化(L2/L3 Construct):
new s3.Bucket()一行でベストプラクティスを適用 - CloudFormation との完全互換: CF の全機能(ロールバック・スタック管理・変更セット)をそのまま活用
- Construct Hub エコシステム: サードパーティ Construct ライブラリを npm/pip で再利用
- マルチ環境・複合リソースの効率化: 1 つのコードベースでパラメーター差分管理
具体的なユースケース
✅ マルチ環境(dev/stg/prod)を同一コードベースでパラメーター変更でデプロイ ✅ 社内標準の「セキュアな S3」「標準 VPC」を Construct 化して組織全体で共有 ✅ ECS + ALB + RDS + IAM などの複合リソースを 1 Stack クラスで管理 ✅ CI/CD パイプライン(CDK Pipelines)で PR → 自動デプロイ ✅ カスタムロジック(ループ・条件分岐)で大規模インフラを DRY に定義
2. アーキテクチャと主要コンセプト
2.1 CDK のレイヤー構造
開発者が書く CDK コード(TypeScript/Python/Java/Go)
↓ cdk synth
CloudFormation テンプレート(JSON/YAML)
↓ cdk deploy
AWS CloudFormation スタック
↓
AWS リソース(S3, Lambda, VPC, RDS, etc.)
初心者向けメモ: CDK は「インフラを定義する言語」で、最終的には CloudFormation テンプレートを生成します。CDK 自体が AWS に何かをデプロイしているわけではなく、CF を経由しています。
2.2 主要コンセプト
graph TB
App["App<br/>(CDK アプリのルート)<br/>複数 Stack を管理"]
Stack1["Stack(本番)<br/>CloudFormation スタックに 1:1 対応"]
Stack2["Stack(開発)<br/>Environment: account + region"]
Construct1["Construct<br/>(VPC)<br/>L2 高レベル"]
Construct2["Construct<br/>(ECS Cluster)"]
Construct3["Construct<br/>(ALB)"]
Resource1["L1 CFN Resource<br/>(AWS::EC2::VPC)"]
Resource2["L2/L3 Construct"]
App --> Stack1
App --> Stack2
Stack1 --> Construct1
Stack1 --> Construct2
Stack1 --> Construct3
Construct1 --> Resource1
Construct2 --> Resource2
style App fill:#e8f4f8
style Stack1 fill:#b3e5fc
style Construct1 fill:#81d4fa
style Resource1 fill:#4fc3f7
| コンセプト | 説明 | 例 |
|---|---|---|
| App | CDK アプリのルート。1 つの App に複数の Stack を含める |
new cdk.App() |
| Stack | CloudFormation スタックに 1:1 で対応。デプロイの単位 | class MyStack extends cdk.Stack |
| Construct | AWS リソースを表すクラス。Stack の構成要素 | new s3.Bucket() |
| Environment | Stack をデプロイする AWS アカウント + リージョンの組み合わせ | env: { account: '123...', region: 'ap-northeast-1' } |
| Asset | Lambda コード・Docker イメージなどのローカルファイル。S3/ECR に自動アップロード | Code.fromAsset('lambda') |
| Context | デプロイ時に渡す設定値(アカウント ID・環境名など) | node.tryGetContext('stage') |
2.3 Construct の 3 レベル(L1/L2/L3)
| レベル | 名称 | 説明 | 例 | 使用頻度 |
|---|---|---|---|---|
| L1 | CFN Resources | CloudFormation リソースの 1:1 マッピング。全プロパティを手動指定 | CfnBucket, CfnFunction |
△ 低レベル制御用 |
| L2 | Curated Constructs | AWS が提供する高レベル抽象化。デフォルトでベストプラクティスを適用 | s3.Bucket, lambda.Function |
✅ 最頻出 |
| L3 | Patterns | 複数の L2 Construct を組み合わせた再利用可能なアーキテクチャパターン | ecs_patterns.ApplicationLoadBalancedFargateService |
✅ 標準パターン用 |
L1 vs L2 の比較:
// L1: CloudFormation そのまま(全プロパティを自分で指定)
new s3.CfnBucket(this, 'MyBucket', {
bucketName: 'my-bucket',
versioningConfiguration: { status: 'Enabled' },
bucketEncryption: {
serverSideEncryptionConfiguration: [{
serverSideEncryptionByDefault: { sseAlgorithm: 'AES256' }
}]
},
publicAccessBlockConfiguration: {
blockPublicAcls: true,
blockPublicPolicy: true,
ignorePublicAcls: true,
restrictPublicBuckets: true
}
});
// L2: 高レベル抽象(デフォルトがベストプラクティス)
const bucket = new s3.Bucket(this, 'MyBucket', {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: RemovalPolicy.RETAIN
});
// L3: パターン(複数リソースをまとめて作成)
new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Service', {
cluster,
taskImageOptions: { image: ContainerImage.fromRegistry('nginx') },
publicLoadBalancer: true
});
3. 対応言語
CDK は複数の言語をサポートし、言語間で完全な機能パリティを維持しています。
| 言語 | パッケージマネージャ | 学習曲線 | 用途 |
|---|---|---|---|
| TypeScript | npm | 中 | ✅ 推奨・最活発 |
| Python | pip | 低(Python 知識あれば) | ✅ ML・データ系チーム向け |
| Java | Maven / Gradle | 中(Java 知識あれば) | △ Enterprise 環境 |
| C# / .NET | NuGet | 中(.NET 知識あれば) | △ Windows 環境 |
| Go | go get | 高(Go+ AWS 知識) | △ インフラエンジニア向け |
言語別スターター例:
# TypeScript(推奨)
cdk init app --language typescript
# Python
cdk init app --language python
# Java
cdk init app --language java
# Go
cdk init app --language go
4. CDK のセットアップと基本操作
4.1 インストール
# 前提: Node.js 18+ がインストール済み
npm install -g aws-cdk
# バージョン確認(現在 v2.x)
cdk --version
# AWS CLI と認証情報も設定済みであることを確認
aws sts get-caller-identity
4.2 主要な CDK CLI コマンド
| コマンド | 説明 | 例 |
|---|---|---|
cdk init app --language typescript |
新規 CDK プロジェクトの初期化 | cdk init app --language typescript |
cdk bootstrap |
CDK 用 S3 バケット・IAM ロールを AWS に作成(初回のみ) | cdk bootstrap aws://123456789012/ap-northeast-1 |
cdk synth |
CloudFormation テンプレートを生成して表示 | cdk synth > template.json |
cdk diff |
現在のスタックと変更後の差分を表示 | cdk diff MyStack |
cdk deploy |
スタックをデプロイ | cdk deploy MyStack |
cdk deploy --hotswap |
Lambda・ECS など一部リソースを CF 経由せず高速更新 | cdk deploy --hotswap |
cdk destroy |
スタックを削除 | cdk destroy MyStack |
cdk ls |
App 内のスタック一覧を表示 | cdk ls |
cdk watch |
ファイル変更を監視して自動デプロイ(開発時) | cdk watch |
cdk context |
Context 値の表示・削除 | cdk context --reset |
4.3 CDK Bootstrap
CDK を初めて使うアカウント+リージョンで必要な事前準備。CDKToolkit という CloudFormation スタックを作成する。
# 特定アカウント・リージョンにブートストラップ
cdk bootstrap aws://123456789012/ap-northeast-1
# 複数リージョンに一括ブートストラップ
cdk bootstrap aws://123456789012/us-east-1 aws://123456789012/ap-northeast-1
# 信頼する CI/CD アカウントを指定(クロスアカウントデプロイ用)
cdk bootstrap --trust 987654321098 aws://123456789012/ap-northeast-1
# より新しい Bootstrap テンプレートを使用
cdk bootstrap --template-body cdk-bootstrap.yaml aws://ACCOUNT/REGION
Bootstrap で作成されるリソース:
- S3 バケット(
cdk-xxxxxxxx-assets-ACCOUNT-REGION): Lambda コード・Docker イメージなどの Asset を格納 - ECR リポジトリ: Docker イメージ Asset の格納先
- IAM ロール: CDK デプロイ用の各種実行ロール(
cdk-xxxxxxxx-cfn-exec-role-*など)
4.4 プロジェクト構造(TypeScript)
my-cdk-app/
├── bin/
│ └── my-cdk-app.ts # App のエントリーポイント
├── lib/
│ ├── my-cdk-app-stack.ts # Stack 定義
│ ├── constructs/
│ │ ├── vpc-construct.ts # カスタム Construct
│ │ └── secure-bucket.ts
│ └── config.ts # 設定・定数
├── test/
│ └── my-cdk-app.test.ts # CDK Assertions テスト
├── lambda/ # Lambda 関数コード
│ └── handler.js
├── cdk.json # CDK 設定ファイル
├── package.json
├── tsconfig.json
└── README.md
bin/my-cdk-app.ts(エントリーポイント):
import * as cdk from 'aws-cdk-lib';
import { MyStack } from '../lib/my-cdk-app-stack';
const app = new cdk.App();
// 開発環境
new MyStack(app, 'MyStack-Dev', {
env: { account: '111111111111', region: 'ap-northeast-1' },
stage: 'dev',
vpcCidr: '10.0.0.0/16'
});
// ステージング環境
new MyStack(app, 'MyStack-Stg', {
env: { account: '111111111111', region: 'ap-northeast-1' },
stage: 'stg',
vpcCidr: '10.1.0.0/16'
});
// 本番環境
new MyStack(app, 'MyStack-Prod', {
env: { account: '222222222222', region: 'ap-northeast-1' },
stage: 'prod',
vpcCidr: '172.16.0.0/16'
});
lib/my-cdk-app-stack.ts(Stack 定義):
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
interface MyStackProps extends cdk.StackProps {
stage: 'dev' | 'stg' | 'prod';
vpcCidr: string;
}
export class MyStack extends cdk.Stack {
public readonly bucket: s3.Bucket;
public readonly vpc: ec2.Vpc;
constructor(scope: Construct, id: string, props: MyStackProps) {
super(scope, id, props);
// VPC 作成
this.vpc = new ec2.Vpc(this, 'Vpc', {
cidrMask: 24,
maxAzs: props.stage === 'prod' ? 3 : 2,
natGateways: props.stage === 'prod' ? 3 : 1,
cidrBlock: props.vpcCidr,
});
// S3 バケット作成
this.bucket = new s3.Bucket(this, 'DataBucket', {
bucketName: `my-data-bucket-${props.stage}`,
versioned: props.stage === 'prod',
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: props.stage === 'prod'
? cdk.RemovalPolicy.RETAIN
: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: props.stage !== 'prod',
});
// Lambda 関数作成
const fn = new lambda.Function(this, 'Handler', {
runtime: lambda.Runtime.NODEJS_20_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
environment: {
BUCKET_NAME: this.bucket.bucketName,
STAGE: props.stage,
VPC_ID: this.vpc.vpcId,
},
timeout: cdk.Duration.seconds(60),
});
// Lambda に S3 バケットへの読み書き権限を付与
this.bucket.grantReadWrite(fn);
// 出力
new cdk.CfnOutput(this, 'BucketName', {
value: this.bucket.bucketName,
exportName: `${id}-BucketName`,
});
new cdk.CfnOutput(this, 'VpcId', {
value: this.vpc.vpcId,
exportName: `${id}-VpcId`,
});
}
}
5. Construct の設計パターン
5.1 カスタム Construct の作成
組織内の標準構成をカスタム Construct としてカプセル化することで、チーム全体で一貫したベストプラクティスを強制できます。
// lib/constructs/secure-bucket.ts
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';
interface SecureBucketProps {
bucketName: string;
isProd?: boolean;
enableLogging?: boolean;
}
export class SecureBucket extends Construct {
public readonly bucket: s3.Bucket;
constructor(scope: Construct, id: string, props: SecureBucketProps) {
super(scope, id);
this.bucket = new s3.Bucket(this, 'Bucket', {
bucketName: props.bucketName,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
versioned: true,
enforceSSL: true,
// アクセスログを別バケットに出力(オプション)
serverAccessLogsBucket: props.enableLogging
? new s3.Bucket(this, 'LogBucket', {
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
})
: undefined,
serverAccessLogsPrefix: 'access-logs/',
removalPolicy: props.isProd
? cdk.RemovalPolicy.RETAIN
: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: !props.isProd,
});
// CloudWatch アラーム(オプション)
if (props.isProd) {
// 大容量アップロード検知など
}
}
}
// 利用側
const dataBucket = new SecureBucket(this, 'DataBucket', {
bucketName: 'my-data-bucket',
isProd: true,
enableLogging: true,
});
5.2 Stack 間のリソース共有
// 方法1: CfnOutput + Fn.importValue(クロス参照)
// Stack A(VPC を作成)
const vpcStack = new VpcStack(app, 'VpcStack');
new cdk.CfnOutput(vpcStack, 'VpcId', {
value: vpcStack.vpc.vpcId,
exportName: 'SharedVpcId',
});
// Stack B(VPC を参照)
const vpcId = cdk.Fn.importValue('SharedVpcId');
// 方法2: Props で直接渡す(推奨・同一 App 内)
const vpcStack = new VpcStack(app, 'VpcStack');
const appStack = new AppStack(app, 'AppStack', { vpc: vpcStack.vpc });
appStack.addDependency(vpcStack);
// 方法3: SSM Parameter Store 経由(異なる App/アカウント)
import * as ssm from 'aws-cdk-lib/aws-ssm';
// 書き込み側
new ssm.StringParameter(vpcStack, 'VpcIdParam', {
parameterName: '/shared/vpc-id',
stringValue: vpcStack.vpc.vpcId,
});
// 読み取り側
const vpcId = ssm.StringParameter.valueForStringParameter(this, '/shared/vpc-id');
6. CDK Pipelines(CI/CD の自動化)
CDK Pipelines は CDK を使ってインフラの CI/CD パイプライン自体を定義する機能。CodePipeline を自動構築し、PR マージ → 自動デプロイのフローを実現します。
import * as pipelines from 'aws-cdk-lib/pipelines';
export class PipelineStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const pipeline = new pipelines.CodePipeline(this, 'Pipeline', {
synth: new pipelines.ShellStep('Synth', {
input: pipelines.CodePipelineSource.gitHub('my-org/my-repo', 'main', {
authentication: cdk.SecretValue.secretsManager('github-token'),
}),
commands: [
'npm ci',
'npm run build',
'npm test',
'npx cdk synth',
],
}),
selfMutation: true, // Pipeline 自体の変更を自動適用
crossAccountKeys: true, // クロスアカウント対応
});
// ステージング環境
const stagingStage = pipeline.addStage(
new MyApplicationStage(this, 'Staging', {
env: { account: '111111111111', region: 'ap-northeast-1' },
})
);
// ステージングに手動承認を追加
stagingStage.addPost(new pipelines.ManualApprovalStep('ApproveToProduction'));
// 本番環境
pipeline.addStage(
new MyApplicationStage(this, 'Production', {
env: { account: '222222222222', region: 'ap-northeast-1' },
})
);
}
}
// ステージ定義
class MyApplicationStage extends cdk.Stage {
constructor(scope: Construct, id: string, props: cdk.StageProps) {
super(scope, id, props);
new MyStack(this, 'App');
new DatabaseStack(this, 'Database');
}
}
7. テスト
7.1 CDK Assertions によるユニットテスト
import * as cdk from 'aws-cdk-lib';
import { Template, Match } from 'aws-cdk-lib/assertions';
import { MyStack } from '../lib/my-cdk-app-stack';
describe('MyStack', () => {
let template: Template;
beforeEach(() => {
const app = new cdk.App();
const stack = new MyStack(app, 'TestStack', {
stage: 'dev',
vpcCidr: '10.0.0.0/16'
});
template = Template.fromStack(stack);
});
test('S3 バケットが暗号化されていること', () => {
template.hasResourceProperties('AWS::S3::Bucket', {
BucketEncryption: {
ServerSideEncryptionConfiguration: Match.arrayWith([
{ ServerSideEncryptionByDefault: { SSEAlgorithm: 'AES256' } }
])
}
});
});
test('S3 バケットが 1 つだけ作成されること', () => {
template.resourceCountIs('AWS::S3::Bucket', 1);
});
test('Lambda 関数が正しい環境変数を持つこと', () => {
template.hasResourceProperties('AWS::Lambda::Function', {
Environment: {
Variables: Match.objectLike({
STAGE: 'dev'
})
}
});
});
test('Lambda に S3 への読み書き権限があること', () => {
template.hasResourceProperties('AWS::IAM::Policy', {
PolicyDocument: {
Statement: Match.arrayWith([
Match.objectLike({
Action: Match.arrayWith(['s3:GetObject', 's3:PutObject']),
Effect: 'Allow'
})
])
}
});
});
test('VPC が正しく作成されていること', () => {
template.hasResourceProperties('AWS::EC2::VPC', {
CidrBlock: '10.0.0.0/16'
});
});
});
8. 重要な機能・パターン
8.1 Aspects(横断的なポリシー適用)
全リソースに対して横断的なチェック・変更を適用する。セキュリティポリシーの強制などに使う。
import { Aspects, IAspect } from 'aws-cdk-lib';
import { CfnBucket } from 'aws-cdk-lib/aws-s3';
import { IConstruct } from 'constructs';
// すべての S3 バケットでバージョニングを強制するアスペクト
class EnforceS3Versioning implements IAspect {
visit(node: IConstruct): void {
if (node instanceof CfnBucket) {
node.versioningConfiguration = { status: 'Enabled' };
}
}
}
// Stack 全体に適用
Aspects.of(stack).add(new EnforceS3Versioning());
// cdk-nag(セキュリティルールチェック)
import { AwsSolutionsChecks, NagSuppressions } from 'cdk-nag';
Aspects.of(app).add(new AwsSolutionsChecks({ verbose: true }));
// 特定ルールを除外
NagSuppressions.addStackSuppressions(stack, [
{ id: 'AwsSolutions-S1', reason: 'Logging not required for development' }
]);
8.2 Tokens と遅延解決
CDK では多くの値が「デプロイ時に解決されるトークン」として扱われます。cdk synth 時点では値が未確定なもの(他リソースの ARN など)は ${Token[TOKEN.123]} という形式のプレースホルダーになります。
const bucket = new s3.Bucket(this, 'Bucket');
// これはトークン(synth 時点では値不明)
console.log(bucket.bucketName); // → "${Token[TOKEN.12]}"
// CloudFormation で解決される
new lambda.Function(this, 'Fn', {
environment: {
BUCKET_NAME: bucket.bucketName, // CF テンプレートで Ref に変換
}
});
// トークンかどうかの判定
if (cdk.Token.isUnresolved(bucket.bucketName)) {
console.log('デプロイ時に解決されます');
}
8.3 RemovalPolicy(リソース削除時の挙動)
| ポリシー | 挙動 | 用途 |
|---|---|---|
| RETAIN | スタック削除後もリソースを残す | 本番の S3・RDS など(データ喪失防止) |
| DESTROY | スタック削除時にリソースも削除 | 開発環境(リソース削除) |
| SNAPSHOT | 削除前にスナップショットを作成 | RDS・ElastiCache(復旧対応) |
9. Asset(ローカルファイルの管理)
Asset は Lambda コード・Docker イメージなどのローカルファイルを S3/ECR に自動アップロードする機能です。
// Lambda コードを S3 に自動アップロード
const handler = new lambda.Function(this, 'Handler', {
code: lambda.Code.fromAsset('lambda'), // lambda/ ディレクトリを S3 に
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_20_X,
});
// Docker イメージを ECR に自動アップロード
const image = ecs.ContainerImage.fromAsset('docker', {
file: 'Dockerfile',
repositoryName: 'my-app',
});
// 任意のファイルを S3 に自動アップロード
new s3_deployment.BucketDeployment(this, 'Deploy', {
sources: [s3_deployment.Source.asset('dist')],
destinationBucket: bucket,
});
10. Custom Resource
CloudFormation がネイティブサポートしていないカスタム処理を実装する場合、Custom Resource を使います。
import * as custom_resources from 'aws-cdk-lib/custom-resources';
// Lambda を実行する Custom Resource
const resource = new custom_resources.AwsCustomResource(this, 'CustomResource', {
onCreate: {
service: 'dynamodb',
action: 'putItem',
parameters: {
TableName: table.tableName,
Item: {
id: { S: 'test-id' },
name: { S: 'Test Item' }
}
},
physicalResourceId: custom_resources.PhysicalResourceId.of('resource-id'),
},
});
// IAM 権限を自動付与
table.grantWriteData(resource.grantPrincipal);
11. CDK for Terraform(CDKTF)
CDK の表現力で Terraform HCL を生成できます。マルチクラウド対応が可能です。
# CDKTF プロジェクト初期化
cdktf init --template=typescript --providers=aws
# Terraform コードを生成・デプロイ
cdktf synth
cdktf deploy
12. CDK for Kubernetes(cdk8s)
CDK の表現力で Kubernetes マニフェストを生成します。
import { Chart, ChartProps } from 'cdk8s';
import { KubeDeployment, KubeService } from 'cdk8s-plus-27';
export class MyChart extends Chart {
constructor(scope: Construct, id: string, props: ChartProps = {}) {
super(scope, id, props);
const deployment = new KubeDeployment(this, 'deployment', {
spec: {
replicas: 3,
selector: { matchLabels: { app: 'my-app' } },
template: {
metadata: { labels: { app: 'my-app' } },
spec: {
containers: [
{
name: 'app',
image: 'my-app:latest',
ports: [{ containerPort: 8080 }],
}
]
}
}
}
});
new KubeService(this, 'service', {
spec: {
type: 'LoadBalancer',
selector: { app: 'my-app' },
ports: [{ port: 80, targetPort: 8080 }]
}
});
}
}
13. CDK v2 と v1 の違い
CDK v2(2021 年 12 月 GA)が現在の標準。v1 は 2023 年 6 月にサポート終了。
| 項目 | CDK v1 | CDK v2 |
|---|---|---|
| パッケージ | サービスごとに個別インストール(@aws-cdk/aws-s3 など) |
aws-cdk-lib に全サービスを一括収録 |
| インポート | import * as s3 from '@aws-cdk/aws-s3' |
import * as s3 from 'aws-cdk-lib/aws-s3' |
| Constructs | @aws-cdk/core に含まれる |
constructs パッケージに分離 |
| Experimental | メインパッケージに含む | @aws-cdk/aws-xxx-alpha に分離 |
| サポート | ✗ 2023/6 終了 | ✅ アクティブ |
14. CDK と他ツールの比較
graph LR
CDK["AWS CDK<br/>言語: TS/Py/Java<br/>対象: AWS のみ<br/>型: ◎"]
CF["CloudFormation<br/>言語: YAML/JSON<br/>対象: AWS のみ<br/>型: ✗"]
TF["Terraform<br/>言語: HCL<br/>対象: マルチクラウド<br/>型: △"]
Pulumi["Pulumi<br/>言語: TS/Py/Go<br/>対象: マルチクラウド<br/>型: ◎"]
CDK -->|AWS 特化| CF
TF -->|マルチクラウド| Pulumi
CDK -->|表現力| TF
| 観点 | AWS CDK | CloudFormation(直書き) | Terraform | Pulumi |
|---|---|---|---|---|
| 記述言語 | TypeScript/Python/Java/Go/.NET | YAML/JSON | HCL | TypeScript/Python/Go/.NET |
| 学習コスト | 中(言語知識が必要) | 中(YAML + CF 知識) | 中(HCL) | 中 |
| 抽象化レベル | 高(L2/L3 Construct) | 低(全プロパティを記述) | 中 | 高 |
| 型安全性 | ◎(TypeScript) | ✗ | △ | ◎ |
| マルチクラウド | ✗(AWS のみ) | ✗(AWS のみ) | ✅ | ✅ |
| State 管理 | CloudFormation に委任 | CloudFormation に委任 | tfstate ファイル | Pulumi Cloud / self-managed |
| 新サービス対応速度 | ✅(L1 は CF と同期) | ✅ | △(遅れることあり) | △ |
| Drift 検出 | ✅(CF の機能) | ✅ | ✅ | ✅ |
| エコシステム | Construct Hub(5000+) | — | Terraform Registry | Pulumi Registry |
| 費用 | 無料(CF 費用のみ) | 無料(CF 費用のみ) | 無料(State 管理は有償) | 無料(Cloud は有償) |
15. 主要ユースケース(10+)
15.1 Application Stack(アプリケーション + インフラ)
VPC, ALB, ECS, RDS, S3 を一体管理
new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Service', {
cluster,
desiredCount: 3,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('my-app:latest'),
containerPort: 8080,
environment: { DB_HOST: db.instanceEndpoint.hostname }
},
publicLoadBalancer: true,
});
15.2 Multi-Account(複数アカウント管理)
組織の複数アカウントに異なる環境をデプロイ
const devStack = new MyStack(app, 'Dev', {
env: { account: DEV_ACCOUNT, region: 'ap-northeast-1' }
});
const prodStack = new MyStack(app, 'Prod', {
env: { account: PROD_ACCOUNT, region: 'ap-northeast-1' }
});
15.3 CI/CD Pipeline(自動デプロイ)
CDK Pipelines で GitHub → AWS 自動デプロイ
15.4 Data Lake
S3 + Glue + Athena を統合管理
15.5 ML Pipeline
SageMaker + Lambda + S3 を自動構築
15.6 Serverless Application
Lambda + API Gateway + DynamoDB
const handler = new lambda.Function(this, 'Handler', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('lambda'),
handler: 'index.handler',
});
const api = new apigw.RestApi(this, 'Api');
api.root.addMethod('GET', new apigw.LambdaIntegration(handler));
15.7 EKS Cluster
完全マネージド Kubernetes クラスタ
const cluster = new eks.Cluster(this, 'Cluster', {
vpc,
version: eks.KubernetesVersion.V1_28,
desiredCapacity: 3,
});
15.8 SaaS Multi-Tenant
テナント分離・リソース共有
15.9 Migration(オンプレミス → AWS)
既存インフラを CDK でコード化
15.10 Custom Construct Library
組織標準ライブラリを npm で共有
16. 他の類似ツールとの比較
| ツール | 特徴 | 用途 |
|---|---|---|
| CDK | AWS 専用・高レベル抽象化・言語豊富 | AWS メインのチーム向け |
| Terraform | マルチクラウド・HCL・成熟したエコシステム | インフラ全体を統一したいチーム向け |
| Pulumi | CDK に近い・マルチクラウド対応 | 言語の自由度重視 |
| CloudFormation | AWS ネイティブ・YAML/JSON | シンプルな構成向け |
| Serverless Framework | サーバーレス特化・デプロイ簡単 | サーバーレスメインのチーム向け |
| AWS SAM | CloudFormation のスーパーセット・Lambda 特化 | Lambda 中心のアプリ向け |
17. ベストプラクティス
17.1 Construct 設計
✅ 単一責任原則: 1 つの Construct は 1 つの責任を持つ ✅ 再利用性: パラメーター化してライブラリ化 ✅ 型安全性: Props インターフェースを厳密に定義 ❌ 避けるべき: グローバル変数、ハードコード、Construct 外のリソース操作
17.2 Stack 管理
✅ 小分け: Stack は関心事ごとに分割(VPC, DB, App)
✅ 環境分離: dev/stg/prod は別 Account + Stack
✅ 依存順序: addDependency で明示的に指定
❌ 避けるべき: Stack を大きくしすぎ、環境混在
17.3 テスト
✅ Assertions: CloudFormation リソースの検証 ✅ スナップショット: テンプレートの変更検知 ✅ Integration テスト: 実際にデプロイして検証 ❌ 避けるべき: テストなしのデプロイ
17.4 CI/CD Pipeline
✅ 自動化: PR → Staging → 手動承認 → Production
✅ 変更検知: cdk diff で差分確認
✅ ロールバック: CloudFormation のロールバック機能を活用
❌ 避けるべき: 手動デプロイ、権限集中
17.5 セキュリティ
✅ 最小権限: grant* メソッドで自動付与
✅ Aspects: cdk-nag で秘密情報チェック
✅ Secrets Manager: 秘密情報は環境変数ではなく Secrets Manager
❌ 避けるべき: IAM ポリシーのハードコード、API キー埋め込み
18. クライアントとエコシステム
18.1 Construct Hub
公開 Construct ライブラリ(5000+ 件)
npm search @aws-solutions-constructs/aws-ecs-fargate
npm install @aws-solutions-constructs/aws-ecs-fargate
18.2 AWS Solutions Constructs
業界別・ユースケース別の高レベル Construct
aws-apigateway-lambdaaws-ecs-fargateaws-data-lakeaws-ml-pipeline
18.3 Projen
CDK プロジェクトのテンプレートとメンテナンスツール
npm install -D projen
npx projen new awscdk
18.4 cdk-nag
CDK コードのセキュリティ・コンプライアンスチェック
18.5 PDK(AWS Proton Development Kit)
エンタープライズグレードの Construct テンプレート
19. トラブルシューティング
| エラー | 原因 | 対処 |
|---|---|---|
This CDK deployment requires bootstrap |
Bootstrap 未実施 | cdk bootstrap を実行 |
Cross stack references are only supported for stacks deployed to the same environment |
異なる env(アカウント/リージョン)間の直接参照 | SSM Parameter Store や CfnOutput の exportName を使う |
| Resolution error: …is not yet deployed | デプロイ前のリソース値を参照 | デプロイ順序を addDependency で保証 |
Resource already exists |
同名の CF スタックがすでに存在 | cdk destroy 後に再デプロイ、またはスタック名を変更 |
Cannot update a stack in ROLLBACK_COMPLETE state |
前回のデプロイが失敗してロールバック済み | AWS コンソールでスタックを削除してから cdk deploy |
| Token が undefined になる | synth 時点でのみ存在するトークンを console.log | cdk.Token.isUnresolved() で確認し、出力は CfnOutput で |
| cdk synth: command not found | CDK CLI インストール漏れ | npm install -g aws-cdk |
Cannot find module 'aws-cdk-lib' |
パッケージインストール漏れ | npm install |
20. 2025-2026 最新動向
20.1 CDK v2 成熟化・最新リリース(2026年3月)
- CDK Mixins 安定化:v2.233.0+ で本番対応(再利用可能コンポーネント)
- EKS v2 production-ready:Kubernetes v1.28 完全対応
- CLI --revert-drift オプション:ドリフト修復を単一コマンドで実行(v2.1099.0+)
- Feature flags の簡潔化、パフォーマンス改善
- 新 AWS サービスへの L1 対応の迅速化
20.2 Construct Hub 拡張
- 5000+ 件の公開 Construct(品質基準・セキュリティスキャン導入)
- AWS Solutions Constructs の継続拡張
- コミュニティ Construct の活発化
20.3 AI コード生成
- Q Developer 統合:自然言語プロンプト → CDK Stack 自動生成
- IDE 内での実装支援(VS Code・JetBrains 拡張)
20.4 マルチクラウド・言語統合
- CDKTF(v2.x以上):Terraform HCL 生成、AWS・Azure・GCP 対応
- cdk8s v2.x:Kubernetes マニフェスト生成、任意クラスタ対応
- 多言語パリティ:TypeScript・Python・Java・Go・C# 完全機能同等
20.5 セキュリティ・ポリシー自動化
- cdk-nag 進化:AWS Solutions Checks・HIPAA・PCI-DSS チェック
- Projen 活況:プロジェクトテンプレートとメンテナンス自動化
21. 学習リソース
公式ドキュメント
コミュニティリソース
書籍・記事
- 「AWS CDK Deep Dive」
- AWS Blog: CDK カテゴリ
22. よく使うパターン集
22.1 VPC + ECS Fargate + ALB + Auto Scaling
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns';
const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2 });
const cluster = new ecs.Cluster(this, 'Cluster', { vpc });
const service = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Service', {
cluster,
cpu: 256,
memoryLimitMiB: 512,
desiredCount: 2,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('nginx:latest'),
containerPort: 80,
environment: { APP_ENV: 'production' },
},
publicLoadBalancer: true,
redirectHTTP: true,
});
// オートスケーリング
const scaling = service.service.autoScaleTaskCount({ maxCapacity: 10 });
scaling.scaleOnCpuUtilization('CpuScaling', { targetUtilizationPercent: 70 });
22.2 Lambda + API Gateway + DynamoDB
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigw from 'aws-cdk-lib/aws-apigateway';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
const table = new dynamodb.Table(this, 'Table', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: cdk.RemovalPolicy.DESTROY,
stream: dynamodb.StreamSpecification.NEW_AND_OLD_IMAGES,
});
const handler = new lambda.Function(this, 'ApiHandler', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('lambda'),
handler: 'api.handler',
environment: { TABLE_NAME: table.tableName },
});
table.grantReadWriteData(handler);
const api = new apigw.RestApi(this, 'Api', {
restApiName: 'My API',
defaultCorsPreflightOptions: {
allowOrigins: apigw.Cors.ALL_ORIGINS,
allowMethods: apigw.Cors.ALL_METHODS,
},
});
const items = api.root.addResource('items');
items.addMethod('GET', new apigw.LambdaIntegration(handler));
items.addMethod('POST', new apigw.LambdaIntegration(handler));
22.3 環境別設定の切り替え
// cdk.json
{
"context": {
"dev": {
"instanceType": "t3.small",
"multiAz": false,
"minCapacity": 1,
"maxCapacity": 5
},
"prod": {
"instanceType": "r6g.large",
"multiAz": true,
"minCapacity": 3,
"maxCapacity": 20
}
}
}
// Stack コード
const stage = this.node.tryGetContext('stage') ?? 'dev';
const config = this.node.tryGetContext(stage);
const asg = new autoscaling.AutoScalingGroup(this, 'ASG', {
vpc,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass[config.instanceType.split('.')[0].toUpperCase()],
ec2.InstanceSize[config.instanceType.split('.')[1].toUpperCase()]
),
desiredCapacity: config.minCapacity,
maxCapacity: config.maxCapacity,
});
// デプロイ時
// cdk deploy -c stage=prod
22.4 RDS + Secrets Manager
import * as rds from 'aws-cdk-lib/aws-rds';
import * as secrets from 'aws-cdk-lib/aws-secretsmanager';
const secret = new secrets.Secret(this, 'DBSecret', {
generateSecretString: {
secretStringTemplate: JSON.stringify({ username: 'admin' }),
generateStringKey: 'password',
passwordLength: 32,
},
});
const db = new rds.DatabaseInstance(this, 'Database', {
engine: rds.DatabaseInstanceEngine.postgres({ version: rds.PostgresEngineVersion.VER_15_2 }),
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.SMALL),
allocatedStorage: 100,
storageType: rds.StorageType.GP3,
credentials: rds.Credentials.fromSecret(secret),
vpc,
vpcSubnets: { subnets: [vpc.privateSubnets[0]] },
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// Lambda から DB に接続
const handler = new lambda.Function(this, 'Handler', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('lambda'),
handler: 'db.handler',
environment: {
DB_ENDPOINT: db.dbInstanceEndpointAddress,
DB_SECRET: secret.secretArn,
},
});
secret.grantRead(handler);
23. 導入ロードマップ
| フェーズ | 期間 | 活動 |
|---|---|---|
| Phase 1: 学習 | 2 週間 | CDK 基礎・チュートリアル・プロトタイプ |
| Phase 2: パイロット | 1 ヶ月 | 小規模プロジェクトで実装・ベストプラクティス確立 |
| Phase 3: 展開 | 3 ヶ月 | 既存プロジェクトを CDK 化・Pipeline 構築 |
| Phase 4: 成熟化 | 継続 | Construct ライブラリ化・自動化推進 |
24. 実装チェックリスト
デプロイ前
- ✅
cdk initで プロジェクト初期化 - ✅
npm installで依存パッケージインストール - ✅
cdk bootstrapで Bootstrap スタック作成 - ✅
cdk synthで CloudFormation テンプレート生成確認 - ✅
cdk diffで変更差分確認 - ✅
npm testで ユニットテスト実行
デプロイ
- ✅
cdk deployで スタック作成・更新 - ✅ AWS コンソールで 動作確認
- ✅ CloudWatch ログ・メトリクス監視
###運用
- ✅
cdk watchで 自動更新設定(開発環境) - ✅
cdk destroyで リソース削除(不要時) - ✅ Git への コミット・Push
- ✅ CI/CD Pipeline 設定
25. よくあるエラーと対処法(補足)
| エラー | 原因 | 対処 |
|---|---|---|
Cannot find module '@aws-cdk/...' |
v1 インポート + v2 使用 | インポート文を aws-cdk-lib に変更 |
The specified SSM parameter does not exist |
Context 値参照失敗 | cdk context でリセット |
ERR! 404 Not Found - GET |
npm パッケージ未公開 | パッケージ名・バージョン確認 |
| AccessDenied: User is not authorized | IAM 権限不足 | AWS IAM ポリシー確認・追加 |
26. 参考文献
公式リソース
- AWS CDK Home
- CDK API Reference
- CDK Workshop
- CDK CLI Reference
- GitHub Repository - aws/aws-cdk
- Releases - CDK v2.233.0+(Mixins安定化)
- Construct Hub(5000+ Construct)
- AWS Solutions Constructs
マルチクラウド・マルチ言語
- CDKTF - CDK for Terraform(AWS/Azure/GCP)
- cdk8s - CDK for Kubernetes v2.x(任意のK8sクラスタ対応)
- CDK vs Terraform vs Pulumi(2026年比較)
- Pulumi Documentation(TypeScript/Python/Go対応)
セキュリティ・ポリシー
- cdk-nag GitHub(AWS Solutions/HIPAA/PCI-DSS チェック)
- AWS CDK Aspects(横断的ポリシー適用)
- Projen - Project Generator(プロジェクトテンプレート・メンテナンス自動化)
コミュニティリソース
まとめ
AWS CDK は AWS インフラを効率的にコード化する次世代ツール です。
主な利点
✅ プログラミング言語の表現力:ループ・条件分岐・モジュール化で DRY なコード ✅ 型安全性・IDE 補完:デプロイ前の誤り検出 ✅ 高レベルの抽象化:ベストプラクティスの自動適用 ✅ CloudFormation との完全互換:既存資産との融合 ✅ 豊富なエコシステム:Construct Hub で 5000+ の再利用可能コンポーネント
推奨される採用シーン
✅ 複数環境(dev/stg/prod)を統一管理したいチーム ✅ 社内標準のインフラパターンをライブラリ化したい企業 ✅ CI/CD パイプライン自体をコード化したい組織 ✅ AWS エコシステムに主力を置いている企業
学習パス
- 基礎(1-2 週間): Construct・Stack・App の理解
- 実践(2-4 週間): プロトタイププロジェクト・テスト実装
- 応用(1-3 ヶ月): Aspect・Pipeline・Custom Construct
- 成熟化(継続): Construct ライブラリ化・組織全体展開
本ドキュメントが CDK の習得と活用の一助となれば幸いです。
最終更新:2026-04-26 バージョン:v2.2(2026年3月CDK Mixins安定化、CDKTF/cdk8s拡張、Pulumi比較追加)