目次

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+ 件)

https://constructs.dev/

npm search @aws-solutions-constructs/aws-ecs-fargate

npm install @aws-solutions-constructs/aws-ecs-fargate

18.2 AWS Solutions Constructs

業界別・ユースケース別の高レベル Construct

  • aws-apigateway-lambda
  • aws-ecs-fargate
  • aws-data-lake
  • aws-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 は AWS インフラを効率的にコード化する次世代ツール です。

主な利点

プログラミング言語の表現力:ループ・条件分岐・モジュール化で DRY なコード ✅ 型安全性・IDE 補完:デプロイ前の誤り検出 ✅ 高レベルの抽象化:ベストプラクティスの自動適用 ✅ CloudFormation との完全互換:既存資産との融合 ✅ 豊富なエコシステム:Construct Hub で 5000+ の再利用可能コンポーネント

推奨される採用シーン

✅ 複数環境(dev/stg/prod)を統一管理したいチーム ✅ 社内標準のインフラパターンをライブラリ化したい企業 ✅ CI/CD パイプライン自体をコード化したい組織 ✅ AWS エコシステムに主力を置いている企業

学習パス

  1. 基礎(1-2 週間): Construct・Stack・App の理解
  2. 実践(2-4 週間): プロトタイププロジェクト・テスト実装
  3. 応用(1-3 ヶ月): Aspect・Pipeline・Custom Construct
  4. 成熟化(継続): Construct ライブラリ化・組織全体展開

本ドキュメントが CDK の習得と活用の一助となれば幸いです。


最終更新:2026-04-26 バージョン:v2.2(2026年3月CDK Mixins安定化、CDKTF/cdk8s拡張、Pulumi比較追加)