新機能 Multi-VPC ENI アタッチメントを検証しつつ他のサービスと比較する

記事タイトルとURLをコピーする

マネージドサービス部 佐竹です。
新機能としてリリースされた Multi-VPC ENI アタッチメントを検証してみましたので、ついでに PrivateLink あたりと比較していきたいと思います。

はじめに

Multi-VPC ENI アタッチメントが2023年10月26日にリリースされました。

aws.amazon.com

これは1つの EC2 インスタンスに、異なる VPC に存在する ENI (NIC) をアタッチすることが可能となったという新機能です。

これまでは同 VPC 内からのみ指定が可能だった

本機能がリリースされるまで、セカンダリとしてアタッチ可能な ENI は、同じ VPC 内である必要がありました。

これは以下の公式ドキュメントに One or more secondary private IPv4 addresses from the IPv4 address range of your VPC と記載があります。

docs.aws.amazon.com

今後は別 VPC の ENI も指定が可能に

新機能「Multi-VPC ENI アタッチメント」により、別 VPC からも ENI がアタッチ可能となりました。

このように、別々の VPC の ENI がアタッチされている EC2 インスタンスは、AWS 公式ドキュメントにおいては「dual-homed インスタンス」と呼ばれています。

Multi-VPC ENI アタッチメントの機能上の制限

ただし、いくつか機能上の制限が存在します。それは「同じ Availability Zone (AZ) であること」と「同じ AWS アカウント内であること」です。

本制限の原文は以下の引用の通りです。

You can launch an EC2 instance in one VPC and attach a secondary ENI from another VPC (but in the same Availability Zone) to the instance. This enables you to create multi-homed instances across VPCs with different networking and security configurations. You cannot create multi-homed instances across VPCs across different AWS accounts.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/scenarios-enis.html

設計フェーズにおいて、これらの制限事項には十分に注意ください。

VPC を跨ぐためのサービスを簡単に整理する

本機能を加えると、AWS の機能を用いて VPC を跨ぐことが可能となる機能が5つに増えた認識です。

  1. VPC Peering
  2. AWS PrivateLink
  3. AWS Transit Gateway
  4. Amazon VPC Lattice
  5. Multi-VPC ENI Attachments

これらのうち、Protocol が規定されている「Amazon VPC Lattice」を除いて以下で表形式にして比較してみます。

機能名 AWS アカウントの制限 Availability Zone の制限 VPC CIDR の制限 その他
VPC Peering 別アカウントと接続可 AZ の制限なし CIDR の重複不可 Subnet のルートテーブルの設定が必要
AWS PrivateLink 別アカウントと接続可 設定により AZ が異なる通信も可能*1 考慮する必要がない NLB の追加構築が必要
AWS Transit Gateway 別アカウントと接続可*2 AZ の制限なし*3 CIDR の重複不可 アタッチメントの分利用料が高額
Multi-VPC ENI Attachments 同アカウント内のみ アタッチ自体は同 AZ のみ CIDR の重複は回避可能*4 OS のルートテーブルの設定が必要

簡単に比較が終わったところで、以下で実際に動作検証を行った結果を構成図と共にご紹介します。

Multi-VPC ENI アタッチメント動作検証

今回、検証を行うにあたりまずは AWS 環境構成図を使って解説します。

前提となる AWS 環境構成図

上図のような既存構成があるとします。

ポイントとしては、AWS アカウントは同アカウント内で、VPC が CIDR 重複なしで複数ある状態としています。

これまで可能であったこと

先に記載した通り、以前より同 VPC 内の ENI を EC2 インスタンスのセカンダリ ENI としてアタッチすることが可能です。

画像では、赤の縦線で表しています。

Multi-VPC ENI アタッチメントで可能になったこと

今回 Multi-VPC ENI アタッチメントで、上図の通り「別 VPC の同 AZ の ENI をアタッチする」ことが可能となりました。

ただし、制限の通り別の AZ を指定することは不可能なため、AZ-1a の ENI をプライマリとして構築された EC2 インスタンスは、AZ-1c の ENI をセカンダリとして指定ができません。

動作検証用の構成

VPC を跨ぎつつ、同 AZ で ENI をアタッチするために、上図の通りの構成を準備しました。

AWS CLI による Multi-VPC ENI アタッチメント実装

この状態で、AWS CLI を用いて実装を行います。AWS CLI を利用するのは、今現在では AWS マネジメントコンソール上では同 VPC の ENI しか一覧に表示されないためです。

以下はコマンド例です。

