はじめに
今回は、以下の記事で作成した「単一スタック」のテンプレートを、「ネストスタック」に書き換えてデプロイしてみました。
ネストスタックはデプロイ単位を「親スタックのみ」にまとめることができるのが特徴です。
クロススタックとの比較
| 項目 | クロススタック | ネストスタック |
|---|---|---|
| デプロイ単位 | 各スタック | 親スタックのみ |
| CloudFormation | 別スタック | 子スタックとして内包 |
| 依存関係 | Export/Import | 内部参照 |
| 再利用性 | 高い | 低い |
| 実務採用 | 多い | 少ない |
さっそく実装してみた
以下のような(ネスト)スタック構成になります。
App
└── AppStack
├── Network
├── Security
└── Compute
bin/app.tsを以下のコードで書き換えます。
bin/app.ts
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { AppStack } from '../lib/app-stack';
const app = new cdk.App();
new AppStack(app, 'AppStack');
lib/app-stack.ts(親スタック)を以下のコードで書き換えます。
lib/app-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { NetworkNestedStack } from './network-nested-stack';
import { SecurityNestedStack } from './security-nested-stack';
import { ComputeNestedStack } from './compute-nested-stack';
export class AppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// =========================
// Network(子スタック)
// =========================
const network = new NetworkNestedStack(this, 'NetworkNestedStack');
// =========================
// Security(子スタック)
// =========================
const security = new SecurityNestedStack(this, 'SecurityNestedStack', {
vpc: network.vpc,
});
// =========================
// Compute(子スタック)
// =========================
new ComputeNestedStack(this, 'ComputeNestedStack', {
vpc: network.vpc,
securityGroup: security.sg,
});
}
}
lib/network-nested-stack.tsを作成します。
lib/network-nested-stack.ts
import * as cdk from 'aws-cdk-lib';
import { NestedStack, NestedStackProps } from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
export class NetworkNestedStack extends NestedStack {
public readonly vpc: ec2.Vpc;
constructor(scope: Construct, id: string, props?: NestedStackProps) {
super(scope, id, props);
this.vpc = new ec2.Vpc(this, 'Vpc', {
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
maxAzs: 1,
subnetConfiguration: [
{
name: 'public-subnet',
subnetType: ec2.SubnetType.PUBLIC,
cidrMask: 24,
},
],
natGateways: 0,
});
}
}
lib/security-nested-stack.tsを作成します。
lib/security-nested-stack.ts
import * as cdk from 'aws-cdk-lib';
import { NestedStack, NestedStackProps } from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
interface Props extends NestedStackProps {
vpc: ec2.Vpc;
}
export class SecurityNestedStack extends NestedStack {
public readonly sg: ec2.SecurityGroup;
constructor(scope: Construct, id: string, props: Props) {
super(scope, id, props);
this.sg = new ec2.SecurityGroup(this, 'PublicSG', {
vpc: props.vpc,
description: 'Allow HTTP access',
allowAllOutbound: true,
});
this.sg.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
'Allow HTTP from anywhere'
);
}
}
lib/compute-nested-stack.tsを作成します。
lib/compute-nested-stack.ts
import * as cdk from 'aws-cdk-lib';
import { NestedStack, NestedStackProps } from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
interface Props extends NestedStackProps {
vpc: ec2.Vpc;
securityGroup: ec2.SecurityGroup;
}
export class ComputeNestedStack extends NestedStack {
constructor(scope: Construct, id: string, props: Props) {
super(scope, id, props);
const instance = new ec2.Instance(this, 'EC2', {
vpc: props.vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PUBLIC,
},
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
),
machineImage: ec2.MachineImage.latestAmazonLinux2023(),
securityGroup: props.securityGroup,
});
instance.addUserData(
'#!/bin/bash',
'dnf update -y',
'dnf install -y httpd',
'systemctl start httpd',
'systemctl enable httpd',
'echo "<h1>Hello from EC2!!!!!</h1>" > /var/www/html/index.html'
);
cdk.Tags.of(instance).add('Name', 'test-ec2');
}
}
デプロイ
親スタックのみをデプロイすればいいので、以下のコマンドを実行します。
zsh
cdk deploy AppStack
更新
デプロイと同様のコマンドを実行します。
削除
親スタックのみを削除すれば子スタックもすべて削除されます。
zsh
cdk destroy AppStack