調査・レポート
2024/4/16調査
AWS CDKのレイヤー構造と選定ポイント
越川徹也 クラウド事業推進部・クラウドアーキテクト
本レポートの内容
- Infrastructure as Code(IaC)の1つである、AWS Cloud Development Kit(CDK)に存在するレイヤーの概念について記載する。
- 実際にCDKを使う上で各レイヤーをどのように使い分けていくべきかを併せて記載する。
本レポートの想定読者
- CDKの概要を理解しており、これから実際にコーディングを実施しようとしている方。
IaCとは
- IaCとはサーバーやネットワークなどあらゆるインフラリソースをコード化し、構築を自動化する手法。
- 一度、コード化をしてしまえば、そのテンプレートは他のプロジェクトや環境でも流用することができるため環境構築の工数を削減することが可能。
- また、同じコードであれば同一の環境が展開されるため、ヒューマンエラーなどの防止にもなる。
CDKとは
- IaCの一種でTypeScript、Pythonといったプログラミング言語でAWSリソースを定義してCloudFormationを通じてAWSアカウントへ展開できるフレームワーク。
- 2024年2月時点では、JavaScript、TypeScript、Python、Java、C# 、Go(開発者プレビュー)がサポートされている。
- Constructという形でAWSリソースを定義するが、CloudFormationのようにすべてのパラメータを指定せず、CDK内で事前定義されたパラメータを使用でき、L1、L2、L3の3種類がある。
- App>Stack>Constructというツリー構造を持ち、複数のCloudFormation Stackを1つのAppという形で管理できる。
ツリー構造の概念図
CDKのレイヤー説明
- AWS CDKには定義方法の抽象度に応じて、L1、L2、L3のConstructが存在する。
各レイヤーの概念図



各レイヤーの詳細
L1
概要
- CloudFormationリソースと1:1で対応していて、名前の接頭辞に「Cfn」が利用される。

ユースケース
- L2 Constructで対応してない場合や、L1のみで設定できるパラーメータがあった場合に使用。
メリット
- 各リソースのパラメータを細かく設定できる。
デメリット
- 1つずつリソースを定義する必要があるため、記載量が他のレイヤーと比較して多くなる。
L2
概要
- L1 Constructにデフォルト値や関数を加えて抽象化したもの。
- VPCではデフォルト(明示的に記載しなくても)でNAT Gatewayが作成されるなど、AWS側でベストプラクティスとされる設定が自動的に適用される。
- L1のように全てのパラメータを記載する必要がなく、ベストプラクティスに沿った既定値が定められているため、3レイヤーの中では主にL2が利用されるケースが多い。
-
また、L2では一部リソースでgrantメソッドが用意されており、本メソッドを利用することで用途に合ったIAMポリシーを簡単に付与できる。加えて、最小権限の原則に沿った形でIAMポリシーの付与ができるのもgrantメソッドの魅力である。以下の一例ではS3バケットを作成し、バケットへの読込権限を指定のIAMユーザに付与している。
Grantメソッドを利用したIAMポリシーの権限付与//S3バケットを作成 const bucket = new s3.Buket(this,"MyBucket"); //IAM Userを作成 const user = new iam.User(this,"MyUser"); //作成したIAMユーザに対してS3バケットの読込権限を付与 buket.grantRead(user);

ユースケース
- CDKのメリットを享受しつつ柔軟にリソース操作が行えるL2を利用するケースが多い。
- L1やL3のユースケースに合致しない場合に利用。
メリット
- 適度に抽象化されており、パラメータの設定もある程度行えるため柔軟性が高い。
デメリット
-
ただし、L2コンストラクタでは抽象化されている分、L2からは設定できないパラメータが存在する。その場合はL1に一度、型変換を行い設定値を上書きするなどの手段をとる必要がある。
-
以下の一例では、L2でVPCを作成した後、各サブネットをL1として再定義して、cidrを上書きしている。
※このように抽象化のレベルを変えて、ニーズに合った形でカスタマイズすることをCDKの世界ではエスケープハッチと呼ぶ。VPCのL2コンストラクタを利用した型変換の一例
//L2コンストラクタを利用してVpcを作成 const Vpc = new ec2.Vpc(this, 'Vpc', { cidr: '10.10.0.0/16', maxAzs: 1, natGateways: 2, subnetConfiguration: [ { //細かいcidrの指定はできない cidrMask: 24, name: 'Public', subnetType: ec2.SubnetType.PUBLIC, }, { //細かいcidrの指定はできない cidrMask: 20, name: 'Private', subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, }, ], }); //L1として再定義 // パブリックサブネット //Vpcオブジェクトの中からサブネット取り出して、L1として再定義する const L1PublicSubnet = Vpc.publicSubnets[0].node.defaultChild as ec2.CfnSubnet; //L1として再定義した上でcidrのプロパティを再設定する L1PublicSubnet.cidrBlock = "10.10.100.0/24"; // プライベートサブネット //Vpcオブジェクトの中からサブネット取り出して、L1として再定義する const L1PrivateSubnet = Vpc.privateSubnets[0].node.defaultChild as ec2.CfnSubnet; //L1として再定義した上でcidrのプロパティを再設定する L1PrivateSubnet.cidrBlock = "10.10.200.0/24"; }
L3
概要
- 複数のAWSリソースを組み合わせて、アーキテクチャパターンを更に抽象化したもの。(API Gateway-Lambda-DynamoDB等)
- AWSコンストラクタライブラリ内では「pattern」という接尾辞が付く。

ユースケース
- 構築したいアーキテクチャパターンがL3に存在し、各リソースに対するパラメータに対しても拘りがない場合。
- スピーディーに環境を構築したい場合。
メリット
- 構築したいアーキテクチャパターンがL3に存在する場合は簡単に環境を展開できる。
デメリット
- 3レイヤーの中で最も抽象度が高いため、設定できるパラメータの数も他のレイヤーに比べて限られている。
各レイヤーの選定ポイント
- 選定に迷った場合は、先ずはL2の採用が可能か検討することを推奨する。理由として、L2はL1より記載量が少なく、L3より柔軟にパラメータの設定ができるため。
- L3については、アーキテクチャのパターンがある程度決まっている場合に検討すると良い。
- L1については、L2では設定できないパラメータが存在する場合に利用するような補助的な役割で利用すると良い。
実際のコードを用いたサンプル
L1 Constructを利用してVPCを構築した場合

L2 Constructを利用してVPCを構築した場合

L3 Constructを利用したサンプル(ALB-ECSを利用した構成)

各レイヤーのまとめ
| 名称 | L1 | L2 | L3 |
|---|---|---|---|
| 概要 |
L1
|
L2
|
L3
|
| ユースケース |
L1
|
L2
|
L3
|
| メリット |
L1
|
L2
|
L3
|
| デメリット |
L1
|
L2
|
L3
|