aws ec2 attach-network-interface --device-index 1 --instance-id i-EC2-Side-A-1a --network-interface-id eni-ENI-Side-B-1a
aws ec2 attach-network-interface --device-index 1 --instance-id i-EC2-Side-B-1c --network-interface-id eni-ENI-Side-A-1c

引数の各 ID 部分は置き換えてご利用ください。

以下は実際の実行結果です。

$ aws ec2 attach-network-interface --device-index 1 --instance-id i-052a1ea437756a660 --network-interface-id eni-0b5d6778913783e57
{
    "AttachmentId": "eni-attach-04892b64abbe8883f",
    "NetworkCardIndex": 0
}

$ aws ec2 attach-network-interface --device-index 1 --instance-id i-0760487b7da4e2e7f --network-interface-id eni-02334a6e1f2214606
{
    "AttachmentId": "eni-attach-0a14d64f82c009462",
    "NetworkCardIndex": 0
}

無事に成功すると "AttachmentId" が返却されます。

マネジメントコンソールから、EC2 インスタンスの「Private IPv4 addresses」も合わせて確認します。画像の通りですが、「EC2 Side-A 1a」では「10.10.10.140」に加えて「10.20.20.140」がアタッチされていることがわかります。

そしてここまで完了すると、上図の通り VPC を跨いで ENI がアタッチされた「dual-homed インスタンス」がそれぞれの AZ ごとに完成します。

接続確認

この状況で、左上にある「EC2 Side-A 1a 10.10.10.140」から右下にある「EC2 Side-B 1c 10.20.20.150」への通信とその逆をそれぞれ検証します。

念のためですが、ENI を EC2 インスタンスにアタッチ後は、追加された ENI が正しく認識されるよう OS を再起動させています。

なお、各 Subnet のルートテーブルの設定ですが「local」の経路が各 ENI ごとにそれぞれ作用するため、本構成においてはルートテーブルの設定を編集することなく疎通が可能です。

① 「ENI Side-B 1a 10.20.20.140」を経由した Side-A から Side-B

まずは「EC2 Side-A 1a 10.10.10.140」に Session Manager でアクセスし、「EC2 Side-B 1c 10.20.20.150」へ疎通確認してみます。

方向としては、この図の左上から右下への矢印です。

参考まで、先に networkctl statusifconfig , ip route のコマンドの結果をそれぞれ掲載しておきます。Amazon Linux 2023 を利用していますが、特に OS では設定を変更しておらずデフォルトのままです。

networkctl status
sh-5.2$ networkctl status
●          State: routable
    Online state: online
         Address: 10.10.10.140 on ens5
                  10.20.20.140 on ens6
                  fe80::471:74ff:fe82:ed5 on ens5
                  fe80::4a8:d1ff:fe54:aacd on ens6
         Gateway: 10.10.10.129 on ens5
                  10.20.20.129 on ens6
             DNS: 10.10.10.2
                  10.20.20.2
  Search Domains: ap-northeast-1.compute.internal
