はじめに

猫好きエンジニアの福田です。
人肌ならぬ猫肌が恋しくなる季節ですね。

さて、今回は CDKで既存のNAT GatewayにセカンダリIPを追加する方法をご紹介します。

背景

k6/jmeterなど --->  ALB ---> ECS(負荷試験対象) ---> NAT GW ---> 外部API

上記のような構成でECSの負荷試験を実施していた際、50,000リクエストを超えたあたりから
急激に処理できるリクエスト数が激減してしまいました。
調査すると、NAT Gatewayの同時接続数 55,000件の上限に引っかかっていることが判明しました。
異なるAZのサブネット側にNAT Gatewayを配置するなどで解消する方法もありますが、

Amazon が一意の送信先への同時接続をサポートする NAT ゲートウェイ機能を強化

2023/2/1 より、NAT Gatewayに複数のセカンダリIPアドレスを追加することで、同時接続数の上限を増やすことができるようになりましたので
今回は、CDKでVPCリソース作成時に自動的に作成されたNAT Gatewayに対して、セカンダリIPを追加する方法をご紹介します。

CDKで設定

以下のような感じでNAT Gatewayを取得、EIPを作成、紐付けすることで、セカンダリIPを設定することができます。

// VPC作成例
this.vpc = new ec2.Vpc(this.scope, vpcName, {
  cidr: '10.0.0.0/16',
  natGateways: 1,
  maxAzs: 2,
  subnetConfiguration: [ ... ]
  // ...
})

// ...

//
// 既存のNAT Gatewayを取得(複数件には未対応)
//
let natGateway: ec2.CfnNatGateway
const publicSubnets = this.vpc.selectSubnets({ subnetGroupName: 'public' })

for (let subnet of publicSubnets.subnets) {
  natGateway = subnet.node.children.find(child => child.node.id == 'NATGateway') as ec2.CfnNatGateway
  if (natGateway) break
}

if (natGateway) {
  // セカンダリ用のEIPを作成
  const name = this.createResourceName('nat-gw-secondary-eip-01')
  const secondaryEip01 = new ec2.CfnEIP(this.scope, name, {
    tags: [{
      key: 'Name', // AWSコンソール上に表示する名前
      value: name,
    }]
  })
  // EIPを紐付け
  natGateway.secondaryAllocationIds = [
    secondaryEip01.attrAllocationId,
  ]
}
# 差分の例
$ cdk diff

~省略~

Resources
[+] AWS::EC2::EIP my-project-nat-gw-secondary-eip-01 myprojectmatgwsecondaryeip01
[~] AWS::EC2::NatGateway my-project-vpc/publicSubnet1/NATGateway myprojectvpcpublicSubnet1NATGateway73C09016 
 └─ [+] SecondaryAllocationIds
     └─ [{"Fn::GetAtt":["myprojectmatgwsecondaryeip01","AllocationId"]}]
     
~省略~

まとめ

今回はNAT GatewayにセカンダリIPをCDKで追加する方法をご紹介しました。
NAT GatewayのIPでIP制限をしている場合、新規作成したIPも許可し忘れないようにご注意ください。