ちょっと話題の記事

[M5/C5] VPC ピアリングに隠された Nitro 世代 EC2 と PrivateLink の不思議な関係 

Nitro世代のインスタンスタイプであるM5/C5ではVPCエンドポイントの仕様に違いがあるという話です
2018.05.26

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

こんにちは、菊池です。

※ 2018年6月10日追記:i3.metalも同様の仕様であることを追記しました。最新の仕様は、公式ドキュメントの英語表記にてご確認ください。

先日、PrivateLinkを使ったVPCエンドポイント(インターフェースエンドポイント)について公式ドキュメントを見ていたところ、気になる記述を発見しました。

Interface Endpoint Properties and Limitations

To use interface endpoints, you need to be aware of their properties and current limitations:

  • An interface endpoint can be accessed through an AWS Direct Connect connection. It can also be accessed through an intra-region VPC peering connection from C5, i3.metal, and M5 instance types only. You cannot access an interface endpoint through an AWS VPN connection, an inter-region VPC peering connection, or an intra-region VPC peering connection from an instance type other than C5, i3.metal, or M5.

「C5、i3.metal および M5 インスタンスタイプのみからリージョン内 VPC ピア接続を介してアクセスできます。」

※ 2018年6月10日追記:i3.metalも同様の仕様であることを追記しました。最新の仕様は、公式ドキュメントの英語表記にてご確認ください。

つまり、VPCピアリングを経由したインターフェースエンドポイントの利用可否が、インスタンスタイプによって異なるということです。ここでアクセス可能とされる C5、M5インスタンスは、Nitro Systemというハイパーバイザーを搭載した最新世代のインスタンスタイプです。Nitro Systemについての詳細は以下を参照ください。

【レポート】 EC2仮想基盤の進化 (C5 Instances and the Evolution of Amazon EC2 Virtualization) #reinvent #CMP332

また、i3.metalは先日登場したばかりの、ハイパーバイザを用いないベアメタルインスタンスです。

[i3.metal] ついに登場!Amazon EC2 ベアメタルインスタンスが一般提供開始!

インスタンスタイプによってVPCコンポーネントへのアクセス可否が異なるという仕様は、把握していないと思わぬハマりどころになりそうです。

VPCピアリング経由でインターフェースエンドポイントにアクセスしてみる

実際に、以下のようにm5.largeとm4.largeのインスタンスを使って、VPCピアリングを経由したKinesis Streamsへのインターフェースエンドポイントへアクセスして試してみます。ドキュメントの通りであれば、m5.largeからのみアクセスできるはずです。

まずは、2つのVPCをピアリングします。

次に、片方のVPC(CIDR:10.0.0.0/16)にKinesis StreamsのVPCエンドポイントを作成しました。

VPCピアリング経由でのインターフェースエンドポイントの名前解決

インターフェースエンドポイント(PrivateLink)では、対象のAWSサービスのエンドポイントの名前解決で、VPC内のプライベートIPを返すことでアクセスできます。今回の場合、Kinesis Streamsのエンドポイントであるkinesis.ap-northeast-1.amazonaws.comの名前解決で取得するIPが、10.0.0.xxxになることとで、インターネットを経由しないプライベートな経路でのアクセスが可能です。

ということで、まずは2つのインスタンスからエンドポイントのIPを引いてみます。

  • m5.large
[ec2-user@ip-172-16-0-66 ~]$ curl http://169.254.169.254/latest/meta-data/instance-type
m5.large
[ec2-user@ip-172-16-0-66 ~]$ dig kinesis.ap-northeast-1.amazonaws.com @172.16.0.2

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.57.amzn1 <<>> kinesis.ap-northeast-1.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12763
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;kinesis.ap-northeast-1.amazonaws.com. IN A

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
;; ANSWER SECTION:
kinesis.ap-northeast-1.amazonaws.com. 23 IN A	54.240.225.127

;; Query time: 0 msec
;; SERVER: 172.16.0.2#53(172.16.0.2)
;; WHEN: Sat May 26 03:34:47 2018
;; MSG SIZE  rcvd: 70
  •  m4.large
[ec2-user@ip-172-16-0-104 ~]$ curl http://169.254.169.254/latest/meta-data/instance-type
m4.large
[ec2-user@ip-172-16-0-104 ~]$ dig kinesis.ap-northeast-1.amazonaws.com @172.16.0.2

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.57.amzn1 <<>> kinesis.ap-northeast-1.amazonaws.com
;; global options: +cmd
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40862
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;kinesis.ap-northeast-1.amazonaws.com. IN A