ifconfig
sh-5.2$ ifconfig
ens5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 10.10.10.140  netmask 255.255.255.240  broadcast 10.10.10.143
        inet6 fe80::471:74ff:fe82:ed5  prefixlen 64  scopeid 0x20<link>
        ether 06:71:74:82:0e:d5  txqueuelen 1000  (Ethernet)
        RX packets 68171  bytes 16505324 (15.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 67004  bytes 13341406 (12.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens6: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 10.20.20.140  netmask 255.255.255.240  broadcast 10.20.20.143
        inet6 fe80::4a8:d1ff:fe54:aacd  prefixlen 64  scopeid 0x20<link>
        ether 06:a8:d1:54:aa:cd  txqueuelen 1000  (Ethernet)
        RX packets 5235  bytes 678967 (663.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5488  bytes 555600 (542.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 12  bytes 1020 (1020.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12  bytes 1020 (1020.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ip route
sh-5.2$ ip route
default via 10.10.10.129 dev ens5 proto dhcp src 10.10.10.140 metric 512
default via 10.20.20.129 dev ens6 proto dhcp src 10.20.20.140 metric 522
10.10.10.2 via 10.10.10.129 dev ens5 proto dhcp src 10.10.10.140 metric 512
10.10.10.128/28 dev ens5 proto kernel scope link src 10.10.10.140 metric 512
10.10.10.129 dev ens5 proto dhcp scope link src 10.10.10.140 metric 512
10.20.20.2 via 10.20.20.129 dev ens6 proto dhcp src 10.20.20.140 metric 522
10.20.20.128/28 dev ens6 proto kernel scope link src 10.20.20.140 metric 522
10.20.20.129 dev ens6 proto dhcp scope link src 10.20.20.140 metric 522

この状態で ping 10.20.20.150 を実行してみます。

sh-5.2$ ping 10.20.20.150
PING 10.20.20.150 (10.20.20.150) 56(84) bytes of data.
^C
--- 10.20.20.150 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2091ms

疎通できませんでした。これはデフォルトでプライマリになっている ENI が優先されるためで、今回であれば「10.10.10.140 on ens5」が優先されているためです。

よって「ENI Side-B 1a 10.20.20.140」を指定した状態で再度 ping を実行してみます。

sh-5.2$ ping 10.20.20.150 -I 10.20.20.140
PING 10.20.20.150 (10.20.20.150) from 10.20.20.140 : 56(84) bytes of data.
64 bytes from 10.20.20.150: icmp_seq=1 ttl=127 time=1.93 ms
64 bytes from 10.20.20.150: icmp_seq=2 ttl=127 time=1.95 ms
64 bytes from 10.20.20.150: icmp_seq=3 ttl=127 time=1.96 ms
^C
--- 10.20.20.150 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.934/1.947/1.960/0.010 ms

今度は疎通できました。

このように、EC2 インスタンスではデフォストでプライマリの ENI が優先されるため、OS のルート設定によって疎通の可否が左右されてしまうわけです。

② 「ENI Side-B 1a 10.20.20.140」を経由した Side-B から Side-A

今度は先の反対の経路で、この図の右下から左上への矢印です。

この場合に、宛先として指定する IP アドレスは「10.20.20.140」そのものになります。

「10.20.20.140」は「EC2 Side-B 1c 10.20.20.150」に直接アタッチされているわけではないため、EC2 インスタンスはプライマリの ENI から疎通が可能です。

h-5.2$ ping 10.20.20.140
PING 10.20.20.140 (10.20.20.140) 56(84) bytes of data.
64 bytes from 10.20.20.140: icmp_seq=1 ttl=127 time=1.94 ms
64 bytes from 10.20.20.140: icmp_seq=2 ttl=127 time=1.93 ms
64 bytes from 10.20.20.140: icmp_seq=3 ttl=127 time=1.95 ms
^C
--- 10.20.20.140 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 1.932/1.939/1.951/0.008 ms

この通り、通常通りプライマリ ENI からの疎通が可能となっています。

実際に「EC2 Side-A 1a 10.10.10.140」が ping を受信できているのか sudo tcpdump icmp -i ens6 で確認も行いました。

ens6 (10.20.20.140) 側で、ping を受信できていることがわかります。

sh-5.2$ sudo tcpdump icmp -i ens6
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens6, link-type EN10MB (Ethernet), snapshot length 262144 bytes
05:12:08.557011 IP ip-10-20-20-150.ap-northeast-1.compute.internal > ip-10-20-20-140.ap-northeast-1.compute.internal: ICMP echo request, id 6, seq 1, length 64
05:12:08.557045 IP ip-10-20-20-140.ap-northeast-1.compute.internal > ip-10-20-20-150.ap-northeast-1.compute.internal: ICMP echo reply, id 6, seq 1, length 64
05:12:09.559053 IP ip-10-20-20-150.ap-northeast-1.compute.internal > ip-10-20-20-140.ap-northeast-1.compute.internal: ICMP echo request, id 6, seq 2, length 64
05:12:09.559086 IP ip-10-20-20-140.ap-northeast-1.compute.internal > ip-10-20-20-150.ap-northeast-1.compute.internal: ICMP echo reply, id 6, seq 2, length 64
05:12:10.560124 IP ip-10-20-20-150.ap-northeast-1.compute.internal > ip-10-20-20-140.ap-northeast-1.compute.internal: ICMP echo request, id 6, seq 3, length 64
05:12:10.560156 IP ip-10-20-20-140.ap-northeast-1.compute.internal > ip-10-20-20-150.ap-northeast-1.compute.internal: ICMP echo reply, id 6, seq 3, length 64
05:12:11.561165 IP ip-10-20-20-150.ap-northeast-1.compute.internal > ip-10-20-20-140.ap-northeast-1.compute.internal: ICMP echo request, id 6, seq 4, length 64
05:12:11.561196 IP ip-10-20-20-140.ap-northeast-1.compute.internal > ip-10-20-20-150.ap-northeast-1.compute.internal: ICMP echo reply, id 6, seq 4, length 64

そして②の構成は、後に改めて比較します PrivateLink の構成に似ています。

③ 「ENI Side-A 1c 10.10.10.150」を経由した Side-B から Side-A

参考までに、逆方向である「EC2 Side-B 1c 10.20.20.150」から「EC2 Side-A 1a 10.10.10.140」への通信も見ておきます。

方向としては、この図の右下から左上への矢印です。

sh-5.2$ ping 10.10.10.140 -I 10.10.10.150
PING 10.10.10.140 (10.10.10.140) from 10.10.10.150 : 56(84) bytes of data.
64 bytes from 10.10.10.140: icmp_seq=1 ttl=127 time=2.61 ms
64 bytes from 10.10.10.140: icmp_seq=2 ttl=127 time=1.99 ms
^C
--- 10.10.10.140 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 1.988/2.298/2.608/0.310 ms

先ほどと同様、ping の引数でセカンダリ ENI の「10.10.10.150」を指定することで疎通が可能です。

④ 「ENI Side-A 1c 10.10.10.150」を経由した Side-A から Side-B

先の図の左上から右下への矢印も確認します。

h-5.2$ ping 10.10.10.150
PING 10.10.10.150 (10.10.10.150) 56(84) bytes of data.
64 bytes from 10.10.10.150: icmp_seq=1 ttl=127 time=1.99 ms
64 bytes from 10.10.10.150: icmp_seq=2 ttl=127 time=1.99 ms
64 bytes from 10.10.10.150: icmp_seq=3 ttl=127 time=2.00 ms
^C
--- 10.10.10.150 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 1.985/1.990/1.997/0.005 ms

プライマリの ENI が利用されるため、通常通り疎通が可能でした。

これらの検証結果の通り、VPC を跨いでアタッチされたセカンダリ ENI はデフォルトで優先されないため、合わせて OS 上で適切な経路設計が追加で必要なことがわかります。

Multi-VPC ENI アタッチメントと PrivateLink を構成図上に並べて描いてみると、近い構成になることがわかります。

PrivateLink との比較

上図は上段が PrivateLink で、下段が Multi-VPC ENI アタッチメントです。

図の左側から右側に VPC を跨いで疎通したいと要望があった場合、PrivateLink で実装が可能なことはもちろんながら、NLB なしで Multi-VPC ENI アタッチメントでも実装が可能になります。「同一 AWS アカウント」且つ「同一 AZ」という制限はあるものの、要件に当てはまる場合は PrivateLink よりも安く実装できるでしょう。

加えて、PrivateLink よりも容易に「両方向の通信が可能」となる点もメリットとなります。

これを見るに、「同一 AWS アカウント」且つ「同一 AZ」においては Multi-VPC ENI アタッチメントが PrivateLink の代替案になる可能性はありそうです。

その他のサービスと比較して感じること

Transit Gateway との比較

Transit Gateway と比較して検討する場合を考えてみると、Transit Gateway を実装する場合には「TGW アタッチメント」の保持で費用が嵩んでしまいますが、Transit Gateway なしで VPC 間を簡易的に疎通させたい場合にも有用かと思われます。

VPC Peering との比較

同様に VPC Peering ですが、特に「一時的に共有を行い、不要となれば削除する」ような使い方においては、VPC や Subnet の経路設計に影響が出てしまう VPC Peering と比較してもお手軽さを感じます。

まとめ

本ブログでは、新機能である Multi-VPC ENI アタッチメントを検証しつつ、これまでのサービスとの比較検討を行ってみました。

また本機能の制限として「同じ Availability Zone であること」と「同じ AWS アカウント内であること」が前提の機能となっていることを紹介しました。

動作検証と共に、最後に PrivateLink との構成を比較検討しました。

今後、適切な利用ケースにおいて本機能が役立つ場合があるかも知れませんため、本機能を頭の片隅に置きつつネットワークの構成提案を今後も続けていきたいと思います。

それでは、またお会いしましょう。

*1:https://blog.serverworks.co.jp/configuration-for-enabling-communication-between-instances-in-different-availability-zones-using-aws-privatelink

*2:AWS Resource Access Manager によるリソース共有が必要

*3:各 AZ に TGW アタッチメントを作成する必要がある点に注意が必要

*4:OS 内で NAT 等を行えば IP の重複も回避が可能

佐竹 陽一 (Yoichi Satake) エンジニアブログの記事一覧はコチラ

マネージドサービス部所属。AWS資格全冠。2010年1月からAWSを利用してきています。2021-2022 AWS Ambassadors/2023 Japan AWS Top Engineers/2020-2023 All Certifications Engineers。AWSのコスト削減、最適化を得意としています。