これは AWS CDK v2 開発者ガイドです。旧版の CDK v1 は 2022 年 6 月 1 日にメンテナンスを開始し、2023 年 6 月 1 日にサポートを終了しました。
AWS CDK スタックの概要
AWS CDK スタックはデプロイの最小単位です。これは、CDK コンストラクトを使用して定義する AWS リソースのコレクションを表します。CDK アプリケーションをデプロイすると、CDK スタック内のリソースは AWS CloudFormation スタックとして一緒にデプロイされます。AWS CloudFormation スタックの詳細については、「AWS CloudFormation ユーザーガイド」の「AWS CloudFormation スタックを使用した AWS リソースの単一ユニットとしての管理」を参照してください。
スタックを定義するには、Stack
コンストラクトを拡張または継承します。以下の例は、スタックファイルと呼ばれる別のファイルで CDK スタックを定義するための一般的なパターンです。ここでは、Stack
クラスを拡張または継承し、id
、scope
、props
を受け入れるコンストラクターを定義します。次に、受け取った scope
、id
、props
を引数とする super
で、基底となる Stack
クラスのコンストラクターを呼び出します。
- TypeScript
-
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class MyCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define your constructs here
}
}
- JavaScript
-
const { Stack } = require('aws-cdk-lib');
class MyCdkStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Define your constructs here
}
}
module.exports = { MyCdkStack }
- Python
-
from aws_cdk import (
Stack,
)
from constructs import Construct
class MyCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Define your constructs here
- Java
-
package com.myorg;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
public class MyCdkStack extends Stack {
public MyCdkStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyCdkStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// Define your constructs here
}
}
- C#
-
using Amazon.CDK;
using Constructs;
namespace MyCdk
{
public class MyCdkStack : Stack
{
internal MyCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
// Define your constructs here
}
}
}
- Go
-
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type CdkDemoAppStackProps struct {
awscdk.StackProps
}
func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// The code that defines your stack goes here
return stack
}
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
NewCdkDemoAppStack(app, "CdkDemoAppStack", &CdkDemoAppStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
//...
前の例では、スタックのみを定義しています。スタックを作成するには、CDK アプリのコンテキスト内でインスタンス化する必要があります。一般的なパターンは、CDK アプリケーションを定義し、アプリケーションファイルと呼ばれる別のファイルでスタックを初期化することです。
以下は、MyCdkStack
という名前の CDK スタックを作成する例です。ここでは、CDK アプリケーションが作成され、アプリケーションのコンテキストで MyCdkStack
がインスタンス化されます。
- TypeScript
-
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MyCdkStack } from '../lib/my-cdk-stack';
const app = new cdk.App();
new MyCdkStack(app, 'MyCdkStack', {
});
- JavaScript
-
#!/usr/bin/env node
const cdk = require('aws-cdk-lib');
const { MyCdkStack } = require('../lib/my-cdk-stack');
const app = new cdk.App();
new MyCdkStack(app, 'MyCdkStack', {
});
- Python
-
app.py
にあります
#!/usr/bin/env python3
import os
import aws_cdk as cdk
from my_cdk.my_cdk_stack import MyCdkStack
app = cdk.App()
MyCdkStack(app, "MyCdkStack",)
app.synth()
- Java
-
package com.myorg;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.StackProps;
import java.util.Arrays;
public class MyCdkApp {
public static void main(final String[] args) {
App app = new App();
new MyCdkStack(app, "MyCdkStack", StackProps.builder()
.build());
app.synth();
}
}
- C#
-
using Amazon.CDK;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MyCdk
{
sealed class Program
{
public static void Main(string[] args)
{
var app = new App();
new MyCdkStack(app, "MyCdkStack", new StackProps
{});
app.Synth();
}
}
}
- Go
-
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
// ...
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
NewMyCdkStack(app, "MyCdkStack", &MyCdkStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
// ...
以下の例では、2 つのスタックを含む CDK アプリケーションを作成します。
- TypeScript
-
const app = new App();
new MyFirstStack(app, 'stack1');
new MySecondStack(app, 'stack2');
app.synth();
- JavaScript
-
const app = new App();
new MyFirstStack(app, 'stack1');
new MySecondStack(app, 'stack2');
app.synth();
- Python
-
app = App()
MyFirstStack(app, 'stack1')
MySecondStack(app, 'stack2')
app.synth()
- Java
-
App app = new App();
new MyFirstStack(app, "stack1");
new MySecondStack(app, "stack2");
app.synth();
- C#
-
var app = new App();
new MyFirstStack(app, "stack1");
new MySecondStack(app, "stack2");
app.Synth();
- Go
-
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type MyFirstStackProps struct {
awscdk.StackProps
}
func NewMyFirstStack(scope constructs.Construct, id string, props *MyFirstStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
myFirstStack := awscdk.NewStack(scope, &id, &sprops)
// The code that defines your stack goes here
return myFirstStack
}
type MySecondStackProps struct {
awscdk.StackProps
}
func NewMySecondStack(scope constructs.Construct, id string, props *MySecondStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
mySecondStack := awscdk.NewStack(scope, &id, &sprops)
// The code that defines your stack goes here
return mySecondStack
}
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
NewMyFirstStack(app, "MyFirstStack", &MyFirstStackProps{
awscdk.StackProps{
Env: env(),
},
})
NewMySecondStack(app, "MySecondStack", &MySecondStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
// ...
スタック API について
Stack
オブジェクトには、以下のような豊富な API が用意されています。
-
Stack.of(construct)
– コンストラクトが定義されているスタックを返す静的メソッド。これは、再利用可能なコンストラクト内からスタックを操作する必要がある場合に役立ちます。スタックがスコープ内で見つからない場合、呼び出しは失敗します。
-
stack.stackName
(Python: stack_name
) — スタックの物理名を返します。前述のように、すべての AWS CDK スタックには、合成中に AWS CDK が解決できる物理名があります。
-
stack.region
および stack.account
— このスタックがデプロイされる AWS リージョンとアカウントをそれぞれ返します。これらのプロパティは、以下のいずれかの値を返します。
スタックの環境の決定方法については、「AWS CDK の環境」を参照してください。
-
stack.addDependency(stack)
(Python: stack.add_dependency(stack)
) – 2 つのスタック間の依存関係の順序を明示的に定義するために使用できます。この順序は、複数のスタックを一度にデプロイするときに cdk
deploy コマンドによって考慮されます。
-
stack.tags
– スタックレベルのタグを追加または削除するために使用できる TagManager を返します。このタグマネージャーは、スタック内のすべてのリソースにタグを付け、AWS CloudFormation を通してスタックを作成した場合は、スタック自体にもタグを付けます。
-
stack.partition
、stack.urlSuffix
(Python: url_suffix
)、stack.stackId
(Python: stack_id
)、および stack.notificationArn
(Python: notification_arn
) – { "Ref": "AWS::Partition" }
など、それぞれの AWS CloudFormation 擬似パラメータに解決されるトークンを返します。これらのトークンは、AWS CDK フレームワークがクロススタック参照を識別できるように、特定のスタックオブジェクトに関連付けられます。
-
stack.availabilityZones
(Python: availability_zones
) – このスタックがデプロイされている環境で使用可能なアベイラビリティーゾーンのセットを返します。環境に依存しないスタックの場合、これは常に 2 つのアベイラビリティーゾーンを持つ配列を返します。環境固有のスタックの場合、AWS CDK は環境をクエリし、指定したリージョンで使用できるアベイラビリティーゾーンの正確なセットを返します。
-
stack.parseArn(arn)
および stack.formatArn(comps)
(Python: parse_arn
、format_arn
) — Amazon リソースネーム (ARN) の操作に使用できます。
-
stack.toJsonString(obj)
(Python: to_json_string
) – AWS CloudFormation テンプレートに埋め込むことができる JSON 文字列として任意のオブジェクトをフォーマットするために使用できます。オブジェクトにはトークン、属性、参照を含めることができ、これらはデプロイ中にのみ解決されます。
-
stack.templateOptions
(Python: template_options
) – スタックの変換、説明、メタデータなどの AWS CloudFormation テンプレートオプションを指定します。
スタックの操作
スタックは、AWS CloudFormation スタックとして AWS 環境にデプロイされます。この環境は、特定の AWS アカウント と AWS リージョン を対象としています。
複数のスタックを持つアプリケーションの cdk synth
コマンドを実行すると、クラウドアセンブリにはスタックインスタンスごとに個別のテンプレートが含まれます。2 つのスタックが同じクラスのインスタンスであっても、AWS CDK は 2 つの個別のテンプレートとして出力します。
cdk synth
コマンドでスタック名を指定することで、各テンプレートを合成できます。以下の例は、stack1
のテンプレートを合成します。
$
cdk synth stack1
このアプローチは、テンプレートを複数回デプロイし、AWS CloudFormation パラメータを介してパラメータ化できるという、AWS CloudFormation テンプレートの通常の使用方法とは概念的に異なります。AWS CloudFormation パラメータは AWS CDK でも定義できますが、AWS CloudFormation パラメータがデプロイ時にしか解決されないため、通常は推奨されません。これは、コード内ではパラメータの値を判断できないことを意味します。
たとえば、パラメータ値に基づいてアプリにリソースを条件付きで含めるには、AWS CloudFormation 条件を設定し、そのリソースにタグを付ける必要があります。AWS CDK は、合成時に具体的なテンプレートが解決されるアプローチを取ります。したがって、if
ステートメントを使用して値をチェックし、リソースを定義するか、何らかの動作を適用するかを決定できます。
AWS CDK は、合成時に可能な限り多くの解決を提供し、プログラミング言語のイディオマティックで自然な使用を可能にします。
他のコンストラクトと同様に、スタックはまとめてグループに構成できます。以下のコードは、コントロールプレーン、データプレーン、モニタリングスタックの 3 つのスタックで構成されるサービスの例を示しています。サービスコンストラクトは 2 回定義されます。ベータ環境用に 1 回、本番環境用に 1 回です。
- TypeScript
-
import { App, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
interface EnvProps {
prod: boolean;
}
// imagine these stacks declare a bunch of related resources
class ControlPlane extends Stack {}
class DataPlane extends Stack {}
class Monitoring extends Stack {}
class MyService extends Construct {
constructor(scope: Construct, id: string, props?: EnvProps) {
super(scope, id);
// we might use the prod argument to change how the service is configured
new ControlPlane(this, "cp");
new DataPlane(this, "data");
new Monitoring(this, "mon"); }
}
const app = new App();
new MyService(app, "beta");
new MyService(app, "prod", { prod: true });
app.synth();
- JavaScript
-
const { App, Stack } = require('aws-cdk-lib');
const { Construct } = require('constructs');
// imagine these stacks declare a bunch of related resources
class ControlPlane extends Stack {}
class DataPlane extends Stack {}
class Monitoring extends Stack {}
class MyService extends Construct {
constructor(scope, id, props) {
super(scope, id);
// we might use the prod argument to change how the service is configured
new ControlPlane(this, "cp");
new DataPlane(this, "data");
new Monitoring(this, "mon");
}
}
const app = new App();
new MyService(app, "beta");
new MyService(app, "prod", { prod: true });
app.synth();
- Python
-
from aws_cdk import App, Stack
from constructs import Construct
# imagine these stacks declare a bunch of related resources
class ControlPlane(Stack): pass
class DataPlane(Stack): pass
class Monitoring(Stack): pass
class MyService(Construct):
def __init__(self, scope: Construct, id: str, *, prod=False):
super().__init__(scope, id)
# we might use the prod argument to change how the service is configured
ControlPlane(self, "cp")
DataPlane(self, "data")
Monitoring(self, "mon")
app = App();
MyService(app, "beta")
MyService(app, "prod", prod=True)
app.synth()
- Java
-
package com.myorg;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.constructs.Construct;
public class MyApp {
// imagine these stacks declare a bunch of related resources
static class ControlPlane extends Stack {
ControlPlane(Construct scope, String id) {
super(scope, id);
}
}
static class DataPlane extends Stack {
DataPlane(Construct scope, String id) {
super(scope, id);
}
}
static class Monitoring extends Stack {
Monitoring(Construct scope, String id) {
super(scope, id);
}
}
static class MyService extends Construct {
MyService(Construct scope, String id) {
this(scope, id, false);
}
MyService(Construct scope, String id, boolean prod) {
super(scope, id);
// we might use the prod argument to change how the service is configured
new ControlPlane(this, "cp");
new DataPlane(this, "data");
new Monitoring(this, "mon");
}
}
public static void main(final String argv[]) {
App app = new App();
new MyService(app, "beta");
new MyService(app, "prod", true);
app.synth();
}
}
- C#
-
using Amazon.CDK;
using Constructs;
// imagine these stacks declare a bunch of related resources
public class ControlPlane : Stack {
public ControlPlane(Construct scope, string id=null) : base(scope, id) { }
}
public class DataPlane : Stack {
public DataPlane(Construct scope, string id=null) : base(scope, id) { }
}
public class Monitoring : Stack
{
public Monitoring(Construct scope, string id=null) : base(scope, id) { }
}
public class MyService : Construct
{
public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id)
{
// we might use the prod argument to change how the service is configured
new ControlPlane(this, "cp");
new DataPlane(this, "data");
new Monitoring(this, "mon");
}
}
class Program
{
static void Main(string[] args)
{
var app = new App();
new MyService(app, "beta");
new MyService(app, "prod", prod: true);
app.Synth();
}
}
- Go
-
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type ControlPlaneStackProps struct {
awscdk.StackProps
}
func NewControlPlaneStack(scope constructs.Construct, id string, props *ControlPlaneStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
ControlPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops)
// The code that defines your stack goes here
return ControlPlaneStack
}
type DataPlaneStackProps struct {
awscdk.StackProps
}
func NewDataPlaneStack(scope constructs.Construct, id string, props *DataPlaneStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
DataPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops)
// The code that defines your stack goes here
return DataPlaneStack
}
type MonitoringStackProps struct {
awscdk.StackProps
}
func NewMonitoringStack(scope constructs.Construct, id string, props *MonitoringStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
MonitoringStack := awscdk.NewStack(scope, jsii.String(id), &sprops)
// The code that defines your stack goes here
return MonitoringStack
}
type MyServiceStackProps struct {
awscdk.StackProps
Prod bool
}
func NewMyServiceStack(scope constructs.Construct, id string, props *MyServiceStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
MyServiceStack := awscdk.NewStack(scope, jsii.String(id), &sprops)
NewControlPlaneStack(MyServiceStack, "cp", &ControlPlaneStackProps{
StackProps: sprops,
})
NewDataPlaneStack(MyServiceStack, "data", &DataPlaneStackProps{
StackProps: sprops,
})
NewMonitoringStack(MyServiceStack, "mon", &MonitoringStackProps{
StackProps: sprops,
})
return MyServiceStack
}
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
betaProps := MyServiceStackProps{
StackProps: awscdk.StackProps{
Env: env(),
},
Prod: false,
}
NewMyServiceStack(app, "beta", &betaProps)
prodProps := MyServiceStackProps{
StackProps: awscdk.StackProps{
Env: env(),
},
Prod: true,
}
NewMyServiceStack(app, "prod", &prodProps)
app.Synth(nil)
}
// ...
この AWS CDK アプリは最終的に環境ごとに 3 つずつ、合計 6 つのスタックで構成されます。
$
cdk ls
betacpDA8372D3
betadataE23DB2BA
betamon632BD457
prodcp187264CE
proddataF7378CE5
prodmon631A1083
AWS CloudFormation スタックの物理名は、ツリー内のスタックのコンストラクトパスに基づき、AWS CDK によって自動的に決定されます。デフォルトでは、スタックの名前は Stack
オブジェクトのコンストラクト ID から取得されます。ただし、以下のように stackName
prop (Python では stack_name
) を使用して、明示的な名前を指定できます。
- TypeScript
-
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
- JavaScript
-
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
- Python
-
MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name")
- Java
-
new MyStack(this, "not:a:stack:name", StackProps.builder()
.StackName("this-is-stack-name").build());
- C#
-
new MyStack(this, "not:a:stack:name", new StackProps
{
StackName = "this-is-stack-name"
});
ネストされたスタックの操作
ネストされたスタックは、親スタックと呼ばれる別のスタック内に作成する CDK スタックです。ネストされたスタックは、NestedStack
コンストラクトを使用して作成します。
ネストされたスタックを使用すると、複数のスタックにまたがってリソースを整理できます。ネストされたスタックは、スタックあたり 500 リソースという AWS CloudFormation の制限を回避する方法も提供します。ネストされたスタックは、それを含むスタック内の 1 つのリソースとしてカウントされます。そしてそれには、さらにネストされたスタックを含め、最大 500 個のリソースを含めることができます。
ネストされたスタックのスコープは、Stack
または NestedStack
コンストラクトである必要があります。ネストされたスタックは、親スタック内で字句的に宣言される必要はありません。ネストされたスタックをインスタンス化するときには、親スタックを最初のパラメータ (scope
) として渡すだけで済みます。この制限とは別に、ネストされたスタック内のコンストラクトの定義は、通常のスタックとまったく同じように機能します。
合成時に、ネストされたスタックは独自の AWS CloudFormation テンプレートに合成され、デプロイ時に AWS CDK ステージングバケットにアップロードされます。ネストされたスタックは親スタックにバインドされ、独立したデプロイアーティファクトとしては扱われません。これらは cdk list
で一覧表示されず、cdk
deploy
でデプロイすることもできません。
親スタックとネストされたスタック間の参照は、他のクロススタック参照と同様に、生成された AWS CloudFormation テンプレート内のスタックパラメータと出力に自動的に変換されます。
セキュリティ体制の変更は、ネストされたスタックのデプロイ前には表示されません。この情報は、最上位スタックにのみ表示されます。