;; ANSWER SECTION:
kinesis.ap-northeast-1.amazonaws.com. 24 IN A	52.95.34.163

;; Query time: 2 msec
;; SERVER: 172.16.0.2#53(172.16.0.2)
;; WHEN: Sat May 26 03:36:34 2018
;; MSG SIZE  rcvd: 70

どちらも、PublicIPが取得されました。一方で、VPCエンドポイント固有のDNS名である、vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.comを引いてみます。

  • m5.large
[ec2-user@ip-172-16-0-66 ~]$ dig vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com @172.16.0.2

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.57.amzn1 <<>> vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com @172.16.0.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57515
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com. IN A

;; ANSWER SECTION:
vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com. 60 IN A 10.0.0.238

;; Query time: 32 msec
;; SERVER: 172.16.0.2#53(172.16.0.2)
;; WHEN: Sat May 26 04:28:12 2018
;; MSG SIZE  rcvd: 107
  • m4.large
[ec2-user@ip-172-16-0-104 ~]$ dig vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com @172.16.0.2

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.57.amzn1 <<>> vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1933
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com. IN A

;; ANSWER SECTION:
vpce-01168adb08a47a58c-oz584kry.kinesis.ap-northeast-1.vpce.amazonaws.com. 60 IN A 10.0.0.238

;; Query time: 5 msec
;; SERVER: 172.16.0.2#53(172.16.0.2)
;; WHEN: Sat May 26 03:37:01 2018
;; MSG SIZE  rcvd: 107

こちらは、どちらのインスタンスタイプでも、PrivateIPである10.0.0.238を取得できました。

インターフェースエンドポイントでは、VPC内のAmazon DNSがエンドポイントの名前解決でPrivateIPを返すことで実現されます。しかし、以下のようにAmazon DNSでは自VPC内からのみ利用可能なため、VPCピアリングを経由しての利用はできません。

そのため、EC2のあるVPCからの名前解決では、PublicにあるエンドポイントのIPを返してしまっているようです。これは、VPCピアリング間のDNS名前解決を有効にしても同様の結果でした。

エンドポイント独自のDNS名を使うことで、インターフェースエンドポイントへアクセスすることはできそうですが、それではCLIやSDKを使っての利用に支障があります。そこで、VPCピアリング経由でのAmazon DNSを使った名前解決を可能にするため、以下のようにSimpleADをDNSキャッシュサーバとして中継させる構成を利用します。

サクッとSimpleADを立ち上げ、そのIPをDNSとして設定します。

これで、再度kinesis.ap-northeast-1.amazonaws.comを引いてみます。

[ec2-user@ip-172-16-0-66 ~]$ curl http://169.254.169.254/latest/meta-data/instance-type
m5.large
[ec2-user@ip-172-16-0-66 ~]$ dig kinesis.ap-northeast-1.amazonaws.com @10.0.0.50

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.57.amzn1 <<>> kinesis.ap-northeast-1.amazonaws.com @10.0.0.50
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40181
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;kinesis.ap-northeast-1.amazonaws.com. IN A

;; ANSWER SECTION:
kinesis.ap-northeast-1.amazonaws.com. 60 IN A	10.0.0.238

;; Query time: 2 msec
;; SERVER: 10.0.0.50#53(10.0.0.50)
;; WHEN: Sat May 26 04:53:24 2018
;; MSG SIZE  rcvd: 81

VPCピアリング経由でkinesis.ap-northeast-1.amazonaws.comのインターフェースエンドポイントのIPが取得できました。

インターフェースエンドポイントにアクセスする

それでは、いよいよm5.large、m4.largeの各インスタンスからインターフェースエンドポイントにアクセスします。

  • m5.large
[ec2-user@ip-172-16-0-66 ~]$ curl http://169.254.169.254/latest/meta-data/instance-type
m5.large
[ec2-user@ip-172-16-0-66 ~]$ aws kinesis list-streams --region ap-northeast-1
{
    "StreamNames": []
}
  •  m4.large
[ec2-user@ip-172-16-0-104 ~]$ curl http://169.254.169.254/latest/meta-data/instance-type
m4.large
[ec2-user@ip-172-16-0-104 ~]$ aws kinesis list-streams --region ap-northeast-1

