AWS CDK で EIP リソースを明示的に定義しつつ NAT Gateway で使用する構成を実装してみた
こんにちは、製造ビジネステクノロジー部の若槻です。
NAT Gateway をパブリックサブネットに作成すると Elastic IP Address が NAT Gateway に自動的に割り当てられます。これにより VPC 内のリソースからインターネットへのアクセスが可能になり、またその際のパブリック IP アドレスも固定することができます。
今回は、AWS CDK で Elastic IP Address のリソースを明示的に定義しつつ NAT Gateway で使用する構成を実装してみました。なお、VPC 内に作成する NAT Gateway は一つのみとします。
やってみた
そもそも Elastic IP Address のリソースを明示的に定義したい理由は以下になります。
- Elastic IP Address を作成していることを明示的に示したい
- Elastic IP Address のパブリック IP アドレスを簡単に出力したい
CDK コード
前述の理由を満たす最もシンプルな CDK コードは以下のようになりました。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
export class MainStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: cdk.StackProps) {
super(scope, id, props);
// Elastic IP の作成
const eip = new ec2.CfnEIP(this, 'EIP');
// VPC の作成
new ec2.Vpc(this, 'VPC', {
maxAzs: 2, // 開発環境のため 2 AZ のみ使用
natGateways: 1, // 開発環境のため NAT Gateway は 1 つのみ作成
natGatewayProvider: ec2.NatProvider.gateway({
eipAllocationIds: [eip.attrAllocationId],
}),
subnetConfiguration: [
{
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
],
});
// Elastic IP アドレスの出力
new cdk.CfnOutput(this, 'EIPAddress', {
value: eip.ref,
});
}
}
上記をデプロイすると、Elastic IP Address と単一の NAT Gateway が作成されました。
また、Elastic IP Address のパブリック IP アドレスが出力されました。
EC2 のマネジメントコンソールを確認すると、それぞれ CloudFormation で作成された NAT Gateway に Elastic IP Address が割り当てられていることが確認できます。
VPC Construct 単体で NAT Gateway を作成した場合は?
VPC Construct 単体で NAT Gateway を作成した場合にも Elastic IP Address は自動的に作成されて割り当てられますが、Elastic IP Address を出力したい場合に VPC からの EIP リソースの取得が下記のようにあまりスマートにできないのでおすすめできません。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
export class MainStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: cdk.StackProps) {
super(scope, id, props);
// VPC の作成
const vpc = new ec2.Vpc(this, 'VPC', {
maxAzs: 2, // 開発環境のため 2 AZ のみ使用
natGateways: 1, // 開発環境のため NAT Gateway は 1 つのみ作成
subnetConfiguration: [
{
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
],
});
// VPC から EIP リソースの取得
const natGatewayEip = vpc.publicSubnets[0].node.findChild(
'EIP'
) as ec2.CfnEIP;
// Elastic IP アドレスの出力
new cdk.CfnOutput(this, 'NatGatewayEip', {
value: natGatewayEip.attrPublicIp,
});
}
}
だめだった方法
はじめ次のような CDK コードで実装しようとしたが、独立して作成された 2 つ目の NAT Gateway の方に Elastic IP Address が割り当てられてしまい、意図通りにいきませんでした。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
export class MainStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: cdk.StackProps) {
super(scope, id, props);
// VPC の作成
const vpc = new ec2.Vpc(this, 'VPC', {
maxAzs: 2, // 開発環境のため 2 AZ のみ使用
natGateways: 1, // 開発環境のため NAT Gateway は 1 つのみ
subnetConfiguration: [
{
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
],
});
// Elastic IP の作成(NAT Gateway 用)
const eip = new ec2.CfnEIP(this, 'EIP', {
domain: 'vpc',
});
// 最初のパブリックサブネットを取得
const publicSubnet = vpc.publicSubnets[0];
// NAT Gateway の作成(固定 IP を使用)
const natGateway = new ec2.CfnNatGateway(this, 'NatGateway', {
subnetId: publicSubnet.subnetId,
allocationId: eip.attrAllocationId,
});
// NAT Gateway の依存関係を設定
natGateway.addDependency(eip);
// Elastic IP アドレスの出力
new cdk.CfnOutput(this, 'EIPAddress', {
value: eip.ref,
});
}
}
おわりに
AWS CDK で EIP リソースを明示的に定義しつつ NAT Gateway で使用する構成を実装してみました。
NAT Gateway に割り当てられた Elastic IP Address を簡単に出力したい場合におすすめの方法なので、ぜひ参考にしてみてください。
以上