【AWS CDK】事前に用意した EIP を NAT Gateway に紐付けたい

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

テントの中から失礼します、CX事業本部のてんとタカハシです!

CDK で NAT Gateway を作成すると、自動で EIP が紐付いて便利なのですが、事前に用意した EIP を紐付けたいケースがあったりします。その時の対処法について調べたので、記事にしていきたいと思います。

環境

環境は下記の通りです。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H2

$ cdk --version
1.85.0 (build 5f44668)

普通に NAT Gateway を作成してみる

実装はこんな感じで。

lib/stack.ts

import * as cdk from '@aws-cdk/core';
import { CfnNatGateway, Vpc, SubnetType } from '@aws-cdk/aws-ec2';

export class ReassociateEipWithNatgatewayStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new Vpc(this, 'Vpc', {
      cidr: '10.0.0.0/16',
      enableDnsHostnames: true,
      enableDnsSupport: true,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'PublicSubnet',
          subnetType: SubnetType.PUBLIC,
        },
      ],
      natGateways: 2,
      maxAzs: 2,
    });
  }
}

これをデプロイすると、CDK が自動で EIP を作成して、NAT Gateway に紐付けてくれます。

解決方法

下記を参考にさせて頂きました。

GitHub - Elastic IP association for generated NAT in VPC #4067

NAT Gateway を作成した直後に、自動で紐付けられた EIP を削除しつつ、事前に用意した EIP で紐付け直す方法が紹介されています。natGatewayProvider を使用する方法も他のコメントで紹介されていますが、こちらはちょいと複雑そう。

では、まず EIP を手動で作成します。

次に、手動で作成した EIP の割り当て ID を cdk.json に埋め込みます。

cdk.json

{
  ...
  "context": {
    ...
    "eipAllocationIds": ["eipalloc-123456xxx", "eipalloc-234567xxx"]
  }
}

最後にスタックの実装にて、手動で作成した EIP を紐付け直します。

lib/stack.ts

export class ReassociateEipWithNatgatewayStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    ...
      maxAzs: 2,
    });
    
    const allocationIds: string[] = this.node.tryGetContext('eipAllocationIds');
    vpc.publicSubnets.forEach((subnet, index) => {
      // 各 Subnet から NAT Gateway を探す
      const natGateway = subnet.node.children.find(
        (child) => child.node.id == 'NATGateway'
      ) as CfnNatGateway;
      // 自動で作成された EIP を削除する
      subnet.node.tryRemoveChild('EIP');
      // 事前に作成した EIP を紐付ける
      natGateway.allocationId = allocationIds[index];
    });
  }
}

これでデプロイすると、自動で作成される EIP は削除され、手動で作成した EIP のみ存在する状態になります。

NAT Gateway の Elastic IP アドレスを見ると、手動で作成した EIP が紐付いていることを確認できます。

おわりに

この辺、少しややこしいので、今後のアプデで良い感じになってくれると嬉しいなと思います。

今回は以上になります。最後まで読んで頂きありがとうございました!