HTTPSConnectionPool(host='kinesis.ap-northeast-1.amazonaws.com', port=443): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<botocore.awsrequest.AWSHTTPSConnection object at 0x7f9f2b78d450>, 'Connection to kinesis.ap-northeast-1.amazonaws.com timed out. (connect timeout=60)'))

仕様通りの結果となりました!

m5.largeではKinesis Streamsへアクセスしレスポンスが取得できています。一方で、m4.largeのインスタンスからはアクセスできず、タイムアウトとなっています。

独自エンドポイント(エンドポイントサービス)の場合

これまでは、AWSのエンドポイントで試してみました。インターフェースエンドポイントではAWSサービスのエンドポイント以外に、独自のサービスも公開可能です。こちらでも同様に試してみました。

以下のように、別のVPCにNLB(Network Load Balancer)とEC2でWEBサーバを公開します。

エンドポイントサービスを公開し、エンドポイントを作成します。

作成されたエンドポイント名の名前を引いてみます。

[ec2-user@ip-172-16-0-66 ~]$ dig vpce-076d2b5f8871bc4ab-loqhn66m.vpce-svc-0dd0229a2b6117342.ap-northeast-1.vpce.amazonaws.com @172.16.0.2

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.57.amzn1 <<>> vpce-076d2b5f8871bc4ab-loqhn66m.vpce-svc-0dd0229a2b6117342.ap-northeast-1.vpce.amazonaws.com @172.16.0.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29193
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;vpce-076d2b5f8871bc4ab-loqhn66m.vpce-svc-0dd0229a2b6117342.ap-northeast-1.vpce.amazonaws.com. IN A

;; ANSWER SECTION:
vpce-076d2b5f8871bc4ab-loqhn66m.vpce-svc-0dd0229a2b6117342.ap-northeast-1.vpce.amazonaws.com. 60 IN A 10.0.0.122

;; Query time: 32 msec
;; SERVER: 172.16.0.2#53(172.16.0.2)
;; WHEN: Sat May 26 04:41:34 2018
;; MSG SIZE  rcvd: 126

こちらの場合は、完全に固有のエンドポイント名となり、Publicに名前を引いてもPrivateIPが取得できるため、名前解決に困ることはなさそうです。

では、エンドポイントサービスにアクセスしてみます。

  • m5.large
[ec2-user@ip-172-16-0-66 ~]$ curl http://169.254.169.254/latest/meta-data/instance-type
m5.large
[ec2-user@ip-172-16-0-66 ~]$ curl vpce-076d2b5f8871bc4ab-loqhn66m.vpce-svc-0dd0229a2b6117342.ap-northeast-1.vpce.amazonaws.com
Hello
  • m4.large
[ec2-user@ip-172-16-0-104 ~]$ curl http://169.254.169.254/latest/meta-data/instance-type
m4.large
[ec2-user@ip-172-16-0-104 ~]$ curl vpce-076d2b5f8871bc4ab-loqhn66m.vpce-svc-0dd0229a2b6117342.ap-northeast-1.vpce.amazonaws.com
curl: (7) Failed to connect to vpce-076d2b5f8871bc4ab-loqhn66m.vpce-svc-0dd0229a2b6117342.ap-northeast-1.vpce.amazonaws.com port 80: 接続がタイムアウトしました

こちらも、m5.largeではVPCピアリングを経由したインターフェースエンドポイントにアクセスができました。やはり、m4.largeではアクセスできない結果となっています。

まとめ

ドキュメントの記載を見つけたとき、そんな仕様があるのかと驚きました。Nitroハイパーバイザで動作するインスタンスでは、一部の制約から解放されるという動きがあるようです。

とはいえ、現時点では名前解決も含め、VPCピアリング経由でのインターフェースエンドポイントへのアクセスを実運用に持ち込むのは少しリスクを感じます。インスタンスの追加やインスタンスタイプの変更で、うっかりM5/C5以外を選択してしまうのと、設計が破綻してしまうようなこともあり得るからです。

一方で、今後さらに新しいインスタンスタイプが登場し、あらゆるインスタンスタイプでNitroハイパーバイザが一般化すると、現状あるVPCの多くの制約が取り払われて行くのではないかと期待が持てる仕様と思います。