Multi-VPC ENIを使って、複数VPCの通信を1つのNAT Instanceに集約してみた

先日サポートされた、Multi-VPC ENI Attachments の使い道を試してみました。SPOFを生むので、開発環境にお使いください(本番運用には向きません)

こんにちは、AWS事業本部の荒平(@0Air)です。

開発環境を複数持っていたりすると、NAT Gatewayがちょっと高く感じることはありませんか?
以下のように、令和の時代でも、NAT Instanceでコストを削減したりすることが可能です。

2023年10月26日、衝撃的な以下のアップデートが来ました。
要約すると、EC2に対してセカンダリENIのアタッチが別VPCに対しても可能になりました。

参考:Multi-VPC ENI Attachments

ケチな私は思い付きます。複数のVPCに立てていたNAT Instanceを集約して節約できるのではないかと。
本エントリは、Multi-VPC ENI Attachmentsを使って、別VPCからNAT Instanceへの通信を試してみたという内容です。

注意事項

  • 集約することにより、可用性・パフォーマンスの低下が考えられます。本番環境への適用は推奨しません
    • 本番環境では、これまで通りNAT Gatewayを利用しましょう
  • 本構成は、今後アンチパターンとなる可能性があります
  • 同一AZのENIである必要があります(Multi-VPC ENI Attachmentsの制約)

構成図

NATインスタンスのセカンダリENIを経由したNAT通信を行い、インターネットアクセスを目指します。
特に図中の赤線を検証してみました。

やってみた

1. NATインスタンスの作成

前述の「令和なのにNATインスタンスを手作りして使ってみた」を参考に、NATインスタンスを立てていきます。

今回は以下の条件で構築しました。

  • Amazon Linux 2 Kernel 5.10 AMI 2.0.20231020.1 x86_64 HVM gp2(ami-04f0680f68f076681
  • パブリックサブネットに配置しパブリックIP 割り当て
  • t3a.micro、gp3、8 GiB
  • SecuriryGroup
    • インバウンド:後続の手順で作成するクライアント用インスタンスからのすべてのトラフィック
    • アウトバウンド:0.0.0.0/0 へのすべてのトラフィック

IPフォワードの有効化を永続的に設定します。

[ec2-user@ip-10-0-5-130 ~]$ sudo sysctl -w net.ipv4.ip_forward=1 | sudo tee -a /etc/sysctl.conf
net.ipv4.ip_forward = 1

iptables-services を導入します。

sudo yum -y install iptables-services

iptables の保存を行います。

[ec2-user@ip-10-0-5-130 ~]$ sudo service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

再起動時に iptables を自動起動するよう、enableにしておきます。

[ec2-user@ip-10-0-5-130 ~]$ sudo systemctl enable iptables
Created symlink from /etc/systemd/system/basic.target.wants/iptables.service to /usr/lib/systemd/system/iptables.service.

2. NATインスタンスの送信元/送信先チェックの無効化

NATインスタンス用のEC2インスタンスを選択し、[ネットワーキング] - [ソース/宛先チェックを変更] から「停止」にチェックを入れて保存します。

3. セカンダリENIの作成・アタッチ

セカンダリに利用する別VPCのElastic Network Interface (ENI)を作成します。
ここでは、NATインスタンスと同一のAZとなるように選択します(図では、インスタンスがapne-1aのためこれを選択)

ENIのアタッチに関しては、マネジメントコンソールが未対応だったためコマンドで行いました。

aws ec2 attach-network-interface --device-index 1 --instance-id i-0123456789abcdef --network-interface-id eni-abcdef1234567890

CloudShellで上記コマンドを打ち、サクッとアタッチしていきます。

異なるアドレス体系のENIがアタッチできていることが確認できました。

セカンダリENIの「ソース/宛先チェック」も無効化しておきます
(ENIの画面では何故か、UI上チェックを外す動作が正のためご注意)

4. 別VPCに属するサブネットルートテーブルの変更

送信先 0.0.0.0/0 を前手順でアタッチしたセカンダリENIにルートを向けます。

5. クライアントEC2からインターネット疎通確認

別VPCのクライアントEC2からインターネットへ疎通が取れるかを確認します。
ベタですが、Google DNSにPingを送信し、リプライを確認しました。

ping 8.8.8.8

無事に別VPCのプライベートサブネットに立てたEC2インスタンスから、NAT Instanceを介してインターネットアクセスできました!

おわりに

複数VPCにそれぞれNAT Gatewayを立てていた場合や、開発環境などの重要度が低い場合はNAT Instanceへの集約をすることで若干のコストカットが図れそうです。

ただし前述の通り、SPOFを作ることになり運用面でも面倒になることが予想されるため、大手を広げてオススメはできません。

このエントリが誰かの助けになれば幸いです。
それでは、AWS事業本部 コンサルティング部の荒平(@0Air)がお送りしました!

余談

ルートテーブル指定のところで、インスタンスIDを指定するとENIが複数当たっているため怒られます。
しっかりENIを指定すると問題ありません。

Special Thanks