コンストラクト・ツリー (Construct Tree)
AWS CDK を使って CloudFormation スタックを作成するとき、そのリソース構成は、論理的な コンストラクト (construct) のツリー構造によって表現します。 下記は、典型的な CDK アプリケーションにおけるコンストラクト・ツリー構造です。
App
、Stack
、Construct
はそれぞれ抽象度の異なるオブジェクトですが、すべて IConstruct インタフェース を実装したコンストラクトの一種です。
CDK アプリ―ケーションには、構成のエントリポイントとなる App
コンストラクト が 1 つあり、複数の Stack
コンストラクトを含むことができます。
Stack
コンストラクト は、その名の通り CloudFormation スタックを表現するコンストラクトです。
App
が複数の Stack
から構成されている場合、cdk deploy
コマンドでデプロイを実行したときに複数の CloudFormation スタックが生成されることになります。
cdk deploy <Stack名>
とすれば、特定のスタックのみをデプロイすることも可能です。
指定可能な Stack 名の一覧を確認したいときは、cdk ls
コマンドを使います。
Stack
コンストラクトはスタックを構成する入れ物であり、実際に AWS リソースを配置するには、Stack
内に具体的な AWS リソースを生成するための Construct
コンストラクト を配置します。
末端に配置する Construct
としては、CDK が提供する L1/L2/L3 コンストラクト(後述)や、cdk.Construct
を継承して作った独自のコンストラクトなどを指定します。
Construct
には、ほとんど CloudFormation のリソースそのままの低レベルなもの(例: CfnBucket
)もあれば、高度に抽象化されたもの(例: LambdaRestApi
)もあります。
Construct
クラスには、複数の CDN アプリで使えるように汎用化されたものもあり、それらをコンストラクト・ライブラリ (Construct Library) と呼びます。
CDN 自体が提供している s3.Bucket
もコンストラクト・ライブラリの一種です。
App
直下に独自の Construct
を配置して、その下に複数の Stack
を置くということもできます。
Construct
は柔軟な構成が可能ですが、Construct
を入れ子にするたびに、生成される AWS リソースの物理名も長くなっていくことに注意してください。
Stack
を入れ子構造にしたいときは、Stack
以下に NestedStack を配置します。L1/L2/L3 コンストラクト
CDK はコンストラクト・ライブラリとして、L1 ~ L3 までの異なる抽象度レベルの Construct
クラスを提供しています。
最初は、L2 あたりの Construct
をよく使うことになると思います。
- L1 コンストラクト (CloudFormation-only)
CfnBucket
のように、名前がCfn
で始まるもっとも低レベルなコンストラクトで、Cfn リソース とも呼ばれます。CloudFormation の仕様から自動生成されており、最新の AWS リソースであっても必ずこの L1 コンストラクトは提供されています。CloudFormation でリソースを定義するのと同様に詳細なプロパティ設定する必要があり、AWS リソースおよび CloudFormation に関する知識が必要です。- L2 コンストラクト (Curated)
- 1 つ以上の L1 コンストラクトをカプセル化し、デフォルトの設定やポリシーを提供したコンストラクトです。例えば、S3 バケットを生成するために
s3.Bucket
コンストラクトが提供されており、その実装内部では L1 コンストラクトのCfnBucket
が使われています。L1 コンストラクトのCfnBucket
で S3 バケットを作ろうとすると、bucketName
prop で世界で一意な物理バケット名を指定する必要がありますが、L2 コンストラクトのs3.Bucket
を使うと、コンストラクトにシンプルな論理名を指定するだけで済みます。また、L2 コンストラクトは便利メソッドを提供していることもあります(s3.Bucket
のaddLifeCycleRule()
など)。 - L3 コンストラクト (Patterns)
- 複数の L1、L2 コンストラクトを組み合わせて作られた、特定のユースケースを実現するためのコンストラクトです。例えば、API Gateway と Lambda 関数の組み合わせを簡単に定義する
aws-apigateway.LambdaRestApi
コンストラクトなどがあります。
コンストラクトの階層を作る
コンストラクトの入れ子構造を作るには、各種コンストラクトのコンストラクタ(ややこしい^^;)の 第1引数 で親となるコンストラクトを指定します。
この例では、s3.Bucket
コンストラクトの第1引数で this
、つまり、MyAppStack
コンストラクトを指定しています。
さらに、この MyAppStack
をインスタンス化するときは、その親コンストラクトとして、CDK アプリのエントリポイントである App
コンストラクトを指定します。
これらによって、次のようなコンストラクト・ツリーが作られたことになります。
ちなみに、App
はトップレベルのコンストラクトなので、そのコンストラクタには親コンストラクトを指定するパラメーターはありません(参考: class App)。
通常、コンストラクトのコンストラクタの 第2引数 では、そのコンストラクトの論理 ID を指定します。 この ID はそのコンストラクト階層の中で一意であれば十分なので、CDK アプリ内で意味が通じる程度にシンプルな名前を付けるようにします。
第3引数 は、コンストラクトごとの設定情報である props オブジェクトを指定します。
例えば、s3.Bucket
コンストラクトの場合は、s3.BucketProps オブジェクトを渡すことで、S3 バケットの設定を行うことができます(例: { versioned: true }
)。
多くの場合、props オブジェクトの多くのプロパティは省略可能であり、第3引数の指定自体を省略できるコンストラクトもあります(s3.Bucket
もそのひとつです)。